How to package after xcodebuild?
Hi, I've been building a package with node-swift that I distribute to my colleagues. They integrate it into their Electron app for macOS.
My package.json file had this, which worked well.
{
// ...
"files": [
"CHANGELOG.md",
"module/*",
".build/arm64-apple-macosx/release/Module.node",
".build/arm64-apple-macosx/release/lib*"
],
// ...
}
Now I have to add support for Mac with Intel silicon, i.e. x86_64 architecture.
Issue 19 in this project suggests adding "swift": { "builder": "xcode" } to the package.json file.
I've done that but now don't seem to have any dylib files under .build/
What other changes do I need to make please, to have a distributable package with support for x86_64 and arm64 architectures?
Same question: I'd like to build for the x86_64 architecture.
@kabiroberai any hints? 🙏
Hi and sorry, I have this working now but didn't post my solution. Here are my tips.
-
If you've ever opened your module project with Xcode then it seems to leave behind some preference and configuration files. Those seemed to make the Xcode build tools put the binaries in some other location than under the .build/ sub-directory. The fix is to delete any directories named xcuserdata/ anywhere under the .swiftpm/ directory before running the build. Also add xcuserdata/ to your .gitignore file.
-
Change the index.js for your module to point to the universal binary's location. It could be like .build/release/Module.framework/Versions/A/Module.node for example. Also change the files attribute in the module's package.json file.
-
The Universal Binary artefacts, generated by the Xcode build tools, seems to require a structure of symbolic links to be in place. Without the links Electron builder will fail to sign the app that imports the module. Those links will be created by Xcode build, in the .build release directory structure. However, when your module is installed into the Electron app project the symbolic links might get changed to copies of the link targets' files and directories. My fix was to add a post-install script that deletes the copies and rebuilds the required link structure. That applies to each of the Module.framework and NodeAPI.framework artefacts.
Cheers, Jim
Thanks @sjjhsjjh . For the time being I went with the Native Code and Electron: Swift (macOS) approach, with AI writing the boilerplate code needed.
@sjjhsjjh your approach regarding symlinks is indeed the best way to go if you're using the Xcode builder. The builder script should create symlinks automatically (such that .build/release/Module.node should be a symlink for .build/release/Module.framework/Versions/A/Module.node.) As long as you preserve the symlink structure when bundling, things should work fine. Are you still facing issues with this? cc @Jaarson this strategy should work for you as well.
I understand there's still non-trivial effort involved, I might do a spike on simplifying Electron-based packaging. In order to better understand the use cases here, could you folks please share which Electron bundler you're using?
Hi, In my case the bundler is Electron Builder https://www.electron.build/ I think the Node package manager might be more significant though. In my case pnpm https://pnpm.io/
Electron forge in my case