ARM support for Windows and Linux

The 64-bit ARM CPU architecture (aarch64) is on a tear right now. Not only has Apple Silicon pushed new boundaries in desktop performance but Amazon, NVIDIA and other companies have also developed their own high end ARM CPUs. Conveyor 12 completes our support for the AARCH64 CPU architecture by adding support for Windows and Linux ARM packages.

Conveyor has supported ARM architecture Mac apps from day one. Now we’ve added support for Windows and Linux as well. Because ecosystem support for ARM on these operating systems tends to be not as good as in the Mac sphere and trying to auto-generate ARM packages might yield broken apps, you have to opt in by specifying the machines explicitly:

app {
  machines = [ mac, windows.amd64, windows.aarch64, linux.amd64, linux.aarch64 ]

Most likely you’re using an app framework like Electron or the JVM, in which case Conveyor will download the ARM versions of the runtimes for you automatically. All you have to do is ensure you’re providing ARM versions of any native libraries you use. It’s easy to supply these by providing machine-specific inputs, like this:

app {
  inputs += generic-data.png
  // The paths can be anywhere you like.
  windows.aarch64.inputs += natives/win/aarch64/native-lib.dll
  windows.amd64.inputs += natives/win/x64/native-lib.dll
  linux.aarch64.inputs += natives/linux/aarch64/
  // etc ... 

Using inputs this way will place the architecture-specific files in the root of the app package, or for JVM apps, in the same place as the other native libraries in the bundled JVM. If you need them to go in a specific place you can do it by using the arrow operator, like this:

app {
  windows.aarch64.inputs += natives/win/aarch64/native-lib.dll -> libs/native-lib.dll

Now the app will be able to find the library inside the libs folder in the installation package. Note that on macOS you typically don’t need to move libraries around, as Conveyor will put them in the right directories to ensure they’re found by the dynamic linker automatically.

And that’s all it takes! On Windows the installer EXE is always an Intel binary that will run in emulation, but as it’s small and the actual install/download is done by Windows itself this doesn’t yield any performance impact. Having one binary avoids the risk of users accidentally ending up with the wrong one. Behind the scenes, the right architecture specific package will be downloaded and installed.

The generated HTML download page is of course optional as always, but if you use it, it will detect the user’s CPU architecture on Chrome based browsers and ensure that zip/deb links use the correct architecture. Linux users also get a small bit of shell they can copy into their terminals which will interpolate the right CPU architecture into the URL passed to wget.