😸

M1 Macに古いPythonをインストールする(Python3.6.x)

2022/08/17に公開

概要

発売直後に比べるとやや落ち着いてきたM1 Mac面倒すぎ問題ですが、2022年現在でも定期的に壁にぶつかる今日この頃、この度ローカル環境にPython3.6.9を入れなくてはいけない必要が出てきたのですが、本日はその時の情報についてまとめてみました。

参考URL

環境

  • MacBook Pro (13-inch, M1, 2020)
  • macOS Monterey バージョン 12.0.1

始めに確認

CPUアーキテクチャ

以下のコマンドで現在のM1 MacのCPUアーキテクチャがarm64であることを確認します

uname -m

Homebrewのインストール

(既にHomebrewが導入されている場合はスキップしてください)

(なければ)xcode-selectのインストールを以下のコマンドで行います

xcode-select --install

次に公式にある以下のコマンドでM1 Mac用のHomebrewをインストール

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

最後にパスを通します。ここでは.zshrcに追記しています。

~/.zshrc
eval $(/opt/homebrew/bin/brew shellenv)

pyenvのインストール

(既にpyenvが導入されている場合はスキップしてください)

以下のコマンドでpyenvをインストールします

brew install pyenv

次にパスを通します。ここでは.zshrcに追記しています。

~/.zshrc
export PYENV_ROOT="$HOME/.pyenv/shims"
export PATH="$PYENV_ROOT:$PATH"
export PIPENV_PYTHON="$PYENV_ROOT/python"
eval "$(pyenv init --path)"

Rosetta2関連のセットアップ

Rosetta2のインストール

M1 Macでは、インテルアーキテクチャ向けに作られたアプリをエミュレーションソフトウェア「Rosetta 2」を経由して起動することができます。以下のコマンドでインストールします

softwareupdate --install-rosetta --agree-to-license

正常にインストールされたかどうか確認するために、以下のコマンドで環境を切り替えてみます

# 環境を切り替え
arch -x86_64 zsh

# 切り替わっているかどうか確認
uname -m

無事、x86_64が出力されればOKです。exitコマンドでこの環境を終了して元に戻れます。もしくはarch -arm64e zshコマンドを叩くことでさらにarm64環境に切り替えることも可能です。今後、環境の切り替えを簡単に行えるよう.zshrcにエイリアスを設定しておくと楽です。

~/.zshrc
alias x86='arch -x86_64 zsh'
alias arm='arch -arm64e zsh'

Rosetta2環境におけるHomebrewのインストール

以下のコマンドでインストールします

arch -arch x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

パスも通す必要があります。先ほど.zshrcarm64用のパスを指定していましたが、以下のように場合わけすることで、環境により異なるbrewを使用するよう書き換えます。

~/.zshrc
if [ "$(uname -m)" = "arm64" ]; then
  eval "$(/opt/homebrew/bin/brew shellenv)"
  export PATH="/opt/homebrew/bin:$PATH"
else
  eval "$(/usr/local/bin/brew shellenv)"
fi

Rosetta2環境におけるpyenvのインストール

現在の環境がx86_64であることを確認し、以下のコマンドを叩きます。

brew install pyenv

パスも通す必要があります。先ほど.zshrcarm64用のパスを指定していましたが、以下のように場合わけすることで、環境により異なるpyenvを使用するよう書き換えます。

~/.zshrc
if [ "$(uname -m)" = "arm64" ]; then
  export PYENV_ROOT="$HOME/.pyenv/shims"
  export PATH="$HOME/:$PATH"
else
  export PYENV_ROOT="$HOME/.pyenv_x86"
  export PATH="$HOME/.pyenv_x86/bin:$PATH"
fi
export PIPENV_PYTHON="$PYENV_ROOT/python"
eval "$(pyenv init --path)"

このようにアーキテクチャ毎にpyenvを分けて管理することで、~/.pyenv、及び~/.pyenv_x86という二つのpyenv環境が構築されます。下図は後々のステップを全て終了させた時点でのものですが、pythonのバージョンを別々に管理できていることが確認できると思います。(古いバージョンをx86_64で新しいバージョンをarm64で管理している)

(補足)環境別にプロンプトの表示を切り変える

このステップは絶対に必要というわけではありませんが、環境毎にプロンプトなどを表示分けしておくことで無用な混乱を回避しやすくなります。自分のMacはzplugを導入し、そこから必要なテーマとしてzplug "themes/tjkirch", from:oh-my-zshを導入していてしっくりきているので、そのままにしていますが、もし場合わけしたい場合、以下は簡単な例ですが、環境変数PROMPTを以下の定義しておいてもいいかもしれません。

~/.zshrc
PROMPT="%F{green}%n%f %F{cyan}($(uname -m))%f:%F{blue}%~%f"$'\n'"%# "

x86_64環境にPython3.6.9をインストール

インストールの基本操作

本題の前に、筆者のx86_64環境のbrewにインストールされているフォーミュラの一覧だけ掲載しておきます。(必要なもの不必要なもの混在しているかもしれませんが、一応環境の現状として掲載)

$ brew list
==> Formulae
autoconf	gettext		libffi		m4		pkg-config	xz
ca-certificates	gmp		libmpc		mpfr		pyenv		zstd
gcc		isl		lz4		openssl@1.1	readline

基本的な操作はarm64環境と変わりありません。pyenv install {version}でインストールすることが可能です。ただ肝心の3.6.9はこの方法だとビルドできませんでした。

...
BUILD FAILED (OS X 12.0.1 ...

...

  By default, distutils will build C++ extension modules with "clang++".
  If this is not intended, then set CXX on the configure command line.

checking for the platform triplet based on compiler characteristics... darwin
configure: error: internal configure error for the platform triplet, please file a bug report
make: *** No targets specified and no makefile found.  Stop.

なので以下の流れでインストールをしていきます

# 各フォーミュラのパスを環境変数に代入
export CPPFLAGS="-I$(brew --prefix libffi)/include -I$(brew --prefix openssl)/include -I$(brew --prefix readline)/lib"

export CFLAGS="-I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include -Wno-implicit-function-declaration"

export LDFLAGS="-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib -L$(brew --prefix gettext)/lib -L$(brew --prefix libffi)/lib"

# インストール
pyenv install --patch 3.6.9 <<(curl -sSL https://raw.githubusercontent.com/pyenv/pyenv/master/plugins/python-build/share/python-build/patches/3.6.15/Python-3.6.15/0008-bpo-45405-Prevent-internal-configure-error-when-runn.patch\?full_index\=1)

# 後々面倒にならないよう環境変数を削除
unset CPPFLAGS CFLAGS LDFLAGS

これで無事インストールできました

Discussion