こんにちは、ForSchool事業部の冨山(@atomiyama1216)です。
好きなエディタはVimです。どんなにVSCodeが流行っても僕はVimを使い続けます。
2021年4月に業務用マシンを買い換えApple M1チップ搭載モデルに買い替えました。
その際環境構築でなかなかに躓いたのでそのことについて記録しておきます。
主にRails関連のgemをインストールするときとNode.jsをインストールするときに困ったのでそれらについて書きます。
今回の環境構築ではRosetta 2は使いません。
Disclaimer
以下の環境で構築したときの記事になります。
$ uname -a Darwin PC21-010.local 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:06:51 PST 2021; root:xnu-7195.81.3~1/RELEASE_ARM64_T8101 arm64 $ system_profiler SPHardwareDataType Hardware: Hardware Overview: Model Name: MacBook Pro Model Identifier: MacBookPro17,1 Chip: Apple M1 Total Number of Cores: 8 (4 performance and 4 efficiency) Memory: 16 GB System Firmware Version: 6723.81.1 Serial Number (system): ... Hardware UUID: ... Provisioning UDID: ... Activation Lock Status: Disabled
TL;DR
- 環境構築のためのbootstrapを書いたatomiyama/dotfiles
- homebrewのインストール先はIntelプロセッサでは
/usr/local
、Apple Siliconでは/opt/homebrew
になっている*1 - ffiはv1.14.0移行がApple Silicon環境に対応している
- Node.jsはv15.3.0以上をソースコードからコンパイルする*2
bootstrapを作成した
これまでもdotfilesをshellスクリプトで書いて複数環境で管理していたのですが今回Ansibleを用いる形に書き換えました。
一応これをローカルで実行して最低限の環境が揃ったので参考にしてください。
お星さままってます☆(ゝω・)v☆
mysql2のインストールでコケる
これは以前から頻出の問題でググるとたくさん記事が出てきます。
ただし進研ゼミでやったやつだ!と思ってこれまでのIntel環境同様の手順を脳死で踏むともれなくコケて下のようなエラーが出力されます。
$ bundle install ... 2 warnings generated. compiling infile.c compiling mysql2_ext.c compiling result.c compiling statement.c linking shared-object mysql2/mysql2.bundle ld: library not found for -lssl clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1 make failed, exit code 2 Gem files will remain installed in ...
ld: library not found for -lxxx
っていうのはGNUリンカのldコマンド実行時にxxxってライブラリが見つからんかったってエラーです。
なのでその場所を教えて上げればいいわけです。
これまではこのエラーが出たら脳死で以下のコマンドを実行すれば解決しました。
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
ただApple M1チップ環境では失敗します。
homebrewのドキュメント(こちら)に以下の記載があるようにインストール先が/opt/homebrew
に変更されています。
This script installs Homebrew to its preferred prefix (/usr/local for macOS Intel, /opt/homebrew for Apple Silicon) so that you don’t need sudo when you brew install.
どのパスを指定すればよいかは下の方法で確認できます。
$ brew info openssl ... For compilers to find openssl@1.1 you may need to set: export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib" export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include" ...
つまりここに書いてある通り/opt/homebrew/opt/openssl@1.1/lib
を指定してあげれば問題ないので
bundle config --local build.mysql2 "--with-ldflags=-L/opt/homebrew/opt/openssl@1.1/lib"
としてからbundle install
なりgem install mysql2
すれば成功するはずです。
rails cが起動しない
ここまでやって一通りbundle install
は成功したのでbundle exec rails c
したら次は下のエラーがでました。
$ bundle exec rails c Traceback (most recent call last): ... /path/to/rails/project/vendor/bundle/ruby/2.7.0/gems/ffi-1.13.1/lib/ffi/types.rb:69:in `find_type': unable to resolve type 'size_t' (TypeError)
これはffiのFFI#find_type
で型定義が解決されないことに起因する問題でこちらのPRで解決され、v1.14.0でリリースされています。
Node.jsが動かない
つぎにNode.jsをいれようとしたら動かなくて困りました。(見かけ上はinstallできたが一部jestなどが動作しなかった)
こちらのissueにて言及されているようにv15.3.0より前のリリースではdarwin-arm64環境はサポートされていません。*3
https://nodejs.org/dist/v15.14.0を見るとわかるのですがv15.x以前ではApple M1チップ環境darwin-arm64
向けのビルド済みパッケージは配布されていません。
現在CURRENTリリースのv16.x以上であればdarwin-arm64
向けのビルド済みパッケージが配布されています。
それ以前のバージョンを使用する場合はv15.3.0以降のバージョンを自身でコンパイルして使用するしかないと思います。
ただしこちらに関してもExperimentalサポートなので完全な動作を保障するものではないですが...
なので今回は以下のページを参考にnodebrewを使用してソースコードからコンパイルすることにしました。
手順は以下の通りです
- nodebrewのインストールとセットアップ
$ brew install nodebrew $ nodebrew setup_dirs
- nodebrewのスクリプトの編集 こちらでシステム環境を特定するサブルーチンsystem_infoを以下のように書き換えました。
$ vim $(which nodebrew)
sub system_info { my $arch; my ($sysname, $machine) = (POSIX::uname)[0, 4]; if ($machine =~ m/x86_64/) { $arch = 'x64'; } elsif ($machine =~ m/arm64/) { $arch = 'arm64'; } elsif ($machine =~ m/i\d86/) { $arch = 'x86'; } elsif ($machine =~ m/armv6l/) { $arch = 'armv6l'; } elsif ($machine =~ m/armv7l/) { $arch = 'armv7l'; } elsif ($machine =~ m/aarch64/) { $arch = 'armv7l'; } elsif ($sysname =~ m/sunos/i) { # SunOS $machine => 'i86pc'. but use 64bit kernel. # Solaris 11 not support 32bit kernel. # both 32bit and 64bit node-binary even work on 64bit kernel $arch = 'x64'; } else { die "Error: $sysname $machine is not supported." } return (lc $sysname, $arch); }
- nodeのコンパイル
$ nodebrew compile v15.14.0
この作業はだいぶ時間がかかりました。が、ここまでやれば一通り自分は環境が整いました。
まとめ
Apple M1チップ搭載マシンはまだ未対応のライブラリなどがあるため環境構築で躓くことは多くありましたが、バッテリーの持ちとか動作の速さは素晴らしいと思います。 前であればDockerを立ち上げた状態でZoom会議に参加するとマウスカーソルが遅延したりと使うに耐えない状態でした。 ただ業務マシンを買い替えてからはそういった問題が起きることなく快適に仕事ができてます。 ライブラリの問題などは積極的にフィードバックして一日でも早く人類がM1チップ環境に追いつく日がくるといいなと思ってます。