Added support for swift package dependencies with expo-target config#122
Added support for swift package dependencies with expo-target config#122Warabi1915181 wants to merge 1 commit intoEvanBacon:mainfrom
Conversation
revert formatting
| if (!existingProductDependency) { | ||
| const packageProduct = XCSwiftPackageProductDependency.create(project, { | ||
| productName: name, | ||
| package: reference.uuid as unknown as XCRemoteSwiftPackageReference, // in Xcode 16, this should be the UUID of the reference, not the whole object |
There was a problem hiding this comment.
Just wanted to flag, this changeset works great for my need (similarly need to pull in an SPM package into an Apple Target).
However, I am using Xcode 26 (with the latest 26.2+ Tahoe MacOS) and this flag here seems to encounter an error. This might be valid for Xcode 16 (I have not tested) but it might have gone back to "normal" in Xcode 26 - getting these errors (note, I injected some logs to debug).
[DEBUGGER] Replacing TargetName.entitlements with entitlements JSON from config
configureTargetWithSwiftPackages target PBXNativeTarget {
uuid: 'XXDDCEB16C218EC8877E08XX',
props: {
isa: 'PBXNativeTarget',
buildPhases: [],
buildRules: [],
dependencies: [],
buildConfigurationList: XCConfigurationList {
uuid: 'XXBAF26C8423445623FD65XX',
props: [Object]
},
name: 'TargetName',
productName: 'ProductName',
productReference: PBXFileReference {
uuid: 'XX0AB0FD90B6C986171471XX',
props: [Object]
},
productType: 'com.apple.product-type.app-extension'
}
}
configureTargetWithSwiftPackages props.swiftPackages?.forEach((pkg) => { {
name: 'PackageName',
repositoryURL: 'https://github.com/path/to.git',
kind: 'branch',
branch: 'main'
}
configureTargetWithSwiftPackages name PackageName
configureTargetWithSwiftPackages repositoryURL https://github.com/path/to.git
configureTargetWithSwiftPackages requirement { kind: 'branch', branch: 'main' }
configureTargetWithSwiftPackages reference not found, creating new one
configureTargetWithSwiftPackages project.rootObject.props.packageReferences not found, creating new one
configureTargetWithSwiftPackages existingProductDependency not found, creating new one
configureTargetWithSwiftPackages target.props.packageProductDependencies not found, creating new one
✖ Prebuild failed
Error: [ios.xcodeProjectBeta2]: withIosXcodeProjectBeta2BaseMod: Unable to serialize object: 'XX0514057567EC4CA0096CXX'
Error: [ios.xcodeProjectBeta2]: withIosXcodeProjectBeta2BaseMod: Unable to serialize object: 'XX0514057567EC4CA0096CXX'
at XCSwiftPackageProductDependency.toJSON (/Users/user/Desktop/project/node_modules/@bacons/xcode/src/api/AbstractObject.ts:203:17)
at XcodeProject.toJSON (/Users/user/Desktop/project/node_modules/@bacons/xcode/src/api/XcodeProject.ts:564:32)
at write (/Users/user/Desktop/project/node_modules/@bacons/apple-targets/build/with-bacons-xcode.js:71:66)
at action (/Users/user/Desktop/project/node_modules/@expo/config-plugins/src/plugins/createBaseMod.ts:90:17)
at async interceptingMod (/Users/user/Desktop/project/node_modules/@expo/config-plugins/src/plugins/withMod.ts:109:21)
at async evalModsAsync (/Users/user/Desktop/project/node_modules/@expo/config-plugins/src/plugins/mod-compiler.ts:190:25)
at async compileModsAsync (/Users/user/Desktop/project/node_modules/@expo/config-plugins/src/plugins/mod-compiler.ts:83:10)
at async configureProjectAsync (/Users/user/Desktop/project/node_modules/@expo/cli/build/src/prebuild/configureProjectAsync.js:92:14)
at async prebuildAsync (/Users/user/Desktop/project/node_modules/@expo/cli/build/src/prebuild/prebuildAsync.js:164:9)
The errors go away and the plugin changes run w/o issue if I make this:
package: referenceinstead of
package: reference.uuidas you have it.
|
See also #177 |
|
When I drafted the PR last year, I wanted to add basic support for SPM quickly so that people can start using it immediately. It is definitely in an immature state and I agree with EvanBacon that SPM should be handled with another config plugin. As the PR #177 to include |
Motivation
Currently we can only add swift packages inside Xcode. However, we need to manually do so after each
expo prebuild --clean. While Expo and React Native seem to be adding support to add SPM support in the near future, we still need a way to optionally add it to different apple targets.Execution
Pull request #44 is a promising contribution. It added integration with the swift package methods from the
@bacons/xcodeparser. However, it is lacking some of the version patterns that Xcode supports. It is also outdated with unresolved conflicts and a bug where aXCRemoteSwiftPackageReferenceis created regardless the package already exists or not. This pull request aims to solve all these issues.Test Plan
Test Procedure
Create a new expo project
npx create-expo-app@latest.Install the forked
apple-targetsscript. Since I did not upload my forked version, I build it locally and link it withnpm link.Create a new apple target (say, watch) using
npx create-target watch.In
targets/watch/expo-target.config.js, add theswiftPackages. Here, we use the Firebase iOS SDK (Swift) library as an example, as well as demonstrating the ability to add multiple products from the same package (FirebaseAuthandFirebaseCoreare two product dependencies fromfirebase-ios-sdkpackage).Note
One important note is that the
frameworksarray cannot be empty or undefined. When framework is empty, there is no longer a build phase for frameworks, which causes xcode failing to import the swift packages. I personally think it is neither a bug in this plugin config nor the xcode parser, because this behaviour is the same when we add a swift package to a project target without framework inside xcode -- it will not automatically create a build phase and link the swift packages. However, unlike xcode users who can easily add the build phase and link the libraries, Expo users may expect to handle all these automatically via a plugin config. This feels like a design choice so I would keep it minimal and decide not to fix this in this PR, although this problem is tightly coupled with the feature of this PR.Then run
npx expo prebuild -p ios --clean. Wait for the prebuild to finish. Runxed iosto open up the project in Xcode.Now you can see the Swift package dependencies are added to the project and the target.

A more rigorous test can be done by comparing the
.pbxprojfile from adding swift package inside XCode, and the file generated from this Expo config plugin.