rcmdnk's blog

2020 Apple MacBook Pro Apple M1 Chip (13インチPro, 8GB RAM, 256GB SSD) - シルバー

Appleシリコン(M1チップ)の載ったMacが販売されて大分経つので アプリなども大分M1に対応したものが増えてきましたが まだIntelプロセッサな環境でないと動かないものも結構あります。

通常のアプリはM1に対応してなくてもRosettaによってIntelプロセッサの上で動いている様にして 動かすことが可能です。

CLI環境に関しても同じようなことが出来るのですが、ちょっと特殊な状態があったのでそれについて。

Homebrewのインストール(M1用)

最初から入っているターミナル.appでもiTerm2のような3rdパーティーなアプリでも良いですが、 通常はM1でそのまま動きます。

もしかすると一部のターミナルアプリでM1非対応でRosettaが必須のものもあるかもしれませんが、 そのあたりは注意してください。

そのまま立ち上げて、 ホームページ にあるように

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

をすると、/opt/homebrewの下にHomebrewをインストールしようとします。

この際、rootのパスワードを聞かれます。

とりあえず

$ export PATH=/opt/homebrew/bin:$PATH

としてHomebrewのコマンドにパスを通し、 色々パッケージを入れていくと 一部パッケージで

$ brew install embulk
embulk: The x86_64 architecture is required for this software.
Error: An unsatisfied requirement failed this build.
[ERROR]: Failed at command: /opt/homebrew/bin/brew install embulk

みたいなエラーが出ます。

まだパッケージとして対応してないものがあるみたいです。 個別に自分でコンパイルすれば入れられるものもあるようですが、いくつか出てくると結構手間です。

また、pythonをインストールして、pipを使ってnumpyを入れようとすると失敗してしまい、 機械学習的なことをやろうと思うと構築が面倒です。

ということでIntelな環境でCLI環境を構築します。

この時点で/opt/homebrew/binなどにPATHを通す設定をしてしまうと 下の作業で面倒なので一度それらは.bashrcなり.zshrcから外しておきます。

Homebrewのインストール(Intel用)

まず、今の環境がM1(Arm)環境なのを確認。

ターミナルを立ち上げて

$ uname -m
arm64

となっていればM1(Arm)な環境です。

ここで、ターミナル.appなりiTerm.appのアイコンを右クリックして出てきたメニューから 情報を見るをクリックして情報画面を出して、 Rosettaを使用して開くにチェックを入れます。

20210802_iterm.png

こでアプリを立ち上げます。

そうすると

$ uname -m
x86_64

となっているはずで、これでIntel(x86_64)な環境になりました。

この状態で

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

をすると今度はIntel版Macの様に/usr/localにHomebrewをインストールします。

ここでインストールされたbrewコマンドを使って

$ export PATH=/usr/local/bin:$PATH

とパスを通して色々インストールしていくと、今度は上でエラーが出たembulkなどもそのままインストールできます。

また、pythonをインストールしてpip install numpyなどすると成功します。

ということで、今の所CLI環境はIntelでないと面倒なことが多いのでこちらをメインで使っていきたいと思っています。

なのでiTerm2の設定は上にあるようにRosettaの設定にしておきます。

使うことは殆どないと思いますが、ターミナル.appの方はチェックを入れずにM1な環境で立ち上がるようにしておきます。

パスの設定(.bashrc/.zshrc)

それぞれのアーキテクチャで使っているときに正しいものを使えるように Homebrewのパスの設定は以下のようにしておきます。

.bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
_set_homebrew_path {
  local brwe_dir_cand=()
  if [[ "$OSTYPE" = darwin* ]];then
    if [ "$(uname -m)" = arm64 ];then
      brew_dir_cand=(/opt/homebrew)
    else
      brew_dir_cand=(/usr/local)
    fi
  else
    brew_dir_cand=(/home/linuxbrew/.linuxbrew $HOME/.linuxbrew)
  fi
  for path in "${brew_dir_cand[@]}";do
    if [ -d "$path" ];then
      prefix=$path
      break
    fi
  done
  if [ -n "$prefix" ];then
    export PATH="$prefix/bin:$PATH"
    export PATH "$prefix/sbin:$PATH"
    export LD_LIBRARY_PATH="$prefix/lib:$LD_LIBRARY_PATH"
  fi
}
_set_homebrew_path

上のはLinux用の設定も含めてまとめてあります。(darwinで見ているところがMac用。)

シェルの設定

Macではデフォルトのシェルが設定されていて、最近は/bin/zshになっています。

Bash派は/bin/bashとかにしているかと。

これらのシェルの設定は以下のような感じで変更が可能です。

Homebrewで最新シェル導入後、その最新版をデフォルトシェルとして使用したい、と思うのですが、 上の様に環境を共有している場合はやめておいた方が良いです。

というのも、Homebrewで入るシェルはarm64またはx86_64専用のものになっていて、 別の環境として開こうとした際に失敗します。

/usr/local/bin/bash(x86_64用)を指定して Rosettaを使用して開くのチェックを外して開くと 以下の様なエラーが出て使えません。

20210802_shellfail.png

ただ、逆に /opt/homebrew/bin/bash(arm64用)を指定して Rosettaを使用して開くにチェックを入れて開くと何故か開けますが、 uname -mx86_64を示す状態になります。

ただ、これでもHomebrew版を削除した場合とかに色々と面倒が起こるので、 デフォルトのシェルは/bin/bashなどにしておいて、 必要な場合、iTermの設定などで設定したほうが良いと思います。

(ProfilesGeneralCommandCustom Shellを選んで/usr/local/bin/bashなどを設定)

シェルの状態

M1 macのarchというコマンドを使うと、上の様にアプリそのものをRosetta指定しなくても Intelなコマンドを実行できるようになります。

Rosettaを使用して開くのチェックを外して開いたターミナルで

$ uname -m
arm64

となっている状態で

$ arch -arch x86_64 uname -m
x86_64

の様にarch -arch x86_64に続けてコマンドを打つことでx86_64の状態でコマンドが実行されます。

逆も同様で、 Rosettaを使用して開くのチェックを入れて立ち上げて

$ uname -m
x86_64

となっている状態で

$ arch -arch arm64 uname -m
arm64

とすることもできます。

したがって、実はHomebrewもRosettaでターミナルを立ち上げなくても

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

とすればIntelな環境が/usr/local/にインストールされます。 一時的にIntel環境も入れたい、というのであればこちらのほうが便利です。

今回はその後もRosettaを使って使うことが前提なので上のようにしています。

で、このarchコマンドを使って色々やってみると、

$ arch -arch arm64 /bin/bash
$ uname -m
arm64

$ arch -arch x86_64 /bin/bash
$ uname -m
x86_64

といった感じで、コマンドラインの中でシェルの変更とアーキテクチャの変更を 一緒にすることもできます。

Macに最初から入っている/bin/bashなどはこの様に両アーキテクチャで使える様に作られている様です。

一方で、Homebrewで入れたものは

$ arch -arch x86_64 /opt/homebrew/bin/bash
arch: posix_spawnp: /opt/homebrew/bin/bash: Bad CPU type in executable

$ arch -arch arm64 /usr/local/bin/bash
arch: posix_spawnp: /usr/local/bin/bash: Bad CPU type in executable

といった感じで間違ったアーキテクチャでは使えません。

なんですが、なぜか上にあるように、Rosetta環境で/opt/homebrew/bin/bashをデフォルトにしても そのまま立ち上げることができて、かつその環境はx86_64になっていて ちょっとそこがどうなってるのかはよく分かってません。

また、上の様にarchを使ってアーキテクチャを切り替える事もできますが、 arm64の環境からx86_64にしたいだけなら

$ uname -m
arm64
$ /usr/local/bin/bash
$ uname -m
x86_64

とするだけで必ずx86_64の環境になります。

逆にx86_64の環境で/opt/homebrewのBashを呼んでも

$ uname -m
x86_64
$ /opt/homebrew/bin/bash
$ uname -m
x86_64

とアーキテクチャは変わりません。これは上で言ってるログインシェルのことと同様で 何故かx86_64で使えてしまう状態。

よくわからない状態なので敢えて使わない方が良いかとは思いますが。

Intelなcronジョブを流す

普通に

0 * * * * uname -m

みたいなcronジョブを設定するとターミナルのRosetta使用状況とか関係なしに arm64と出ます。

そもそもターミナルアプリごとの設定とは関係がないので。

ただ、Intel用Homebrewのアップデートを定期的にしたり、Intel用のツールを使って cronジョブを流したいこともあると思います。

そういった場合は

SHELL=/usr/local/bin/bash
0 * * * * uname -m

とすればx86_64の環境で流れます。

もしくは

0 * * * * arch -arch x86_64 uname -m

の様に1つずつ設定するか(arm64なものも設定したい場合はこちらでやるしかない)。

Macではlaunchdがあるのでそれでcron的なことをやることもできますが、その場合も そのままだとx86_64の環境で流れるので

test.plist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>test</string>
  <key>ProgramArguments</key>
  <array>
    <string>arch</string>
    <string>-arch</string>
    <string>x86_64</string>
    <string>uname</string>
    <string>-m</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>0</integer>
    <key>Minute</key>
    <integer>0</integer>
  </dict>
  <key>StandardOutPath</key>
  <string>/tmp/test.out</string>
  <key>StandardErrorPath</key>
  <string>/tmp/test.err</string>
</dict>
</plist>

みたいなものを作ればx86_64な環境で動きます。

Sponsored Links
Sponsored Links

« vim_ahkで簡単にアプリケーション上で有効に出来るようにした GitHub Actions用アクションのDocker to Compositeの変更 »