dittoの--archオプションを使うと、Universalバイナリ(複数のアーキテクチャを含むMach-Oバイナリ)をコピーしながら、指定したアーキテクチャだけを残した「thin」なバイナリにできる。ディレクトリやアプリのバンドルをまとめて処理できる。
Universalバイナリを用意する
検証用に、arm64とx86_64の両方を含むUniversalバイナリをビルドする。
$ printf '#include <stdio.h>\nint main(void){puts("hello");return 0;}\n' > hello.c
$ clang -arch arm64 -arch x86_64 -o hello hello.c
$ lipo -info hello
Architectures in the fat file: hello are: x86_64 arm64
--archでアーキテクチャを指定してコピーする
--archにアーキテクチャ名を指定すると、そのアーキテクチャだけを含むバイナリとしてコピーする。
$ ditto --arch arm64 hello hello-arm64
$ lipo -info hello-arm64
Non-fat file: hello-arm64 is architecture: arm64
$ ./hello-arm64
hello
ファイルサイズも小さくなる。
$ stat -f "%z %N" hello hello-arm64
49816 hello
33432 hello-arm64
--archを複数指定すると、指定したアーキテクチャをすべて含むバイナリになる。
$ ditto --arch arm64 --arch x86_64 hello hello-both
$ lipo -info hello-both
Architectures in the fat file: hello-both are: x86_64 arm64
アプリのバンドルをまとめてthin化する
ディレクトリを指定すると、配下のMach-Oバイナリをすべてthin化してコピーする。Mach-Oバイナリ以外のファイルはそのままコピーされる。
Universalバイナリで配布されているCotEditorのアプリを、arm64だけにしてコピーした結果は以下の通り。
$ lipo -info /Applications/CotEditor.app/Contents/MacOS/CotEditor
Architectures in the fat file: /Applications/CotEditor.app/Contents/MacOS/CotEditor are: x86_64 arm64
$ ditto --arch arm64 /Applications/CotEditor.app CotEditor-arm64.app
$ du -sh /Applications/CotEditor.app CotEditor-arm64.app
29M /Applications/CotEditor.app
22M CotEditor-arm64.app
$ lipo -info CotEditor-arm64.app/Contents/MacOS/CotEditor
Non-fat file: CotEditor-arm64.app/Contents/MacOS/CotEditor is architecture: arm64
thin化したアプリも、コード署名の検証に成功した。
$ codesign --verify --deep --strict --verbose=2 CotEditor-arm64.app
CotEditor-arm64.app: valid on disk
CotEditor-arm64.app: satisfies its Designated Requirement
指定したアーキテクチャを含まないバイナリはコピーされない
--archで指定したアーキテクチャを含まないMach-Oバイナリは、コピー対象から外れる。エラーは表示されない。
$ ditto --arch x86_64 hello-arm64 hello-x86
$ echo $?
0
$ ls hello-x86
ls: hello-x86: No such file or directory
ディレクトリをコピーした場合も、該当するバイナリだけが黙って抜け落ちる。ppcを指定すると、Mach-Oバイナリのbin/helloがコピーされず、テキストファイルのreadme.txtだけが残る。
$ find app
app
app/bin
app/bin/hello
app/readme.txt
$ ditto --arch ppc app app-ppc
$ find app-ppc
app-ppc
app-ppc/bin
app-ppc/readme.txt
終了コードも0になるため、--archを使う場合はコピー後にlipo -infoなどで結果を確認しておくとよい。
参考
DITTO Command: Copy directory hierarchies, create and extract archives in macOS\第一線のプログラマーの行動原理を学べる!/
