GNU coreutils を入れてる M1 Mac で Python 3.x のビルドが通らないのをなんとかする。
環境
- M1 MacBook Air
- macOS Big Sur 11.5.2
# GNU 版での表示
$ uname -a
Darwin MBA101.local 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:27 PDT 2021; root:xnu-7195.141.2~5/RELEASE_ARM64_T8101 arm64 arm64 MacBookAir10,1 Darwin
結論
記事タイトルで半分くらい言っているのだが、 M1 搭載機では GNU 版 uname
の出力が BSD 版 uname
と異なっており、 config.guess
にてその出力を利用しているのが原因だった。
わざわざ GNU 版 coreutils なんかを入れて普段使いしてる人間は少ない模様。ググっても困ってる人がそもそも少ないような感じだった。
pyenv のイシュー欄での このコメント を見付けられなかったらもっと時間かかったと思う。
解決方法 1 (多分こっちの方がいい)
- 一時的に GNU 版 coreutils を使わないようにしてビルドする。
ワンライナーで PATH
を弄るならこんな感じ。
$ export PATH=$(printenv PATH | tr ':' '\n' | grep -v gnubin | tr '\n' ':' | rev | cut -d ':' -f2- | rev)
解決方法 2 (こういうのもある)
-
pyenv
ならPYTHON_CONFIGURE_OPTS
環境変数の指定で./configure
に--build
を渡せるようだ。-
python-build
で使える特別な環境変数は こちら に詳しい。 PYTHON_CONFIGURE_OPTS="--build=arm-apple-darwin$(/usr/bin/uname -r)" pyenv install 3.9.6
-
config.guess
をざっと読んだ限り、多分渡すのはarm
だと思うがaarch64
を渡しても手元ではビルド出来たし、どちらでもMach-O 64-bit executable arm64
のバイナリが出てくる。 - 記事執筆時点で
/usr/bin/uname -r
で取れるカーネルバージョンの指定は20.6.0
。
-
BSD 版と GNU 版で uname
の出力は実際どう違うの?
M1 MacBook Air ではこんな感じ
# uname コマンドが複数入ってることを確認する
$ which -a uname
/opt/homebrew/opt/coreutils/libexec/gnubin/uname
/usr/bin/uname
# GNU 版
$ /opt/homebrew/opt/coreutils/libexec/gnubin/uname -p
arm64
# BSD 版
$ /usr/bin/uname -p
arm
なお手元の Intel 入ってる Mac mini 2018 では -p
オプションについての出力に差異はない
# uname コマンドが複数入ってることを確認する
$ which -a uname
/usr/local/opt/coreutils/libexec/gnubin/uname
/usr/bin/uname
# GNU 版
$ /usr/local/opt/coreutils/libexec/gnubin/uname -p
i386
# BSD 版
$ /usr/bin/uname -p
i386
-a
オプションで全部出すと出力に若干の違いが見られる。
折角なので pyenv で M1 Mac に入れられるバージョンを手元でビルドしつつ試してみた
- 2.x 系
- なし
- 3.6 系以前
- なし
- 3.7 系
- 3.7.9 以降ならビルド出来る
- 3.8 系
- 3.8.10 以降ならビルド出来る
- 3.9 系
- 3.9.1 以降ならビルド出来る
古いやつを Rosetta 2 経由で使いたい
興味がなくて調べてないので他をあたってくれ。
LDFLAGS
とか CPPFLAGS
とか CFLAGS
とか
このあたりの環境依存なので homebrew とかで入れたものがインストール後に表示してくるメッセージをサボらずに読んでちゃんと設定しましょう。
こういうのがめんどいから Docker コンテナに寄せるのがいいのでは?
とは言え手元で書き捨てのスクリプトを実行したいくらいカジュアルな用途では docker volume の指定をしたりする方がめんどい気もするし、Activity Monitor.app で見る限り Docker を常時起動させていると結構バッテリ消費が激しいことが分かりつつあるので最近は必要なときだけ立ち上げているから、なんというか、めんどい。
締め
ちょっと動かしたいサンプルコードを動かそうと思ったら動作環境が手元にないことに気付いて、まぁどうせ pyenv install ...
で終わりだろと軽く思ってたんだけど全然そんなことなくて、色々調べたら誰も困ってないし、なんでやねんと思ってビルド作業ディレクトリまで行って ./configure --help
とかしつつ調査して色々やった結果それで半日終わった。
肝心の動かしたかったサンプルコードはまだ動かしてすらない。