🍏

みんなの M1 Mac における Homebrew のベストプラクティス は間違っている

commits4 min read 13

https://github.com/Homebrew/install/pull/373
  • 追記(2021/02/07): Homebrew 3.0.0 がリリースされ正式に対応されました

https://brew.sh/2021/02/05/homebrew-3.0.0/

Apple Silicon (M1 チップ) を採用した Mac に Homebrew をインストールするときのみんなの設定に対してもっと楽な方法があるのにと思い投稿しました。

https://qiita.com/yujiod/items/56002a7cef5b5a3be3fb
https://qiita.com/shira-shun/items/0f6213f4923cb5544367
https://zenn.dev/sai2_dev/articles/20201213_homebrew

上記の記事ではわざわざRosettaを選択してーシェルを切り替えてーみたいなことが書いてありますがはっきり言って面倒です!

前提

  • Rosettaをインストールしている
    • これがないと話が始まりません
  • ARMで動作するターミナル
    • 現状公式のターミナルアプリのみです
    • -> exec arch -arm64e /bin/zsh で対応していないターミナルからでもarm64動作できました
  • zshを使用している
    • デフォルトのログインシェルを変更していなければ大丈夫です

Homebrew をインストール

やることは簡単で、今回主役のarchコマンドを使います。

通常版

x86_64で動作する方ですね

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

(今後変更される場合があるので/bin/bash以降の部分は公式サイトを見て置き換えてください)

ARM版

ARM64で動作する方です

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

私の環境だと/optはrootが所有しているのでsudoをつけます
ワンライナーが対応してくれました!

設定

Rosettaを入れるとarchコマンドが追加されます。

そしてできるだけarmを使いたいので

~/.zshrc
typeset -U path PATH
path=(
	/opt/homebrew/bin(N-/)
	/usr/local/bin(N-/)
	$path
)

のようにARM版(/opt/homebrew/bin)を優先的に設定します。

(ちなみに(N-/)はフォルダが存在するとパスを追加するという意味です。)

https://qiita.com/mollifier/items/42ae46ff4140251290a7
~/.zshrc
if (( $+commands[sw_vers] )) && (( $+commands[arch] )); then
	[[ -x /usr/local/bin/brew ]] && alias brew="arch -arch x86_64 /usr/local/bin/brew"
	alias x64='exec arch -x86_64 /bin/zsh'
	alias a64='exec arch -arm64e /bin/zsh'
	switch-arch() {
		if  [[ "$(uname -m)" == arm64 ]]; then
			arch=x86_64
		elif [[ "$(uname -m)" == x86_64 ]]; then
			arch=arm64e
		fi
		exec arch -arch $arch /bin/zsh
	}
fi

上記の設定を追加することによってmacでarchコマンドが使えるときのみ設定されます。

他にも

~/.zshrc
setopt magic_equal_subst

を設定するとこのあと説明しますが便利に使用できます。

ほかにも switch-arch で切り替えをできたり

x64a64で強制的に変更できます

使い方

同じように設定したのであればbrewarch -arch x86_64 /usr/local/bin/brewへとエイリアスになっていると思います

また $PATH 上で優先される brew コマンドは /opt/homebrew/bin/brew のはずです

そして magic_equal_subst を設定しているので先頭に = をつけてコマンドを実行するとそのコマンドの絶対パスが帰ってくるので /opt/homebrew/bin/brew が使われるはずです。

Terminal.app
# -> Rosettaを使ってXXXをインストール
brew install XXX
# -> ARMでXXXをインストール
=brew install XXX

まとめ

~/.zshrc
typeset -U path PATH
path=(
	/opt/homebrew/bin(N-/)
	/usr/local/bin(N-/)
	$path
)

if (( $+commands[sw_vers] )) && (( $+commands[arch] )); then
	[[ -x /usr/local/bin/brew ]] && alias brew="arch -arch x86_64 /usr/local/bin/brew"
	alias x64='exec arch -x86_64 /bin/zsh'
	alias a64='exec arch -arm64e /bin/zsh'
	switch-arch() {
		if  [[ "$(uname -m)" == arm64 ]]; then
			arch=x86_64
		elif [[ "$(uname -m)" == x86_64 ]]; then
			arch=arm64e
		fi
		exec arch -arch $arch /bin/zsh
	}
fi

setopt magic_equal_subst

~/.zshrcに追加する!
(~/.zshenvだと$PATHの書き換えが発生するので)

brewはRosettaを使う、ARM版は =brew のように =をつける!

GitHubで編集を提案

この記事に贈られたバッジ

Discussion

この通りやったら、めっちゃ簡単にできるようになりました!
ありがとうございます!

一点だけ、
setopt magic_equal_subs
と書かれている箇所がありますが、正しくは
setopt magic_equal_subst
ですかね?

Typo 報告ありがとうございます。編集しておきました!

~/.zshrc
typeset -U path PATH
path=(
/opt/homebrew/bin(N-/)
/usr/local/bin(N-/)
$path
)
これはどこで開けるのですか?
ターミナルに打つのでしょうか?

~/.zshrc はユーザーディレクトリ直下に存在します。 ~/ はユーザーディレクトリのことを表し、 .zshrc というファイルに書き込めばいいと思います。詳しくは他の人がまとめてくださっているので調べてください。
また好きなエディタで操作して頂いて構いません。標準のテキストエディタで書く場合はターミナルで open ~/.zshrc と打つとできますよ

知見をありがとうございます。
浅学で申し訳ないのですが、いつかRosettaが不要になったとき、どう対処したらよいのかも教えていただきたいです。
このzshrcの内容を削除するだけで、brewはARMで動作するようになるのでしょうか?

現状言えることはHomeBrewがどのような方針にするのかを待つしかありません。

またコードを挿入していない場合はbrewコマンドはターミナルとログインシェルに依存します。
Apple Silicon搭載のmacOSで標準のターミナル.App/usr/bin/zshを使用しているのであればARMで動作するはずです。

とても参考になりました!ありがとうございました!!

めちゃめちゃ参考になりました!
自分の環境で試した際、zsh の compinit チェックで下記警告が出ましたが、警告がでたディレクトリのパーミッション変更することで解消できたので共有します!

$ source ~/.zshrc
zsh compinit: insecure directories, run compaudit for list.
Ignore insecure directories and continue [y] or abort compinit [n]?

$ compaudit
There are insecure directories:
/usr/local/share/zsh/site-functions
/usr/local/share/zsh

$ ls -l /usr/local/share/zsh/site-functions
total 0
lrwxr-xr-x  1 xxxxxx  admin  39  1 12 00:07 _brew -> ../../../Homebrew/completions/zsh/_brew
lrwxr-xr-x  1 xxxxxx  admin  44  1 12 00:07 _brew_cask -> ../../../Homebrew/completions/zsh/_brew_cask

$ chmod 755 /usr/local/share/zsh/site-functions

$ chmod 755 /usr/local/share/zsh

非常に有益な情報ありがとうございます!

質問なのですが、こちらはターミナルアプリにIterm2を使用した場合でも同様に作動しますか?

最新版のiTerm2はユニバーサルアプリとなったため使用できますよ

M1 公式サポート来ましたね!

https://brew.sh/2021/02/05/homebrew-3.0.0/

でもformula側がまだ対応してないのも多いから、結局Rosetta使うことになるんですかね?

情報、ありがとうございます。記事に追記しておきました。

公式ブログを見ると

Apple Silicon is now officially supported for installations in /opt/homebrew. formulae.brew.sh formula pages indicate for which platforms bottles (binary packages) are provided and therefore whether they are supported by Homebrew. Homebrew doesn’t (yet) provide bottles for all packages on Apple Silicon that we do on Intel x86_64 but we welcome your help in doing so. Rosetta 2 on Apple Silicon still provides support for Intel x86_64 in /usr/local.

とあるのでまだすべてのbottlesが対応していないし、Rosetta 2で動作するのは/usr/localにインストールする事が書いてあることからまだまだRosettaを使用しないといけない状況ですね
(Homebrew以外にもDiscordなど対応していないアプリがまだありますし)

なるほど、詳しい情報ありがとうございます!

ressさんのこの記事のおかげで、M1でも快適にHomebrew使えてるので本当にありがとうございます🙇‍♂️

ログインするとコメントできます