naoki86star

インターネットの片隅でなにかしら書いてみる

shc - "Generic shell script compiler"

 最近macOSに触れる羽目になりました。なんかその過程で、shcというコマンドの存在を知りました。shell scriptを実行可能ファイルに変換してくれるツール・unix系コマンドです。その仕組み上当然別に速度が速くなるものでもなくおそらく多くの場合わざわざreadableなファイルを扱いにくくするであろうことに、今まで*1興味持つことなかったです。

 macOSのアプリケーションの起動の仕組みを調べてる過程で、(今時点の自分として)バイナリファイルでないと起動してくれない疑惑あってそれで調べてみる対象に上がってきました。

 今までこれshcの存在知らなく、macOSのこの件を考えていたら検索に引っかかってきたのでもしかして皆似たことをお考えなのかも。*2

加えてmacOSの最近の話題にもなるM1プロセッサでも動かせるようにしておくことを考えていて、それでこういうことができたという整理メモ。すなわち、shcでx86_64 arch64両方同じファイルで動かせるバイナリ作ってみました。

  • Appleシリコンとは?Appleが開発したarm プロセッサとのこと。
  • Rosetta(Rosetta2)とは?M1プロセッサ上で従来のmacOS用のバイナリすなわちintelのバイナリを動かすことのできる仕組み(ソフトウェア?)M1プロセッサのmacOS上で、従来のintelバイナリがRosetta2という仕組みというかソフトウェアのおかげでほとんど意識しなくても動く。
  • Universal macOS Binary? Intel用バイナリがあればM1でも動くがネイティブのほうが当然適切であるとき、ひとつのバイナリで両方のアーキテクチャを含んでいればそれひとつで対応できる。
  • shc? 対象スクリプトを動かすための.cファイルを出力してそれをコンパイル・リンクしてる。.cのファイル内容を見ることができる。

 なので、macOSで言うところのUniversal macOS Binaryにするには、.cのファイルをそれぞれtarget分コンパイルしてlipoってコマンド*3でくっつけてあげれば良さそう、と考えた。

$ shc -r -f myscript.sh -o myexecutable.arm64
$ cc run-hello.sh.x.c -o myexecutable.x86_64 -target x86_64-apple-macos10.15
$ lipo -create -output myexecutable myexecutable.arm64 myexecutable.x86_64

'-r' オプションをつけなければ、コンパイルしたノードでしか動かないようになる模様。
長すぎるとか込み入ったことをするようなスクリプトを変換すると、もしかして色々躓くのかもね。


 まぁスクリプトのままラウンチャーとして登録できるなら別にexecutableに変換する必要性は全くなし。今回はむしろrosetta2という仕組みの存在を知ったことが収穫でした。

*1:例えばpy2exeとかいうのもある

*2:アプリケーションとしてインストールするソフトウェアをbashスクリプトで起動できないというのは多分自分の理解誤りだと思っていてmacOS上の登録の作法に反しているだけだと思っているところ

*3:macOSでのlipoって?