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: add support for macOS 11 and Apple M1 Silicon (arm64) #5581
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is awesome @rokm 🤯
Code review seems good, I will take time to test later in the afternoon.
.github/workflows/macos.yml
Outdated
@@ -49,7 +49,7 @@ jobs: | |||
|
|||
# Compile bootloader | |||
cd bootloader | |||
python waf distclean all | |||
python waf --no-universal2 distclean all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we will wait for macos-11.0
public availability before being able to enable unversal builds.
As stated in the doc:
The macOS 11.0 virtual environment is currently provided as a private preview only.
The "macos-latest" YAML workflow label still uses the macOS 10.15 virtual environment.
Works for me 👍 |
Just letting you know this fixed the first issue I was running into trying to build dupeguru on a M1 mac. (The binary was registering as x86_64 instead of universal or arm64 and resulting in some issue with libraries). I was using python 3.9.2 on macOS 11.2.3. The other problems I am still running into appear to be not related to these changes. |
3dfd622
to
f46b856
Compare
identity = '-' # ad-hoc signing | ||
|
||
logger.debug("Signing file %r", filename) | ||
cmd_args = ['codesign', '-s', identity, '--force', '--all-architectures', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we specify --options runtime
and --timestamp
to ease notarization?
Another thing to consider, eventually, would be to add another option to allow passing an entitlements file (--entitlements path/to/entitlements.plist
).
With all those parameters, one would be allowed to completely sign the app without having to post-process again all files after PyInstaller, which is the case for all code-signed softwares using it for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these options relevant to all collected binaries, or only to the generated executable (or perhaps only to .app bundle)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To everything packaged into an app, and to the final .app bundle also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FTR here is the post-process I am using to sign an .app: https://github.com/nuxeo/nuxeo-drive/blob/9a5827710f113ba6ff61124adbbc7cb3b58b462a/tools/osx/deploy_ci_agent.sh#L108-L133 (put aside the extension stuff, it is not revelant here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does hardened runtime require a real codesign identity? Trying to use it in combination with ad-hoc signing or with self-signed certificate results in error:
[2171] Error loading Python lib '/Users/rok/Development/pyi-macos11/dist/program/Python': dlopen: dlopen(/Users/rok/Development/pyi-macos11/dist/program/Python, 10): no suitable image found. Did find:
/Users/rok/Development/pyi-macos11/dist/program/Python: code signature in (/Users/rok/Development/pyi-macos11/dist/program/Python) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course, I am testing it right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is taking more time than I expected. I am stuck on:
MyApp.app: code has no resources but signature indicates they must be present
I will try to isolate the thing to understand what is not good. I have custom data, maybe it does not help. Will keep you updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your tests, do those commands pass?
$ codesign --verbose=4 --deep --strict file.app
$ spctl --assess --verbose file.app
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think you need to sign the .app bundle - this PR explicitly doesn't do that, so you still need to do it yourself. But you probably don't have to do --deep signing, since individual binaries are already signed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now added an automatic attempt to sign the .app bundle as well. In contrast to library collection, we don't consider a failure here to be fatal, just in case some manual adjustments to bundle are needed.
92f63f5
to
f46b856
Compare
This PR is now rebased on top of
This should enable creation of frozen applications for all possible arch combinations; single-arch with single-arch python, universal2 with universal2 python, and single-arch with universal2 python. For example, freezing a "Hello world" script with universal2 python on x86_64 macOS:
Building universal2 version:
Building arm64-only version ("cross-compiling"):
Trying to build a
|
3a8eccd
to
e20e74c
Compare
ec6875e
to
b9dd798
Compare
I'll have time to check in coming days, I did not forgot ;) |
It might be worth explaining the differences and consequences between thin and fat binaries especially in the context of MacOS +/- universal2 builds. |
Add option to specify code signing identity via codesign_identity argument to EXE(), or using --codesign-identity CLI switch, as an alternative to default ad-hoc signing. Also split the bincache in additional sub-directories based on codesign identity (sha256 of identity string if one is provided, "adhoc" otherwise) to prevent interference. This additional split applies only to macOS at the moment. This effectively allows user to sign all binaries within a onefile build with their codesign identity. NOTE: while this signs all collected binaries and the resulting executable, we do NOT sign app bundles. Those have corner cases tat need to be resolved manually, as has been the case up until now.
On macOS, we've been re-writing library paths on cached results as well. This is probably (hopefully?) unnecessary, as those path adjustments depend only on dist_nm. As path rewriting modifies headers, this forces us to re-sign the binaries on practicaly every run, which negates the point of the cache. However, the strip + upx combination should probably properly forward dist_nm to its call to checkCache (even if the paths get subsequently rewritten again).
Update the virtual machines involved in building macOS bootloaders to produce universal2 bootloaders built against MacOS SDK 11.x. Building against MacOS SDK 11.x enables proper support for Big Sur; for example, it allows ctypes.util.find_library() to find system libraries in the dlyd share cache (provided that python was also built against SDK 11.x). Universal2 bootloaders allow native execution both on x86_64 and the new Apple M1 Silicon (arm64) machines. In order to support the above, the `build-osxcross` virtual machine is updated to use MacOS 11.x SDK from Command Line Tools for Xcode 12.x. This also reduces storage requirements and speeds up the extraction process, as we do not need to use full Xcode package anymore. The `linux64` virtual machine is updated to use clang-11 from apt.llvm.org repository, as clang-7 that is provided by Debian Buster fails to build universal2 binaries.
Prevents the following error ``` /dev/vda does not exist, so cannot grub-install to it! You must correct your GRUB install devices before proceeding: dpkg-reconfigure grub-pc dpkg: error processing package grub-pc (--configure): installed grub-pc package post-installation script subprocess returned error exit status 1 Errors were encountered while processing: grub-pc E: Sub-process /usr/bin/dpkg returned an error code ``` which seems to be caused by the latest grub-pc update.
It seems the toolchain on our CI lacks support for building universal2 bootloaders.
Extend the EXE() arguments with entitlements_file argument, and add corresponding --osx-entitlements-file command-line switch. If specified, the entitlements file is passed to the codesign utility via --entitlements switch when signing the collected binaries and the generated executable.
Using the same parameters as when signing collected binaries, plus --deep in case we missed any files that ought to be signed as well.
790f9e4
to
b349b0b
Compare
On macOS, avoid appending -arm suffix to bootloader directory if we are on arm64 (M1) platform. So instead of Darwin-64bit-arm, we always use Darwin-64bit. Applies both to bootloader's wscript as well as frozen application assembly pipeline (or rather, PyInstaller.PLATFORM). This is because we now build universal2 bootloaders, so there is no need for two arch-specific locations. Furthermore, using -arm suffix for bootloader directory would prevent M1 users from using pre-compiled bootloaders from git tree (unless we saved one copy in each location) and in binary wheels (unless we split wheels into x86_64 and arm64 one). Overall, considering the current design of x86_64/arm64 support, it makes more sense to unify the bootloader directory for macOS.
b349b0b
to
aa4b8d9
Compare
The latest revision forces the bootloader directory to be always Keeping two distinct directories when we have a |
OK, I allocated 1h tomorrow to test it and unlock the merge. |
Excellent job @rokm, it works like a charm! I would say it is OK to merge, and if we need to do adjustments on the codesign part, then it is not a big deal :) |
This is a cleaned-up version of the
macos11-arm-support
branch, which aims to add proper support for macOS 11 Big Sur and Apple M1 Silicon (arm64
) architecture.Fixes #5315.
In particular:
unversal2
(x86_64
,arm64
) binaries by default. This allows native execution onarm64
, and thus fixes Frozenplatform.machine()
returnsx86_64
on Apple Silicon M1 macs #5494. As this requires a recent version ofXcode
toolchain (12.2 or newer), ourwafscript
now has--no-universal2
option to enable buildingx86_64
-only thin-arch bootloaders with older toolchains.universal2
bootloaders, along with their peculiarities (signing requirements onarm64
and its implications, header adjustment, etc.). Fixes PyInstaller and Apple Silicon? #5315 (comment).Python
library is superseded by re-signing with dummy signature. While removal works onx86_64
,arm64
has stricter signing requirements, so we need to replace the signature instead of removing it (which I believe PyInstaller and Apple Silicon? #5315 (comment) is about).crossosx
Vagrant VM now builds the toolchain fromCommand Line Tools for Xcode
instead of fullXcode
package to save bandwidth and time, and to alleviate storage requirements.clang
inlinux64
Vagrant VM is now updated toclang-11
from apt.llvm.org so it can builduniversal2
bootloader.So once the bootloaders are rebuilt using
Xcode
12.2 or later, and with correspondingMacOS SDK
11.x,ctypes.util.find_library()˙ will work when used with
universal2` version of python 3.9.1 (or later), which fixes #5491.We now also need the full back-to-front scan for embedded archive (#5511; the commit is for now included in the PR for easier testing), because the old signature search code in bootloader does not work with fat binaries. (While we could extend it to handle both types, the brute force search is needed to fix other issues as well).
Note: the PR does not include rebuilt bootloaders.