Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Create universal binaries (fat archives) #77

Open
mstange opened this issue Feb 1, 2023 · 10 comments
Open

macOS: Create universal binaries (fat archives) #77

mstange opened this issue Feb 1, 2023 · 10 comments
Labels
feature request New feature or request

Comments

@mstange
Copy link

mstange commented Feb 1, 2023

macOS supports bundling both the x86_64 and the arm64 binary into a single file using lipo. It would be nice to do this by default so that mac users don't have to think about their architecture when picking which file to download.

@Gankra Gankra added the feature request New feature or request label Feb 1, 2023
@Gankra
Copy link
Contributor

Gankra commented Feb 1, 2023

Depends on #74, I assume?

Might ultimately want a flag to configure this, but I agree it would be good to do.

@mstange
Copy link
Author

mstange commented Feb 1, 2023

Compiling macOS-but-other-arch from macOS is trivial - just pass --target=aarch64-apple-darwin to cargo build. It's just compiling macOS builds from Linux that's hard.

@Gankra
Copy link
Contributor

Gankra commented Feb 1, 2023

At least on my x64 macbook pro you need to do

rustup target add aarch64-apple-darwin

Before

cargo build --target=aarch64-apple-darwin

will work. I'll definitely grant that's the most painless cross compile I've ever seen though.

@passcod
Copy link

passcod commented Feb 2, 2023

Will note there's llvm-lipo for doing the combining from Linux, though it's 100% easier to go from a macOS runner without cross-compile.

@Gankra
Copy link
Contributor

Gankra commented Feb 2, 2023

Recording the fact that lipo on macos is comically easy to use

image

I assume it also merges dsyms but haven't checked.

lipo -create \
    -arch arm64 target/distrib/cargo-dist-v0.2.0-aarch64-apple-darwin/cargo-dist \
    -arch x86_64 target/distrib/cargo-dist-v0.2.0-x86_64-apple-darwin/cargo-dist \
    -output target/distrib/cargo-dist-v0.2.0-universal-apple-darwin/cargo-dist

Unclear what the target naming scheme for such a binary should be (here I used universal-apple-darwin).

@mstange
Copy link
Author

mstange commented Feb 2, 2023

Oh right, yes I forgot about the rustup target add step.

I'm not sure how dSYMs for universal binaries are usually handled. Having two dSYMs would make it easier to fetch the right one from a symbol server. But this section about property lists in dSYM bundles and this LLVM commit imply that you can have fat dSYMs. But I would be surprised if lipo created those automatically if you only call it on the binaries - I'd expect you'd have to call lipo again for the objects in the two dSYMs.

I don't have any input on the naming scheme for the universal binary. What you have sounds fine to me.

@Gankra
Copy link
Contributor

Gankra commented Feb 2, 2023

Apparently the python ecosystem likes "universal2-apple-darwin" in deference to the fact that the OG ppc -> intel transition was the original "universal". I think I like that as compact but still pedantically future proof.

@Gankra
Copy link
Contributor

Gankra commented Feb 12, 2023

Did some searching and testing and it appears that you can't invoke lipo on a dSYM but you can invoke it on the gooey binary center, at least according to this build script.

mkdir tmp  

cargo build --profile=dist --target=aarch64-apple-darwin --target=x86_64-apple-darwin

cp -RL target/x86_64-apple-darwin/dist/cargo-dist.dSYM tmp/cargo-dist.dSYM

lipo -create \
  target/x86_64-apple-darwin/dist/cargo-dist.dSYM/Contents/Resources/DWARF/cargo_dist-03dd926e5c1d7b2f \
  target/aarch64-apple-darwin/dist/cargo-dist.dSYM/Contents/Resources/DWARF/cargo_dist-1725163586ad2995 \
  -output tmp/cargo-dist.dSYM/Contents/Resources/DWARF/cargo_dist-03dd926e5c1d7b2f

Copying one of the two dSYMs and overwriting its inner binary asset I think helps make sure you have a valid Info.plist file, but it's a bit gross/annoying that in the background rust is using these magic hash filenames and it leaks into the actual dSYM's paths/listings. Sadly the two binaries do not use the same name here, so I don't know if something would freak out about Picking One.

I think macos has... some weird amount of symbol magic going on so I'm having trouble figuring out an exact methodology where I don't get symbols without the dSYM but do get them with it. i.e. copying a binary to a temp dir, running cargo clean, and then running it under instruments seems to symbolicate the stack trace still 😵‍💫.

@frol
Copy link
Contributor

frol commented Feb 19, 2023

@mstange Do you suggest cargo-dist be compiled as a universal binary or do you suggest having support inside cargo-dist that will generate CI scripts and build for this "universal" target?

The former does not seem like it is worth the trouble as users would usually install it with a single-line shell installer or cargo install. See PR #143 where I add aarch64-apple-darwin target support for cargo-dist target and, as a result, of dogfooding, cargo-dist binary release for aarch64-apple-darwin.

The latter might be useful in the future, but I feel it might create issues that are hard to debug.

@Gankra
Copy link
Contributor

Gankra commented Feb 20, 2023

@frol markus is referring to the latter -- making universal binaries of end-user apps. This feature is also one of the biggest answers to your question in #143 (comment) (you otherwise make a reasonable point about parallelism, although each machine you spin up does have non-trivial fixed overheads so there's also an argument for Being Responsible and not needlessly spinning up more machines than you need just to reduce your build's latency).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants