Apple M1 CPU と Intel CPU では
CPUアーキテクチャ(命令文やデータ形式)も異なり
バイナリファイル(実行可能なファイル)の中身も別物になる
※M1搭載のMacで従来(Intel CPU搭載Mac)向けのバイナリが実行できるのは
Rosetta 2というアプリケーションでM1向けバイナリに変換したものを実行しているため
また、macOSの実行ファイル形式Mach-Oでは複数のアーキテクチャのバイナリを格納することが可能で
複数のアーキテクチャ向けバイナリを格納したバイナリをユニバーサルバイナリと呼んだりする
バイナリファイルのアーキテクチャを調べる
file ファイル名
コマンドで調べることができる
# Intel CPU向けバイナリの場合
$ file file ./foo/bar/hoge
./foo/bar/hoge: Mach-O 64-bit executable x86_64
# M1 CPU向けバイナリの場合
$ file ./foo/bar/hoge
./foo/bar/hoge: Mach-O 64-bit executable arm64
# ユニバーサルバイナリの場合
file ./foo/bar/hoge
./foo/bar/hoge: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
./foo/bar/hoge (for architecture x86_64): Mach-O 64-bit executable x86_64
./foo/bar/hoge (for architecture arm64): Mach-O 64-bit executable arm64
クロスビルド
clang(C言語)でのバイナリビルド
--target
オプションで指定する
例
# M1 CPU向けバイナリビルド
clang -target=arm64-apple-macos12 -o arm64.out main.c
# Intel CPU向けバイナリビルド
clang -target=x86_64-apple-macos12 -o amd64.out main.c
Go言語でのバイナリビルド
環境変数GOARCH
でアーキテクチャを指定する
例
# M1 CPU向けバイナリビルド
GOARCH=arm64 go build -o arm64.out main.go
# Intel CPU向けバイナリビルド
GOARCH=amd64 go build -o amd64.out main.go
ユニバーサルバイナリにする
lipo
コマンドで複数のアーキテクチャのバイナリファイルをまとめて1つのバイナリファイルにする
例
lipo -create -output universal.out arm64.out amd64.out