Closed marcelblum closed 2 years ago
@marcelblum I think it just hasn't been updated yet, you should just set universal
as the architecture for forge / packager. You don't need to hop around between devices either, on a new enough macOS you can build for both arm or intel on the other architecture.
E.g. electron-forge package --arch=universal
should work (although iirc shows some weird terminal output 😆 )
@MarshallOfSound thanks for the clarification, I didn't realize I could build for either target on either arch now. But I still don't get how little details like arch-specific native module files are handled if everything was built on the same machine. Would I need to maintain 2 separate project folders each with their own separate node_nodules
, one for each arch? Or just add a bunch of special case code to handle modules that need it? Some native modules have their own package folder structure with different folders for different arch builds but not all do. For example a package that looks for its binaries under \node_modules\[name]\build\Release\[name].node
rather than say \node_modules\[name]\builds\[archname]\build\Release\[name].node
.
Wanted to report back in case anyone stumbles on this issue. I was able to build a universal binary with Electron Forge on an m1 mac relatively easily but there were 2 gotchas that aren't well documented, hopefully this helps someone else out there:
1) With Forge the only way to package/make for the universal
target is to use the command line option AFAICT. There is no way to specify it in the forge config, any packagerConfig.arch
value is ignored, and if you try to use packagerConfig.all
it will throw an error.
2) Native modules: My project was depending on a native module whose package folder structure did not use arch-specific folder names for its binary builds, presenting a problem in creating a universal binary that needed to contain 2 different arch versions of the package binaries in a way that the package could find them. In my case this package used the popular node-bindings to load its binaries. node-bindings
actually searches in a variety of folder name permutations for the binary, including one permutation that includes the platform and arch, see here. So I was able to simply rename the folder structure to include the different arch version binaries in folders node-bindings
automatically tries, without having to fork the package or do any clunky duping of the package to get it to work. So if you run into this issue, check if your native module dependency is using node-bindings
because that offers a painless solution.
Apologies for this basic question, but I'm feeling a bit in the dark as to how and when (at what point in the build/package process) to use this package especially in conjunction with the code signing, notarizing, and dmg-making steps, and which steps can only be done on one arch or the other (and the brief docs both here and at
electron-packager
are lacking). I useelectron-forge
and part of my ignorance here surely stems from how beautifully Forge handles all these steps automagically. Here's the best I can infer as to what my build process for a universal binary should be, but it feels clunky and I'd greatly appreciate it if anyone could correct me if/where this is a wrong or wildly inefficient way to go about this:npm run package
, skipping the signing and notarizing steps by leaving theosxSign
andosxNotarize
config options undefined, to create an unsigned Intel .app bundlenpm run package
, again without signing/notarizingmakeUniversalApp()
from this package, pointing to the unsigned Intel & Arm buildsI noticed some past comments mention the possibility of including a
universal
value for thearch
property inelectron-packager
, but the official docs do not mentionuniversal
as an valid option. Then there is theosxUniversal
property but it's not really clear how to use it, or at what point in my steps above.