jq
とは
jq
コマンドは,便利なJSONパーサーとして(そして単なるパーサーを超えてプログラミング言語としても)知られています。jq
で何ができるかは,次のページが参考になるでしょう。
jq
のインストール法3選
さて,macOS に jq
をインストールする方法としては,次のような方法が考えられます。
- Homebrew や MacPorts といったパッケージ管理システムを利用する
- 公式配布バイナリを利用する
- 自分でソースコードからビルドする
既に Homebrew や MacPorts を使っている方であれば,1. が簡単でしょう。
$ brew install jq
$ sudo port install jq
パッケージ管理システムによるインストールの欠点
自分一人で使う分には Homebrew や MacPorts で困らないのですが,この jq
のバイナリを自作アプリに同梱して配布するなど,他のマシンへと移植する場合を考えると,バイナリのポータビリティが気になります。
ライブラリの依存性
MacPortsの場合
例えば,MacPorts でインストールされる /opt/local/bin/jq
が何に依存しているか,その依存ライブラリを調べてみましょう。otool
コマンドが役立ちます。
$ otool -L /opt/local/bin/jq
/opt/local/bin/jq:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)
/opt/local/lib/libonig.5.dylib (compatibility version 10.0.0, current version 10.0.0)
/opt/local/lib/
から始まるパスが現れていることから,この jq
バイナリは,MacPorts でインストールされる oniguruma
ライブラリ(これは正規表現ライブラリ鬼車です)に依存してしまっていることが分かります。これでは,この jq
バイナリを単に他のマシンにコピーするだけでは動きません。
Homebrewの場合
Homebrew でインストールされる /usr/local/bin/jq
についても同様に,Homebrew の依存関係解決に基づきインストールされる oniguruma
ライブラリの存在に依拠しています。
$ otool -L /usr/local/bin/jq
/usr/local/bin/jq:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
/usr/local/opt/oniguruma/lib/libonig.5.dylib (compatibility version 9.0.0, current version 9.0.0)
バイナリの対象アーキテクチャ
また,バイナリの対象アーキテクチャを調べてみましょう。file
コマンドが使えます。
$ file /opt/local/bin/jq
/opt/local/bin/jq: Mach-O 64-bit executable arm64
この MacPorts は Apple Silicon 上で実行しているので,arm64
バイナリが生成されています。これでは,Intel Mac 上にこのバイナリを持っていったときに実行できません。
逆に,x86_64
バイナリを Apple Silicon 上で実行するのは,Rosetta 2 をインストールしてあれば可能ではありますが,Rosetta 2 がインストールされているマシンでなければ動きませんし,動作パフォーマンスも下がるので,好ましくありません。
起動OSの最低バージョン
このバイナリが起動できる最低OSバージョンを調べてみます。otool -l
が役立ちます。
$ otool -l /opt/local/bin/jq | grep minos
minos 14.0
この MacPorts は,macOS 14 Sonoma 上で実行しているため,その上でデフォルトで生成されたバイナリは,起動できるOSバージョンの最低値が macOS 14 と設定されてしまっています。これでは,macOS 13 以前の環境に持っていったときに使えません。Homebrew の場合も同様に,実行しているホストOSを最低動作環境とするバイナリがインストールされます。
公式配布バイナリ
次に,jq
の公式配布バイナリの状況を調べてみます。公式サイトでは,AMD64
(Intel CPU) 向けバイナリと ARM64
(Apple Silicon) 向けバイナリがそれぞれ配布されています。
最新の jq Ver.1.7 の公式バイナリについて,それぞれの状況を調べてみましょう。
Intel CPU 向け公式バイナリ
$ file jq-macos-amd64
jq-macos-amd64: Mach-O 64-bit executable x86_64
$ otool -L jq-macos-amd64
jq-macos-amd64:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
$ otool -l jq-macos-amd64 | grep minos
minos 13.0
Apple Silicon 向け公式バイナリ
$ file jq-macos-arm64
jq-macos-arm64: Mach-O 64-bit executable arm64
$ otool -L jq-macos-arm64
jq-macos-arm64:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
$ otool -l jq-macos-arm64 | grep minos
minos 13.0
このように,Intel CPU 向けバイナリ,Apple Silicon 向けバイナリのどちらも,
- 単一アーキテクチャ用バイナリ
- 依存性はOS標準のライブラリのみ
- 要求OSバージョンは macOS 13 Ventura 以降
となっていることが分かります。macOS 13 Ventura は,本記事執筆時点では最新OSの1つ前のバージョンです。ちょっと要求水準が高めですね。
もっと広範囲の環境で動くようにしたい
他のマシンへのポータビリティを高めるべく,次のような条件を見たす jq
バイナリが欲しいです。
- Intel CPU / Apple Silicon のどちらでもネイティブ起動できる Universal Binary である
- OS標準のライブラリにのみしか依存しない
- できるだけ広い範囲のOS環境で起動できる
このようなバイナリを得るためには,ソースコードから自前で jq
をビルドする必要があるでしょう。
ソースコードからの jq
バイナリのビルド
公式サイトの説明によると,バイナリのビルド&インストール方法は次のように説明されています。
git clone --recursive https://github.com/jqlang/jq.git
cd jq
autoreconf -i
./configure
make
sudo make install
この案内に沿ってバイナリのビルドを進めましょう。
autoreconf
できるようにする
このためには,autoreconf
コマンドが必要です。そのためには,autoconf
をインストールしておきましょう。ここは Homebrew や MacPorts を使うのが簡単です。
$ brew install autoconf
$ sudo port install autoconf
続きをやってみます。
$ git clone --recursive https://github.com/jqlang/jq.git
$ cd jq
$ autoreconf -i
Can't exec "aclocal": No such file or directory at /usr/local/Cellar/autoconf/2.71/share/autoconf/Autom4te/FileUtils.pm line 274.
autoreconf: error: aclocal failed with exit status: 2
何やらエラーが出ました。これは autoreconf
は aclocal
も必要とするからです。このためには,automake
をインストールしておきましょう。aclocal
は automake
に付随してインストールされます。
$ brew install automake
$ sudo port install automake
改めて autoreconf
にチャレンジします。
$ autoreconf -i
src/Makefile.am:24: error: Libtool library used but 'LIBTOOL' is undefined
またエラーが出ました。今度は libtoool
をインストールします。
$ brew install libtool
$ sudo port install libtool
これで,autoreconf -i
が通るようになります。
Homebrew を使っている場合の注意:oniguruma
のアンインストール
Homebrew を使っている場合1で,既に Homebrew によって oniguruma
がインストールされていると,以下の方法でビルドされる jq
バイナリが Homebrew の oniguruma
を参照してしまいます2。よって,事前に Homebrew の oniguruma
をアンインストールしておきます。
$ brew uninstall oniguruma
まずはビルドしてみる
では,この状態でビルドしてみましょう。configure
& make
をしてみます。
$ ./configure
$ make
すると,同ディレクトリ内に jq
バイナリが生成されます。
まずは依存ライブラリを確認します。
$ otool -L jq
jq:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)
システム標準のライブラリのみを参照しており,期待通りです。
ただし,この方法でビルドするだけでは,
- ホストマシンと同じCPUアーキテクチャのみを動作対象とする
- ホストマシンのOSバージョンを最低動作要件とする
バイナリが生成されてしまいます。これでは困るので,対象アーキテクチャと最低動作要件を明示指定したバイナリを作りましょう。
そのためには,CFLAGS
, CXXFLAGS
, LDFLAGS
にオプションを付け加えます。
Apple Silicon 向けバイナリのビルド
Apple Silicon 搭載 Mac は,最低でも macOS 11 Big Sur です。よって,動作要件としては macOS 11 以上を指定すれば十分です。
clangの -arch
オプションによるクロスコンパイル機能を使えば,コンパイルを実行しているホストマシンのCPUが Intel CPU / Apple Silicon のいずれであっても,x86_64
/ arm64
の双方のバイナリを生成できます。
次のように,CFLAGS
, CXXFLAGS
, LDFLAGS
のオプションを指定して,autoreconf -i
を実行します。
$ export CFLAGS="-arch arm64 -mmacosx-version-min=11.0"
$ export CXXFLAGS="-arch arm64 -mmacosx-version-min=11.0"
$ export LDFLAGS="-arch arm64 -mmacosx-version-min=11.0"
$ autoreconf -i
次に configure
スクリプトを実行します。ただし,クロスコンパイルになる場合(ホストマシンのアーキテクチャと生成バイナリのアーキテクチャが異なる場合)は,configure
スクリプトの実行に,--host
オプションでホストマシンのアーキテクチャを明示指定しておく必要があります。
$ ./configure
$ ./configure --host=x86_64
そしていよいよ make
します。既に make
を実行していたのであれば,一旦 make clean
しておきましょう。
$ make clean
$ make
そして,生成された jq
バイナリの状況をチェックします。
依存ライブラリのチェック
$ otool -L jq
jq:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)
対象アーキテクチャのチェック
$ file jq
jq: Mach-O 64-bit executable arm64
最低動作OS要件のチェック
$ otool -l jq | grep minos
minos 11.0
いずれも期待通りの結果となりました。このバイナリを別名で退避しておきます。
$ cp jq jq-arm64
Intel CPU 向けバイナリのビルド
Intel CPU の Mac は昔からあります。最初期のものは MacOS X 10.5 Leopard のあたりです。よって,動作要件を MacOS X 10.5 Leopard 以上とするバイナリを生成してみましょう。
$ export CFLAGS="-arch x86_64 -mmacosx-version-min=10.5"
$ export CXXFLAGS="-arch x86_64 -mmacosx-version-min=10.5"
$ export LDFLAGS="-arch x86_64 -mmacosx-version-min=10.5"
$ autoreconf -i
そして,configure
スクリプトを実行します。ホストが Apple Silicon の場合はクロスコンパイルを指定します。
$ ./configure --host=arm64
$ ./configure
そして make
します。
$ make clean
$ make
そして,生成された jq
バイナリの状況をチェックします。
依存ライブラリのチェック
$ otool -L jq
jq:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.0.0)
対象アーキテクチャのチェック
$ file jq
jq: Mach-O 64-bit executable x86_64
最低動作OS要件のチェック
最低動作OS要件のチェックは otool -l
で行えますが,少し昔のOS用のバイナリの場合,出力の形式が異なり,grep minos
で探せません。otool -l
の出力の中の LC_VERSION_MIN_MACOSX
という行の2行下の version
でチェックします。
$ otool -l jq
(中略)
cmd LC_VERSION_MIN_MACOSX
cmdsize 16
version 10.5
sdk 14.0
(後略)
すると,正しく MacOS X 10.5 Leopard を最低動作要件とするバイナリが生成されていることが分かります。
このバイナリを別名で退避しておきます。
$ cp jq jq-x86_64
Universal Binary として結合する
最後に,こうして得られた
- macOS 11.0 Big Sur 以上で動作する Apple Silicon 向けバイナリ
jq-arm64
- MacOS X 10.5 Leopard 以上で動作する Intel CPU 向けバイナリ
jq-x86_64
を Universal Binary として結合しましょう。バイナリの結合や分解には lipo
コマンドを使います。
$ lipo -create -output jq jq-arm64 jq-x86_64
こうして得られた jq
バイナリを確認します。
$ file jq
jq: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
jq (for architecture x86_64): Mach-O 64-bit executable x86_64
jq (for architecture arm64): Mach-O 64-bit executable arm64
確かに Universal Binary となっています!
これで,めでたくできるだけ広範囲の macOS 環境でネイティブ実行できる jq
バイナリが得られました!これならば,どこの環境に持っていっても確実に動作するので,安心して頒布可能です。以上のような,クロスコンパイルも用いた Universal Binary のビルド方法は,jq
に限らず,広く活用できることでしょう。