概要
- MacbookAir BigSur, Apple M1 チップ
において、
-
Flutter
(AndroidStudio)
の開発環境を最低限構築したが、
とてもとても大変だったのでメモを残す。
m1 Macにおいてruby
環境をどうコントロールするか、
という点がメインの話になるので、Flutter
に関わらず ruby周りで困っている人 は見て頂ければ幸いです。
以下の方針。
-
arm64
とx86_64
、それぞれの独立ターミナル環境を構築 -
ruby
はそれぞれ別個にインストールしなおす(macデフォルトrubyを使わない) - AndroidStudio は内部で
x86_64
でターミナルを起動しているようなので、x86_64
の方の環境でflutter環境を整える arch -x86_64
コマンドは使わない!!
特に最後。
M1 Macでcocoapods
周りで上手く行かないときに、解決策として、
arch -x86_64 sudo gem install cocoapods
がサイトによく載っているが、相当しっかり理解している人でない限り、
これはしない方が良いので注意が必要(最後に詳しく述べます)。
おまけ
- AndroidStudioのPreferenceを開くとフリーズする問題
- 以下の記事を参考にさせて頂きました
- タブでPreferencesを開こうとするとフリーズするようです
- 自分の環境ではデフォルト設定だと、フルスクリーン状態でなければ新規ウィンドウで開かれるので、AndroidStudioをフルスクリーンではなくした後にPreferencesを開くことで解決しました
M1チップ周りの前提知識
詳しくないので厳密には正しくない情報かもしれないが、
以下のような概念をなんとなく把握しておく必要がある。
- M1チップ:
arm64
(略してa64
)- Appleシリコンとも呼ぶ
-
arm64e
との違いはなんだろう、、、
- Intelチップ:
x86_64
- M1のMacでも、
x86_64
でアプリケーションを起動したりコマンド実行したりできる- Finderからアプリケーションの
情報を見る
で、Rosettaを使用して開く
をオンにする -
arch -x86_64
をコマンドの先頭につけてコマンドを実行する-
arch -x86_64 sudo gem install hogehoge
- 個人的にはこれは危険なのでやらない方が良いという結論に(後述)
- これを応用すればRosettaのオプションを使わなくても
x86_64
のシェルを立ち上げられるexec arch -x86_64 /bin/zsh
-
- Finderからアプリケーションの
-
uname -m
コマンドでarm64
かx86_64
かを確認できる
arm64
とx86_64
の各ターミナル環境を構築
次の記事を大変参考にさせて頂きました。
この記事に出会わなければどれだけ迷走していたことか、、、大変感謝です。
以下実際自分が行った手順
x86_64
版ターミナルアプリの作成
Apple Silicon (ARM, M1) のmacOSにaarch64とx86_64のhomebrewを共存させる
を参考にさせて頂きました。アプリをコピーペーストして増やすという発想にびっくり。
- Finderでターミナルアプリをコピーペーストして複製
- 自分は
iterm2
ですが、デフォルトのターミナルアプリでも何でもいい(Rosettaがちゃんと効けば)
- 自分は
- 複製した方のアプリを
ターミナル_x86_64
のような名前に設定 - 複製した方だけ、
情報を見る
からRosettaを使用して開く
をオンにしておく - これで
arm64
で動かしたい時は普通のターミナル、x86_64
で動かしたい時はターミナル_x86_64
を起動すればok-
uname -m
コマンドで今のターミナルがどちらか確認できる
-
双方でhomebrew
をインストール
- 順番が関係あるか分からないが、
arm64
->x86_64
の順で自分は行った - それぞれで次のコマンドを実行 (brew公式のコマンド通り)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
ちなみにhomebrewがarm64
に対応していないという情報がよく出てきますが、
今は対応済みなので普通にインストールできます。
双方でruby
をインストール
brew reinstall -s ruby
- sudoは付けない!
- そもそもM1 Macの場合はデフォルトの
ruby
を使うのは非推奨らしい
flutterをインストール
ここはターミナルとかarm64
とかx86_64
とかは関係ない
flutterインストールページからzipをダウンロードしてインストール
ターミナル構築が一通り完了してからやってもいいが、
パス設定を一気にやってしまいたいのでこのタイミングでflutter入れておくのが効率的。
ruby
とflutter
のパスを設定
-
~.zshrc
ファイル等に以下のように設定することでarm64
,x86_64
双方で独立して動作するようにする -
arm64
のruby
系-
ruby
:/opt/homebrew/opt/ruby/bin
-
gems
:/opt/homebrew/lib/ruby/gems/x.x.x/bin
(x.x.x
は実際に確かめる)
-
-
x86_64
のruby
系-
ruby
:/usr/local/opt/ruby/bin
-
gems
:/usr/local/lib/ruby/gems/x.x.x/bin
(x.x.x
は実際に確かめる)
-
if [[ $(uname -m) = "x86_64" ]]; then
typeset -U path PATH
path=(
/usr/local/opt/ruby/bin
/usr/local/lib/ruby/gems/x.x.x/bin
/usr/local/bin
/usr/local/sbin
/usr/bin
/bin
/usr/sbin
/sbin
$HOME/flutter/bin
)
else
typeset -U path PATH
path=(
/opt/homebrew/bin
/opt/homebrew/sbin
/opt/homebrew/opt/ruby/bin
/opt/homebrew/lib/ruby/gems/x.x.x/bin
/usr/local/bin
/usr/local/sbin
/usr/bin
/bin
/usr/sbin
/sbin
$HOME/flutter/bin
)
fi
- パスの順番は必要に応じて調整
- 前にある方が優先
- 今後新しいパスを追加する必要があれば、双方に追加する
- もちろん分けて管理する必要があるものであれば別個に追加する
細かい話
export文を使うと何度もシェルをリロードする度に重複してパス設定がなされてしまうので、
path変数をここで完全に上書きしている。
特にarch
コマンドによってシェル自体を切り替える想定のある人はこのような書き方の方が安心。
しかし、今回はターミナルアプリ毎分けたので、
リロードによる重複が気にならない人は、このような書き方ではなくても、
普通にexportの羅列で問題ないはず。(if分岐自体は必要)
その場合は、/etc/pathsで事前に読み込まれているであろう /usr/local/bin
~ /sbin
までの設定は省いていい。
ただし優先度には気を付ける必要がある。($PATH
の前に追加するのか後ろに追加するのか)
各ターミナルの確認
双方のターミナルで、以下を確認
-
uname -m
コマンドを打つと、対応するアーキテクチャ名(arm64
orx86_64
)が返ってくること- ここがおかしい場合は、コピーして作ったターミナルアプリの方にRosettaの設定ができていない可能性がある
-
ruby -v
コマンドを打つと、アーキテクチャに応じて以下のように返ってくること-
arm64
:ruby x.x.xoo (xx revision oo) [arm64-xxoo]
-
x86_64
:ruby x.x.xoo (xx revision oo) [x86_64-xxoo]
- ここがおかしい場合は、パス設定が不適切な可能性がある
-
これで、それぞれのターミナルで独立したruby環境を使っているということになる!
これが本記事で一番重要なところ。
AndroidStudio
とXcode
のインストール
ここら辺は普通です。他にも詳しく解説してくださっているサイトがたくさんあります。
-
AndroidStudio
インストール- AndroidStudioインストールページ
- 一度起動してセットアップを実行
- 一部エミュレータでエラーが出るが、とりあえず気にしない!
- とりあえず一部のエミュレータがダメでも基本的には無事動作します
- もし気になる人はここら辺詳しく解説して下さっているサイトが他にたくさんあると思うのでそちらを!
- pluginインストール
-
Configure
->Plugins
でFlutter
をインストール-
Dart
は自動で入るはず
-
-
-
Xcode
インストール- AppleStoreからインストール
Flutter環境構築
やっと本題。
flutter doctor
コマンドで進めていくわけだが、重要なことは、
- x86_64ターミナルの方を開いて環境構築を進める
- gemにsudoをつけない
ということ!
詳しい仕組みはわからないが、AndroidStudio
が内部で呼び出すシェルは、
x86_64
の/bin/zsh
になっている。
パス設定も、x86_64
側のパス設定がAndroidStudio
からコマンド実行される際に呼び出される。
なので、少なくともx86_64
側のターミナルで構築を行う必要がある。
(自分は一応双方とも構築しました)
上記の手順でターミナル環境を構築すると、sudoを使わずにgemを利用できる。
sudoをつけて操作してしまうと、例えばgem install
をした際にはそのgemだけ権限がおかしくなったりするのでよくない。
(gemsの配下をllしてみるとよくわかる)
cocoapodsのインストール
gem install cocoapods
sudoを付けない!
cocoapodsが見つからないエラー
cocoapodsを入れたはずなのにAndroidStudioで見つからないという問題が、ネット上でもよく挙がっています。
自分はその問題の1つの可能性として、AndroidStudioが内部で呼び出すシェルのパスと、
gem install
を実行した環境のパスの不一致があるのではないかと思います。
AndroidStudioはデフォルトだと、/bin/zsh
をx86_64
で内部起動していそうです。
なので、今回みたいにアーキテクチャによって環境変数を分けて管理してる場合は注意が必要です。
自分は最初arm64
側で構築し、flutter doctor
が全部OKになりましたが、
AndroidStudioでいざビルドをしてみるとcocoapods
が無いというエラーが発生しました。
AndroidStudioが呼び出すx86_64
のシェルでは、arm64
側のgemsにパスが通っていないので、至極当然なエラーでした。
それに気づいて、x86_64
側でもcocoapodsを入れたら解決した、という流れでした。
flutter doctor
の指示に沿って環境構築
flutter doctor
コマンドの指示に従って構築する!
(詳しく解説してくださっているサイトがたくさんあるのでここでは省略)
確か以下を行う必要があった。
- AndroidStudio系でライセンス承諾
- xcode系で2つほどよくわからないコマンドを打たされた
以上で無事完了!
M1 MacでFlutterを用いたアプリ開発できるはずです!
archコマンドを推奨しない理由
ハマるポイントはruby, gem周りと思います。
特にarm64系でcocoapods
がうまく動かない、というサイトをたくさん目にしました。
よく解決方法として、
arch -x86_64 sudo gem install cocoapods
等々が記載されていますが、自分はこの方法は非推奨と思います。
しっかと理解して行うならばよいのですが、
何となくこれで解決するだろうと思ってこのコマンドを実行してしまうのは危険です。
それは、同じruby環境の中でgemを、arm64
とx86_64
とを混ぜて操作することになるからです。
これは1つ間違えればgem全体を破壊することになりかねません。
(自分は実際に一度やらかしました。まったくgemコマンドが動作しなくなり、ruby毎再インストールする羽目になりました。)
色々迷走した挙句にたどり着いたのが、
- Yet Another な Apple Silicon (M1) + Homebrew のベストプラクティス
- Apple Silicon (ARM, M1) のmacOSにaarch64とx86_64のhomebrewを共存させる
この方々の記事でした。
これらの記事にbrew
をarm64
用とx86_64
用とで別々に共存させるという発想を頂き、
これを利用してruby
も別個管理できるのではないかと思い至り、
試してみたらうまくいきました。
arm64
用とx86_64
用とで分離して管理できれば、
この地獄のような問題をすっきりと解決できますね!
おわりに
m1 Macを買ったことを後悔しかけていましたが、
今はむしろ良かったとも思えるくらいです。
それくらい納得のいく環境を整えることができました。
これだけ分かればFlutter環境だけでなく、
そのほかのアプリケーションやフレームワークも何とかなりそうと思います。
残念なのはAndroidStudioはx86_64
で動いていそうなことですね、、
せっかくなのでarm64
で動かすことはできないのだろうか、、