fix(ios): select an arch when exporting coverage from universal binaries - #6
Merged
Merged
Conversation
mikehardy
force-pushed
the
fix/ios-universal-arch-selection
branch
from
September 24, 2026 20:22
5f44027 to
58573f5
Compare
llvm-cov cannot read coverage from a universal (multi-arch) Mach-O without -arch, so a simulator build carrying both arm64 and x86_64 slices exported 0% LCOV. This is why consumers building universal simulator binaries (e.g. react-native-firebase) saw an ios-native flag stuck at 0%, while this repo's thin (ONLY_ACTIVE_ARCH=YES) e2e builds were unaffected. ios export/report/summary now: - auto-detect the app binary's slices via 'lipo -archs'; - pass -arch only for fat binaries, choosing the host arch when present else the first slice (thin binaries are unchanged); - accept an override via --arch <arch> or config ios.arch. Adds unit tests for the selection logic and documents the flag.
mikehardy
force-pushed
the
fix/ios-universal-arch-selection
branch
from
September 24, 2026 20:25
58573f5 to
f3afbb2
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6 +/- ##
============================================
+ Coverage 58.85% 59.54% +0.68%
Complexity 15 15
============================================
Files 22 22
Lines 1016 1048 +32
Branches 230 239 +9
============================================
+ Hits 598 624 +26
- Misses 346 352 +6
Partials 72 72
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Flip the static e2e cell to ONLY_ACTIVE_ARCH=NO so it produces a universal (arm64 + x86_64) simulator binary, exercising the new llvm-cov -arch selection in 'rn-coverage ios export'. If the arch fix regresses, that cell's export drops to 0% and the strict assert fails it — an in-repo regression guard at no extra CI cost (no new cell). The dynamic cell stays thin (ONLY_ACTIVE_ARCH=YES) to keep the primary cell fast. Adds a lipo-based assertion that the static binary is actually multi-arch so the guard can't silently degrade to thin.
Export resolveLlvmArch/buildArchArgs and add tests for detectBinaryArchs (mocked lipo), buildArchArgs, and resolveLlvmArch (override/config/auto) so the new arch-selection lines are covered by unit tests, not only by the universal e2e cell.
The app and WDA builds targeted "-destination id=<udid>", which intermittently fails on GitHub runners with "Unable to find a device matching the provided destination specifier" — a CoreSimulator availability race, even after the booted UDID is ready. A simulator is only needed to install and run (simctl + Appium), never to build for the iphonesimulator SDK, so build with "generic/platform=iOS Simulator" instead. This is the same device-agnostic build Detox uses in RNFB's e2e; the specific UDID is still used for install/launch. Complements the existing 'xcrun simctl list' availability workaround in ci.yml.
Collaborator
Author
|
🎉 This PR is included in version 0.2.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes queue item F3: consumers that build universal (multi-arch) iOS simulator binaries — notably react-native-firebase — see their
ios-nativeCodecov flag stuck at 0%, even with full adoption. RNGMA's tooling already documented the limitation:Root cause
llvm-cov(export/show/report) cannot read coverage from a universal Mach-O without an-archselector. A simulator build carrying botharm64andx86_64slices therefore exports empty LCOV.This repo's own e2e never hit the bug because its Xcode Debug build uses the default
ONLY_ACTIVE_ARCH=YES→ a thin binary (which is whye2e-ios-dynamicsits at ~90%). Consumers producing fat simulator binaries hit the 0% path.Fix
ios export,ios report, andios summarynow resolve an architecture before invokingllvm-cov:-archpassed (behavior unchanged).lipo -archs, select the host arch when present, else the first slice.--arch <arch>(CLI) orios.arch(config) always wins.Auto-detection means consumers get the fix for free on upgrade — no config change required. RNFB's
rn-coverage-ios-export.jsalready forwards extra args, so--archis available if they ever want to pin.In-repo dogfood / regression guard (now included)
The static e2e cell now builds with
ONLY_ACTIVE_ARCH=NO, producing a universal (arm64 + x86_64) simulator binary. This exercises the new arch-selection path in CI here: if the fix ever regresses, that cell's export drops to 0% and the strict assert (exit 2) fails the cell. Added alipo-based assertion that the static binary really is multi-arch so the guard can't silently degrade to thin. The dynamic (primary) cell stays thin to keep it fast — no new cell, no extra CI cost.Tests / validation
src/__tests__/arch-selection.test.ts(pure selection logic): thin→none, universal→host, host-absent→first slice, explicit override, blank-ignored. 52 tests / 6 suites pass (was 42/5).yarn typecheck,yarn lint,yarn prepare(build) pass;bash -n+shellcheck -S errorclean on the e2e script.lipo-backeddetectBinaryArchsverified against a real fat binary.npx @docs.page/cli check→ No documentation issues found.Follow-up (not in this PR)
react-native-coveragein RNFB + RNGMA and confirmios-nativeturns non-zero on their Codecov.