macOS: add support for macOS 11 and Apple M1 Silicon (arm64) by rokm · Pull Request #5581 · pyinstaller/pyinstaller (original) (raw)
This PR is now rebased on top of develop
and revised according to feedback and lessons learned so far. Most notably:
- we now re-sign all collected binaries, as modifying the library paths in their headers invalidates any present signatures (and
arm64
slices must have at least ad-hoc signature). By default, we do ad-hoc signing, but an actual identity can be passed via new--codesign-identity
CLI switch (orcodesign_identity
argument toEXE
in spec file), which also turns on hardened runtime option. - by default, we now target current running architecture. This is because even with
universal2
python installation, one might end up with single-arch package wheels. So current running architecture is the only one with the guarantee that all required libraries are available (not to mention that Homebrew python is always single-arch). Buildinguniversal2
application must therefore be explicitly enabled using new--target-arch
CLI switch (ortarget_arch
argument toEXE
in spec file). This can also be used to attempt building a single arch (x86_64
orarm64
) version fromuniversal2
environment (provided all binaries are compatible with that). - we now validate all binaries for arch compatibility, to catch mismatches at build time and avoid run-time surprises.
- when targeting a single arch, we also convert any fat binaries (including the bootloader) to single-arch thin binaries, to reduce the bundle size
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:
$ pyinstaller hello.py
$ lipo -archs dist/hello/hello
x86_64
$ lipo -archs dist/hello/Python
x86_64
Building universal2 version:
$ pyinstaller hello.py --distpath dist-universal2 --target-arch universal2
$ lipo -archs dist-universal2/hello/hello
x86_64 arm64
$ lipo -archs dist-universal2/hello/Python
x86_64 arm64
Building arm64-only version ("cross-compiling"):
$ pyinstaller hello.py --distpath dist-arm64 --target-arch arm64
$ lipo -archs dist-arm64/hello/hello
arm64
$ lipo -archs dist-arm64/hello/Python
arm64
Trying to build a universal2
or arm64
version of a progam that imports psutil
, however, will fail due to psutil
providing single-arch wheel:
$ pyinstaller program_psutil.py --distpath dist-universal2 --target-arch universal2
...
AssertionError: [...]/venv/lib/python3.9/site-packages/psutil/_psutil_osx.cpython-39-darwin.so is not a fat binary!
$ pyinstaller program_psutil.py --distpath dist-arm64 --target-arch arm64
...
AssertionError: [...]/venv/lib/python3.9/site-packages/psutil/_psutil_osx.cpython-39-darwin.so is incompatible with target arch arm64 (has arch: x86_64)!