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

Should arm64 runners build both universal2 and arm64 wheels by default? #1204

Closed
joerick opened this issue Jul 31, 2022 · 7 comments · Fixed by #1217
Closed

Should arm64 runners build both universal2 and arm64 wheels by default? #1204

joerick opened this issue Jul 31, 2022 · 7 comments · Fixed by #1217

Comments

@joerick
Copy link
Contributor

joerick commented Jul 31, 2022

Continuing the discussion from #1191 (comment)

The current situation is that arm64 runners builds universal2 and arm64 by default. This discussion is whether we change that to just arm64.

@joerick: The question of whether to default building both universal2 and arm64 on the arm runner is still open, in my mind. I'm still mostly of the opinion that building both is good, because universal2 packages are preferred in some contexts (e.g. distributable GUI apps), and that most packages are small and the extra build time isn't much of a hit. Of course, people building big libraries would be wise to change this to just build arm64.

@henryiii: Personally, I think the default should be native only. Eventually no one will care about Intel / universal and will only produce native binaries again. Also, there are still workarounds related to cross compiling for universal (like requiring all dependencies to also be universal). And we don’t support it yet, but there are two ways to make a universal binary, the default way and merging two native binaries. And finally universal vs. native is a choice, and I’d you pick universal, you don’t need native. You can always add tags for the native arch’s to a universal binary. And pip won’t even ever download universal if both native wheels exist.

So I’d recommend native being default, and only producing native binaries with it.

Let's get a decision on this before we release CirrusCI support, which would be our first officially supported arm64 CI.

@joerick
Copy link
Contributor Author

joerick commented Jul 31, 2022

Notably, numpy doesn't distribute universal2 wheels currently. There's some discussion about that here: numpy/numpy#20787

@joerick
Copy link
Contributor Author

joerick commented Aug 1, 2022

Regarding wheel fusing (I had to look this up) - multibuild's implementation is here:

https://github.com/multi-build/multibuild/blob/10d9a4c9663759e194495e87eb84f96f7cb513e9/osx_utils.sh#L508-L525

It uses a tool built into delocate called delocate-fuse, called like delocate-fuse <x86_64_wheel> <arm64_wheel> -w <outdir>.

I don't know how well this works, it seems like there could be cases where this fails (particularly I'm wondering what happens we hit the # existing not-lib file not identical to source comment). But, given this is part of multibuild, it must have gotten a good amount of testing, and delocate has always been solid.

@joerick
Copy link
Contributor Author

joerick commented Aug 1, 2022

The other thing that's on my mind is whether we're even doing the universal2 thing at the right stage of the packaging process. As we know, universal2 wheels are ignored by pip when a native one is present. Packaged macOS apps are a pretty small percentage of Python deployment. If fusing is indeed possible, do we really need the universal2 wheels on PyPI at all? Can we push wheel fusing down the process to a distribution tool like py2app or pyinstaller? As @mattip says in the numpy thread linked above:

@mattip: As I understand things, app packagers would still need to have the option to fuse wheels for projects that do not produce universal2 wheels, so I think the proper place for all that to happen is when packaging apps.

I suppose the only downside to this is that project-built universal2 wheels have the chance to be tested before release, whereas I might not be as confident in using a universal2 wheel that was fused 'in the wild'. I suppose that depends on how reliable the 'fuse' process is.

A final thought - is wheel fusing the only option for macOS packagers? Could they build/distribute separate x86_64 and arm64 versions?

@mattip
Copy link
Contributor

mattip commented Aug 1, 2022

Can we push wheel fusing down the process to the packaging tool like py2app or pyinstaller?

+1 from me, until there is a real user-side demand for universal wheels.

@henryiii
Copy link
Contributor

henryiii commented Aug 1, 2022

IMO, this means (for cibuildwheel) that we should never build universal2 by default, but leave it up to a user choice. So AS runners should try to build AS wheels by default, like Intel runners and Intel wheels. We could add a fuse option eventually, which would also allow us to test the fused wheel, but that's very much extra. Users can use delocate-fuse today if they want to - especially if they build on both Intel and Apple Silicon runners. Users can also just not ship Universal2 if they ship both. Maybe packaging could eventually fuze after the fact if they needed both.

PS: I would also recommend retagging a universal2 wheel like macosx_10_10_universal2.macosx_10_10_x86_64.macosx_11_0_arm64.macosx_11_0_universal2 which allows a single wheel to also work with older pips, too. The tooling for that would be in pypa/wheel#422 but wheel development is a bit slow at the moment.

@mattip
Copy link
Contributor

mattip commented Aug 1, 2022

What are "AS runners" and "AS wheels"? The plan sounds reasonable in any case.

@Jackenmen
Copy link
Contributor

AS is probably short for Apple Silicon.

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

Successfully merging a pull request may close this issue.

4 participants