AIX でライブラリの数が多くなりすぎたので sort する2019年02月01日 12時52分19秒

AIX のリンカーは、Solaris や Linux のリンカー等よりも優れている。Solaris や Linux の ar ライブラリファイルのシンボルはオブジェクトファイル単位で管理されている。別の言い方をすると、c や cpp ファイル毎にオブジェクトファイルが作られる。そして、オブジェクトファイル毎にしか取り込めないので、呼ばれない関数なども同じファイルに定義されているだけなのにしっかりとシンボルの解決がなされる。それに引き替え AIX のオブジェクトは、各関数毎に切り分けられるので、呼ばれない関数をわざわざ実行ファイルに取り込む事は無い。

コンパイラなどの実装や、実行ファイルの形式などにもよるのだが、AIX のプログラムの大きさだけ極端に小さい事が多々ある。一割、二割違うぐらいだったら環境の影響だが、数倍も大きさが違うと流石にそれはあり得ない。こんな状況に陥る原因は、無計画な実装。ファイルの分割などを考えなかったり、力技で C 言語の巨大なファイルを生成していたりするようなコードだと頻繁に起こる。AIX では 200MB の実行形式ファイルなのに Solaris や Linux では 2GB の実行形式ファイルが出来るとかだと顕著な場合だ。

この様に異常な大きさの実行形式のファイルが出来ていても、実は、実際に実行コードは大したことが無い場合が多い。これらの巨大なファイルの 9 割以上を占めているのは、デバッグ情報と、リンカーの追加情報だったりする。strip を 2GB の実行形式ファイルにかけたら、50 MB になったりすることも珍しくは無い。

AIX は全てのシンボルテーブルの情報を保持しているみたいで、ライブラリを二度置き直す必要がない。Solaris や Linux では、相互依存しているライブラリは、その再帰的な依存関係の深さの分だけ相互に -l で渡してやらないとリンクに失敗する。ライブラリ A の関数が ライブラリ B の関数を必要とし、ライブラリ B の関数は、他のライブラリ A の他のオブジェクト内の関数を必要とする。こんな場合は、Solaris と Linux では-lA -lB -lA と書く必要がある。そのため、ライブラリの列挙は Solaris や Linux もしっかりとリンクできるように、何度も繰り返しが出てくる場合がある。

前置きが随分と長くなってしまった。つまり、LIBS が Solaris や Linux のリンカーの為に長くなることがある。実は、AIX のシェルが受け取れる引数の数が Solaris や Linux よりも少ない。そのため、make 等が、リンカーを呼び出そうとすると失敗することがある。

ifeq ($(shell uname -s),AIX)
# list of libraries gets too big and gmake on AIX fails to exec shell
LIBS := $(sort $(LIBS))
endif
これは、gnu make での例だが、そんなときは、sort をかけて重複を除いてライブラリの引数を短くする必要がある。