Repository navigation
fix(ios): let pods depending on core resolve ReactNativeHealthkitCore_Private - #395
Merged
robertherber merged 2 commits intoOct 6, 2026
Conversation
🦋 Changeset detectedLatest commit: 37a2c04 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
enavermate
force-pushed
the
fix/core-private-module-include-path
branch
from
October 2, 2026 00:41
81d894c to
f8059bb
Compare
commit: |
robertherber
enabled auto-merge (squash)
October 6, 2026 19:43
FDOTPike
added a commit
to FDOTPike/athlete-kinetics
that referenced
this pull request
Oct 9, 2026
…(Xcode 27) The tester's second run on Xcode 27 (issue #38) confirmed the deployment-target fix and then failed in the ReactNativeHealthkit pod: "Unable to resolve module dependency: 'ReactNativeHealthkitCore_Private'". The pinned core (16.0.0) puts its ios/ directory, which holds that module map, on SWIFT_INCLUDE_PATHS for its own target only; with explicit module builds a dependent pod must resolve the module too. Upstream fixes this in 16.1.0 (kingstinct/react-native-healthkit#395). The Podfile post_install now adds the core's ios/ directory to SWIFT_INCLUDE_PATHS of the pods that depend on the core, as upstream does. It applies to exactly 16.0.0 and fails closed if the module map is missing. The binding's version is unchanged. Podfile.lock carries the new Podfile checksum. verify:native-config gains a check, watched failing with the call removed. typecheck and verify:native-config pass. Not yet run on any Mac: CI covers Xcode 26; Xcode 27 needs another run by the tester. Ledger: Entry 0201 output.
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 #391.
The problem
Since 16.0.0,
ReactNativeHealthkitCoreimports its private Objective-C module:The module map is made findable through the core pod's own
pod_target_xcconfig(SWIFT_INCLUDE_PATHS => $(PODS_TARGET_SRCROOT)/ios), which applies to that pod only. The core module is built without library evolution, so aninternal importdoes not hide the dependency from clients: whenever another pod loadsReactNativeHealthkitCore, that import has to resolve there too. With explicit module builds the dependency scanner ofReactNativeHealthkit(and ofReactNativeHealthkitHealthRecords) looks for it and fails:Reproduction
A blank Expo app (SDK 57, React Native 0.86.3, Xcode 27.0, iOS simulator),
@kingstinct/react-native-healthkit@16.0.0from npm:expo-build-propertiesiosuseFrameworks: "static"useFrameworks: "static"+buildReactNativeFromSource: trueThe last combination is common in apps using React Native Firebase, which is where I hit it. The monorepo's example app doesn't use it, which is likely why it didn't show up there.
The fix
The two pods that depend on core (
ReactNativeHealthkit,ReactNativeHealthkitHealthRecords) add the core'sios/directory to their ownSWIFT_INCLUDE_PATHS. The path is resolved the way Node resolves the dependency (require.resolve('@react-native-healthkit/core/package.json'), the same technique React Native's podspecs use) and written relative to$(PODS_TARGET_SRCROOT), so it works in the monorepo (../core/ios), a flatnode_modules(../../@react-native-healthkit/core/ios) and a nested one, without absolute paths in the generated xcconfig.I also tried switching the import to
@_implementationOnly import: it builds, but the compiler warns that it is unsafe without library evolution (#ImplementationOnlyDeprecated), so I kept yourinternal importand fixed the search path instead.Verification
isHealthDataAvailable()returnstrue.SWIFT_INCLUDE_PATHS = $(inherited) "$(PODS_TARGET_SRCROOT)/../core/ios".Note on health-records
ReactNativeHealthkitHealthRecordsfails with the same private-module error in that configuration, and this change gets it past it. In my app it then stops on a different, unrelated error:'AuthorizationRequestStatus.hpp' file not foundfrom its nitrogen bridge header. Both@kingstinct/react-native-healthkitand@react-native-healthkit/health-recordsgenerate a header with that name, in different namespaces. I left that out of this PR and can open a separate issue for it if that helps.