Mac で Universal Binary な Python が簡単にビルド出来る件。
概要
昨日 Python 3.x のビルドが通らなくてなんとかしてた のだけど、その時に ./configure
のオプションを眺めていたら --with-universal-archs
というのを見付けた。
どうやら読む限り --enable-universalsdk
と一緒に指定してね、ということと、詳しくは Mac/README.rst を読んでくれ、とのこと。
pyenv の python-build でビルドしてみる
どうやら --enable-universalsdk
と --with-universal-archs
は PYTHON_CONFIGURE_OPTS
では渡せないようで、 CONFIGURE_OPTS
で指定する必要があるようだ。
--enable-universalsdk
の値は省略可能で、省略時は /usr/bin/xcodebuild -version -sdk macosx Path
が使われてそう。
CONFIGURE_OPTS="--enable-universalsdk --with-universal-archs=universal2" \
PYTHON_CONFIGURE_OPTS="--build=$(/usr/bin/uname -p)-apple-darwin$(/usr/bin/uname -r)" \
pyenv install 3.9.6
上の例で PYTHON_CONFIGURE_OPTS
を指定してるのは GNU 版 coreutils が入っているとビルド出来ないからで、環境によっては省略可能。
出てきたバイナリ
M1 MacBook Air でビルドした結果 ↓
$ pwd
/opt/homebrew/opt/pyenv/versions/3.9.6/bin
$ file python3.9
python3.9: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
python3.9 (for architecture x86_64): Mach-O 64-bit executable x86_64
python3.9 (for architecture arm64): Mach-O 64-bit executable arm64
2018 Mac mini でビルドした結果 ↓
$ pwd
/usr/local/opt/pyenv/versions/3.9.6/bin
$ file python3.9
python3.9: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
python3.9 (for architecture x86_64): Mach-O 64-bit executable x86_64
python3.9 (for architecture arm64): Mach-O 64-bit executable arm64
M1 環境でも Intel 環境でもちゃんとファットバイナリになってることが確認できる。
締め
Universal Binary の仕組み自体は Mac OSX 10.4 の頃の PowerPC から Intel に移行した時に使われているものがそのまま使われていて (たぶん) 、組み合わせは違えど今もなお現役の素晴しい技術だなと思う。新・OS X ハッキング! のこの記事 あたりからバックナンバーを眺めると勉強になる。
しかし Universal Binary を手元でビルドできて嬉しいのか、とか、こんなんどこで使うんだという気もするが、もしこれが Ruby だったら CocoaPods 周りで問題 が起きて面倒な事例とかがすぐに思い浮かぶし、自分がいかに Python を普段使いしてないかという話でもある。
なお Python 本体をビルドすること自体が楽しくなってしまって、手元で雑に動かしたかったサンプルコードはまだ動かしてない。