M1 Mac (Big Sur 11.2) でNode.js, Python3 開発環境を用意する
これはなに
やっとApple SiliconなMacBookが届いたんですが、環境構築の為にいろんな記事を繋ぎ合わせて解釈する必要があったので、備忘録としてまとめます。
環境
- MacBook Air Late 2020
- Apple M1 (8core GPU)
- RAM 16GB
- macOS Big Sur 11.2 (20D64)
揃えたいもの
今やってる案件がVue.jsとLambda/Pythonなので、取り急ぎ最低限欲しいのはこんな感じ。AWS関連は別途。
- VSCode
- XCode
- Homebrew
- anyenv
- nodenv
- pyenv
- anyenv
1. VSCodeを入れる
ARM64版は記事作成時点でまだInsider扱いのため、以下からダウンロードします。
アイコンが緑色なのが目印。Node.jsやPythonの為のExtensionsは適宜インストール。
2. XCodeを入れる
大抵の説明では一行で済まされていますが、怒られました。
$ xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
実はすでに入ってたんですね。
ただEULAに同意していないので、同意しておきます。
$ xcode-select -license
3. Homebrewを入れる
以下参考に。
macOS ARMでは/opt以下に入れることが推奨されています。
$ cd /opt
$ sudo mkdir homebrew
$ sudo chown $USER:admin homebrew
$ curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
んで、/opt以下なので自分でPATHを通す必要があります。
macOS Big Surは、デフォルトのシェルがzshの為、以下のようにします。
$ echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.zshrc
$ exec $SHELL -l
PATHが通ったら以下でHomebrewの動作を確認。
$ brew doctor
Your system is ready to brew.
なにかエラーがあったら追いかけて直します。
4. anyenvを入れる
Homebrewから入れてみます。
$ brew install anyenv
$ echo 'eval "$(anyenv init -)"' >> ~/.zshrc
$ exec $SHELL -l
初期化処理。
$ anyenv install --init
Manifest directory doesn't exist: /Users/[your_account]/.config/anyenv/anyenv-install
Do you want to checkout ? [y/N]: y
Cloning https://github.com/anyenv/anyenv-install.git master to /Users/[your_account]/.config/anyenv/anyenv-install...
Cloning into '/Users/[your_account]/.config/anyenv/anyenv-install'...
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 44 (delta 1), reused 43 (delta 1), pack-reused 0
Unpacking objects: 100% (44/44), done.
どんな*envが扱えるのかの確認。
$ anyenv install -l
Renv
crenv
denv
erlenv
exenv
goenv
hsenv
jenv
jlenv
luaenv
nodenv
phpenv
plenv
pyenv
rbenv
sbtenv
scalaenv
swiftenv
tfenv
アップデートプラグインを入れる。
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
Cloning into '/Users/[your_acount]/.anyenv/plugins/anyenv-update'...
remote: Enumerating objects: 87, done.
remote: Total 87 (delta 0), reused 0 (delta 0), pack-reused 87
Unpacking objects: 100% (87/87), done.
5. nodenv / Node.js
anyenvからnodenvを入れます。
$ anyenv install nodenv
.
.
.
Cloning https://github.com/nodenv/nodenv.git master to nodenv...
Cloning into 'nodenv'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 4021 (delta 5), reused 4 (delta 1), pack-reused 4003
Receiving objects: 100% (4021/4021), 732.75 KiB | 979.00 KiB/s, done.
Resolving deltas: 100% (2636/2636), done.
~/.anyenv/plugins
~/.anyenv/envs/nodenv/plugins ~/.anyenv/plugins
Cloning https://github.com/nodenv/node-build.git master to node-build...
Cloning into 'node-build'...
remote: Enumerating objects: 231, done.
remote: Counting objects: 100% (231/231), done.
remote: Compressing objects: 100% (132/132), done.
remote: Total 20170 (delta 84), reused 172 (delta 79), pack-reused 19939
Receiving objects: 100% (20170/20170), 3.59 MiB | 3.09 MiB/s, done.
Resolving deltas: 100% (12839/12839), done.
~/.anyenv/plugins
~/.anyenv/envs/nodenv/plugins ~/.anyenv/plugins
Cloning https://github.com/nodenv/nodenv-vars.git master to nodenv-vars...
Cloning into 'nodenv-vars'...
remote: Enumerating objects: 211, done.
remote: Total 211 (delta 0), reused 0 (delta 0), pack-reused 211
Receiving objects: 100% (211/211), 31.82 KiB | 740.00 KiB/s, done.
Resolving deltas: 100% (76/76), done.
~/.anyenv/plugins
Install nodenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.
$
$ exec $SHELL -l
バージョン確認。
$ nodenv -v
nodenv 1.4.0+3.631d0b6
インストール可能なnodeを列挙してみる。
$ nodenv install -l
.
.
.
今回は14.15.4を入れてみます。
$ nodenv install 14.15.4
Downloading node-v14.15.4.tar.gz...
-> https://nodejs.org/dist/v14.15.4/node-v14.15.4.tar.gz
Installing node-v14.15.4...
Installed node-v14.15.4 to /Users/mia/.anyenv/envs/nodenv/versions/14.15.4
新しいバージョンを入れたらrehashしておく。
$ nodenv rehash
globalにつかうnodeを指定しておく。
$ nodenv global 14.15.4
特定のプロジェクトディレクトリ以下でのlocalでの指定方法は以下。
$ nodenv local 14.15.4
確認。
$ node -v
v14.15.4
$ which node
/Users/[your_acount]/.anyenv/envs/nodenv/shims/node
$ which npm
/Users/[your_acount]/.anyenv/envs/nodenv/shims/npm
6. pyenv / Python3
最初にpyenvを入れます。nodenvと手順は大体一緒。
$ anyenv install pyenv
.
.
.
Cloning https://github.com/pyenv/pyenv.git master to pyenv...
Cloning into 'pyenv'...
remote: Enumerating objects: 74, done.
remote: Counting objects: 100% (74/74), done.
remote: Compressing objects: 100% (65/65), done.
remote: Total 18684 (delta 32), reused 14 (delta 4), pack-reused 18610
Receiving objects: 100% (18684/18684), 3.78 MiB | 3.07 MiB/s, done.
Resolving deltas: 100% (12670/12670), done.
~/.anyenv/envs/nodenv/plugins
Install pyenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.
$
$ exec $SHELL -l
バージョン確認。
$ pyenv -v
pyenv 1.2.22-47-g4c302a02
インストール可能なpythonを列挙してみる。
$ pyenv install -l
.
.
.
今回は3.8.7を入れてみます。
$ pyenv install 3.8.7
Downloading openssl-1.1.0j.tar.gz...
-> https://www.openssl.org/source/old/1.1.0/openssl-1.1.0j.tar.gz
Installing openssl-1.1.0j...
BUILD FAILED (OS X 11.2 using python-build 1.2.22-47-g4c302a02)
Inspect or clean up the working tree at /var/folders/XXXXXXXXXXXX
Results logged to /var/folders/XXXXXXXXXXXX
Last 10 log lines:
_conn_write in libcrypto.a(bss_conn.o)
_conn_puts in libcrypto.a(bss_conn.o)
_dgram_write in libcrypto.a(bss_dgram.o)
_fd_write in libcrypto.a(bss_fd.o)
_sock_write in libcrypto.a(bss_sock.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [link_shlib.darwin] Error 1
make[1]: *** [libcrypto.dylib] Error 2
make: *** [all] Error 2
と思ったら失敗しました。そっか、M1対応は3.9.1からってどこかで見たぞ。
試してみると...
$ pyenv install 3.9.1
Downloading openssl-1.1.0j.tar.gz...
-> https://www.openssl.org/source/old/1.1.0/openssl-1.1.0j.tar.gz
Installing openssl-1.1.0j...
BUILD FAILED (OS X 11.2 using python-build 1.2.22-47-g4c302a02)
Inspect or clean up the working tree at /var/folders/XXXXXXXXXXXX
Results logged to /var/folders/XXXXXXXXXXXX
Last 10 log lines:
_conn_write in libcrypto.a(bss_conn.o)
_conn_puts in libcrypto.a(bss_conn.o)
_dgram_write in libcrypto.a(bss_dgram.o)
_fd_write in libcrypto.a(bss_fd.o)
_sock_write in libcrypto.a(bss_sock.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [link_shlib.darwin] Error 1
make[1]: *** [libcrypto.dylib] Error 2
make: *** [all] Error 2
...エラー内容同じですね。3.9.1からM1対応とのことなんですが、調べてみるとHomebrewから直接インストールだったりソース落としてきて自前でビルドしたりしてる事例ばかり。anyenvからのpyenv経由で使いたかったのでもう少し頑張ってみたら、Miniforgeならいけるんではないか説を発見しました。
$ pyenv install miniforge3-4.9.2
Downloading Miniforge3-4.9.2-5-MacOSX-arm64.sh...
-> https://github.com/conda-forge/miniforge/releases/download/4.9.2-5/Miniforge3-4.9.2-5-MacOSX-arm64.sh
Installing Miniforge3-4.9.2-5-MacOSX-arm64...
Collecting package metadata (current_repodata.json): done
Solving environment: done
## Package Plan ##
environment location: /Users/mia/.anyenv/envs/pyenv/versions/miniforge3-4.9.2
added / updated specs:
- pip
The following packages will be downloaded:
package | build
---------------------------|-----------------
certifi-2020.12.5 | py39h2804cbe_1 143 KB conda-forge
pip-21.0.1 | pyhd8ed1ab_0 1.1 MB conda-forge
------------------------------------------------------------
Total: 1.2 MB
The following packages will be UPDATED:
certifi 2020.12.5-py39h2804cbe_0 --> 2020.12.5-py39h2804cbe_1
pip 20.3.3-pyhd8ed1ab_0 --> 21.0.1-pyhd8ed1ab_0
Downloading and Extracting Packages
pip-21.0.1 | 1.1 MB | ##################################################### | 100%
certifi-2020.12.5 | 143 KB | ##################################################### | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
Installed Miniforge3-4.9.2-5-MacOSX-arm64 to /Users/mia/.anyenv/envs/pyenv/versions/miniforge3-4.9.2
ビルド通りましたね!
いそいそとシェルを初期化し、
$ exec $SHELL -l
満を辞してmacOSのPythonからpyenvのpythonに切り替え。
$ python --version
Python 2.7.16
$ pyenv global miniforge3-4.9.2
$ exec $SHELL -l
$ python --version
Python 3.9.1
$ which python
/Users/[your_acount]/.anyenv/envs/pyenv/shims/python
$ which pip
/Users/[your_acount]/.anyenv/envs/pyenv/shims/pip
これで3.9.1が動くようになりました。
本当はまだ3.8系を使っていたいんですが、一旦は仕方ないですね。
Miniforgeはconda環境の為、condaコマンドでenvを作ってactivateが必要だよー、という話もあるんですが、今回はMiniforgeの親であるpyenvで切り替えをさせるので、無視します。conda initとかactivateもしません。既存のプロジェクトとの兼ね合いで、condaでパッケージ管理したくないのです。
pipで問題のあるパッケージについては別途検証。
おまけ(condaでパッケージ管理する場合)
以下実用では試してません。
pyenvで環境を選択するパターン
anyenv > pyenv > miniforge3-[version]/envs/[env_name]
環境はの選択はpyenv、パッケージの管理はminiforge3-[version]、pyenvに選ばれた実際の環境はminiforge3-[version]/envs/[env_name]みたいなややこしいやつ。
使い勝手がcondaじゃない感じになるかも。
作業的には多分こういうことなのではないでしょうか...
$ pyenv global miniforge3-4.9.2
$ exec $SHELL -l
$ conda create -n python39 python=3.9
$ conda install -n python39 numpy
$ conda install -n python39 matplotlib
$ conda install -n python39 pandas
$ pyenv global miniforge3-4.9.2/envs/python39
$ exec $SHELL -l
condaで環境を選択するパターン
anyenv > pyenv > miniforge3-[version] > [env_name]
別のパターンとして、pyenvではminiforge3-[version]を選んでおき、miniforgeのcondaでenvをactivateすることもできます。あくまでconda環境が欲しい場合はこっちの方が順当かも。
普通にconda activateするとbash以外は知らん、みたいな感じで失敗するので、conda initが必要です。
~/.zshrcにinit結果が書き込まれるので、後で環境を戻したい場合は注意。
$ pyenv global miniforge3-4.9.2
$ exec $SHELL -l
$ conda create -n python39 python=3.9
$ conda install -n python39 numpy
$ conda install -n python39 matplotlib
$ conda install -n python39 pandas
$ conda init zsh
$ exec $SHELL -l
(base) $ conda activate python39
(base) $ exec $SHELL -l
(python39) $
まとめ
ここまでくれば、M1(ARM64)だから、という問題は各パッケージの互換性くらいかと思います。
Vue.jsとかはnpmから適宜インストールで行けると思います。
参考資料
Discussion