Swift Package Manager seemingly not supported
hesselbom opened this issue · 3 comments
Problem
After running npx expo prebuild --clean
with an Apple Watch target using EvanBacon/expo-apple-targets I tried adding Supabase as a Swift package. This worked, but when running npx expo prebuild
I get this error:
Error: [ios.xcodeProjectBeta2]: withIosXcodeProjectBeta2BaseMod: Unable to serialize object: 'AC9C55BA2BD8FD4500041977'
at PBXBuildFile.toJSON (.../node_modules/@bacons/xcode/build/api/AbstractObject.js:119:27)
at XcodeProject.toJSON (.../node_modules/@bacons/xcode/build/api/XcodeProject.js:195:38)
at write (.../node_modules/@bacons/apple-targets/build/withXcparse.js:68:66)
It seems like it gets messed up when with productRef
Context
ExpoModulesProvider.swift
which is a fileRef works correctly while Supabase
which is a productRef causes the error.
[file: project.pbxproj]
/* Begin PBXBuildFile section */
[...]
AC9C55BB2BD8FD4500041977 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = AC9C55BA2BD8FD4500041977 /* Supabase */; };
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
[...]
/* End PBXBuildFile section */
If I add a console.log
in AbstractObject's toJSON I can see that fileRef appears to be converted to PBXFileReference while productRef is just a string ("AC9C55BA2BD8FD4500041977" in this case) so my guess is that it never converts to a valid object.
Solution
I've tried looking through the code to see how to patch this, and hopefully also add the ability to add packages like this, but am unable to find where.
Please let me know if you need additional context.
Created a barebones reproduction repo here: https://github.com/hesselbom/xcode-spm-repro
Ok, actually found the issue for the error, looks like XCSwiftPackageProductDependency
and XCRemoteSwiftPackageReference
were missing from KNOWN_ISA
from this file:
Lines 135 to 141 in 0fba858
If I add them to the end of that list, like so:
[json.ISA.XCSwiftPackageProductDependency]: () =>
require("./XCSwiftPackageProductDependency")
.XCSwiftPackageProductDependency as typeof import("./XCSwiftPackageProductDependency").XCSwiftPackageProductDependency,
[json.ISA.XCRemoteSwiftPackageReference]: () =>
require("./XCRemoteSwiftPackageReference")
.XCRemoteSwiftPackageReference as typeof import("./XCRemoteSwiftPackageReference").XCRemoteSwiftPackageReference,
Then I don't get the error and the SPM package is still there in the Watch target, so it doesn't get overwritten. Although it changes:
AC9C55CD2BD92CD000041977 /* Supabase in Frameworks */ = {isa = PBXBuildFile; productRef = AC9C55CC2BD92CD000041977 /* Supabase */; };
into "null" name:
AC9C55CD2BD92CD000041977 /* null in Frameworks */ = {isa = PBXBuildFile; productRef = AC9C55CC2BD92CD000041977 /* XCSwiftPackageProductDependency */; };
But XCode seems to build with it regardless.
Found the issue with the null name, turns out "comments" doesn't account for productRef when looking for name. Here's my complete patch so far:
patches/@bacons+xcode+1.0.0-alpha.12.patch
diff --git a/node_modules/@bacons/xcode/build/api/XcodeProject.js b/node_modules/@bacons/xcode/build/api/XcodeProject.js
index 16e8daf..59cf212 100644
--- a/node_modules/@bacons/xcode/build/api/XcodeProject.js
+++ b/node_modules/@bacons/xcode/build/api/XcodeProject.js
@@ -84,6 +84,10 @@ const KNOWN_ISA = {
.PBXReferenceProxy,
[json.ISA.PBXRezBuildPhase]: () => require("./PBXSourcesBuildPhase")
.PBXRezBuildPhase,
+ [json.ISA.XCSwiftPackageProductDependency]: () => require("./XCSwiftPackageProductDependency")
+ .XCSwiftPackageProductDependency,
+ [json.ISA.XCRemoteSwiftPackageReference]: () => require("./XCRemoteSwiftPackageReference")
+ .XCRemoteSwiftPackageReference,
};
class XcodeProject extends Map {
constructor(filePath, props) {
diff --git a/node_modules/@bacons/xcode/build/json/comments.js b/node_modules/@bacons/xcode/build/json/comments.js
index 9c57be3..499e86c 100644
--- a/node_modules/@bacons/xcode/build/json/comments.js
+++ b/node_modules/@bacons/xcode/build/json/comments.js
@@ -32,7 +32,7 @@ function createReferenceList(project) {
}
function getPBXBuildFileComment(id, buildFile) {
const buildPhaseName = getBuildPhaseNameContainingFile(id) ?? "[missing build phase]";
- const name = getCommentForObject(buildFile.fileRef, objects[buildFile.fileRef]);
+ const name = getCommentForObject(buildFile.fileRef || buildFile.productRef, objects[buildFile.fileRef || buildFile.productRef]);
return `${name} in ${buildPhaseName}`;
}
function getCommentForObject(id, object) {
@@ -55,7 +55,7 @@ function createReferenceList(project) {
referenceCache[id] = getBuildPhaseName(object) ?? "";
}
else {
- referenceCache[id] = object.name ?? object.path ?? object.isa ?? null;
+ referenceCache[id] = object.name ?? object.productName ?? object.path ?? object.isa ?? null;
}
return referenceCache[id] ?? null;
}