0

We can easily compile a Swift script with:

$ swiftc /path/to/script.swift -o /path/to/binary

However, that only compiles for the current architecture.

$ lipo -archs /path/to/binary
arm64

I found some commands to build for multiple architectures, but they seem to require setting up a new project. I don’t want or need to do that yet, for now I just want to compile a single script file easily, hence swiftc. Is there a way to do this?

As a bonus, does Rosetta 2 need to be installed to generate universal binaries, or is it possible to make them without it?

user137369
  • 5,219
  • 5
  • 31
  • 54

1 Answers1

3

You would need to build the binary two times, for example, for a project that's targeting macOS, you would compile once with -target x86_64-apple-macos10.15 and the other one with -target arm64-apple-macos10.15.

After that, you would use lipo -create to stitch those together into a single file like this lipo -create <path/to/arm64-slice> <path/to/x86_64-slice> -output <path/to/universal/binary>.

This is how I did it:

➜  UniversalBinaryTest swiftc source.swift -target x86_64-apple-macos10.15 -o binary_x86-64
➜  UniversalBinaryTest lipo -archs binary_x86-64
x86_64
➜  UniversalBinaryTest swiftc source.swift -target arm64-apple-macos10.15 -o binary_arm64
➜  UniversalBinaryTest lipo -archs binary_arm64
arm64
➜  UniversalBinaryTest lipo -create binary_x86-64 binary_arm64 -output binary_universal
➜  UniversalBinaryTest lipo -archs binary_universal
x86_64 arm64

After all of that, you would probably want to re-sign the new binary.

Edit: Actually, it looks like lipo handles signing for you if both slices are signed:

➜  UniversalBinaryTest codesign -s - binary_x86-64
➜  UniversalBinaryTest codesign -vvv binary_x86-64
binary_x86-64: valid on disk
binary_x86-64: satisfies its Designated Requirement
➜  UniversalBinaryTest codesign -vvvvv binary_x86-64
binary_x86-64: valid on disk
binary_x86-64: satisfies its Designated Requirement
➜  UniversalBinaryTest codesign -s - binary_arm64
➜  UniversalBinaryTest lipo -create binary_x86-64 binary_arm64 -output binary_universal
➜  UniversalBinaryTest codesign -vvv binary_universal
binary_universal: valid on disk
binary_universal: satisfies its Designated Requirement
JustSomeGuy
  • 3,677
  • 1
  • 23
  • 31
  • Thank you. Do you know if Rosetta 2 needs to be installed to be able to generate the x86_64 version? – user137369 Feb 11 '22 at 19:01
  • 1
    I'm pretty sure you don't need rosetta to compile stuff, but you will need it to run. If the problem is that you are running in a CI environment and you are worried you might get hit with a UI prompt, you can use `softwareupdate --install-rosetta` to install it from terminal. – JustSomeGuy Feb 11 '22 at 19:04
  • “If the problem is that you are running in a CI environment”. Nope, I’m just thinking that all my apps are ARM or Universal and want to do a fresh install of macOS and not install Rosetta. But wanted to know if that would affect development. – user137369 Feb 11 '22 at 20:33