xmkmfとimakeによるMakefile生成
8年前のX Window Systemのコードをビルドしようとしてドハマリしています。
Makefileについてgdgdメモします。
Makefileを得るいくつかの方法
ソースコードをmakeするには、Makefileを使用します。
自分が知っているMakefileの作り方は、次の4つです。
- 方法1. configureを使用して生成する
- 方法2. xmkmfを使用して生成する
- 方法3. imakeを直接使用して生成する
- 方法4. 自分で書く
よく使うのは、方法1です。configureスクリプトを実行すると、Makefile.iniMakefile.inからMakefileが生成されます。
また、ダウンロードしてきたオープンソースのコードにMakefileやconfigureスクリプトがなく、代わりにImakefileがある場合は、方法2あるいは3によってMakefileを得ることになります。xmkmfを実行すると、内部でimakeが実行され、ImakefileからMakefileが生成されます。
ちなみに、オープンソースのコードに、親切にも依存ライブラリや関連コマンドが含まれていた場合は、自分のマシンに同じライブラリやコマンドがすでにインストールされていたとしても、ソースコードに同梱されていたものを使ってビルドします(よね?)。ソースコードと一緒に配布されているツールであれば、ライブラリ同士のバージョンの相性が良く、問題なくビルドできる可能性が高いためです。
可能性が高い、と書きました。残念ながら、xmkmfやimakeを叩いただけでは、ビルド可能なMakefileが生成されないことがあります。その場合は、泣きながらMakefileを修正します。
今ハマっているのも、方法2で作ったMakefileでmakeできないケースです。
その話の前に、xmkmfとimake自体について調べたことをメモしておきます。
xmkmfの使い方
次のコマンドを実行すると、実行ディレクトリにあるImakefileからMakefileが生成されます。
$ xmkmf
次のようにaオプションを付けると、Makefileが生成された後、make Makefiles、make includes、make dependが順に実行されます。
$ xmkmf -a
imakeの使い方
次のコマンドを実行すると、実行ディレクトリにあるImakefileからMakefileが生成されます。
$ imake
imakeは、ルールが書かれた設定ファイルを実行時に読み込みます。Iオプションの引数で、ルールファイルがあるディレクトリを指定します。
$ imake -I/usr/share/X11/config
「I」とパスの間に半角スペースを入れないように注意します。
ついでに、Imakefileの記述ルール周りに少し触れると、こんなカンジです。
マクロ定義
imakeのルールが記述されたファイル(Imake.rule)に、MACHINE-INDEPENDENT RULESという項目があり、標準のマクロ定義がコメントで掲載されています。記述の実体は、imakeのテンプレートファイル(Imake.tmpl)にあります。
(ルールの例)サブディレクトリがある場合
Imakefileが、サブディレクトリを持つディレクトリに配置されている場合、次の記述が必要です。
- SUBDIRSという変数を定義し、サブディレクトリ名をスペース区切りで列挙する
- #define IHaveSubdirs を宣言する
- MakeSubdirs() と DependSubdirs() を呼び出す
実際のImakefileを見てみると、まさにそのまま書かれています。
#define IHaveSubdirs
(略)
SUBDIRS = include config lib $(NLSSUBDIR) \
programs $(FONTSDIR) $(DOCSDIR)
(略)
MakeSubdirs($(SUBDIRS))
(略)
DependSubdirs($(SUBDIRS))
ターゲットの記述
makeコマンドによって実行されるMakefileのターゲットは、Imake.ruleに基づいて自動生成された標準のターゲットと、Imakefileに明示的に記述されたターゲットの2種類があります。別の言い方をすると、Imake.ruleで提供されないものは、Imakefileで書かなければなりません。
xmkmfとimakeによる生成結果の差異
ところで、xmkmfコマンドで間接的にimakeを使う場合と、imakeコマンドを直接使う場合とで、生成されるMakefileに違いはあるのでしょうか。
よく分からないので確認してみました。というのも、もし違いがあるならば、より妥当なMakefileを出力できる方を使いたいからです。
昔のXのコードについていたImakefileを、xmkmfとimakeそれぞれに渡してみました。
※ 以下では、xmkmfと比較するために、マシンにインストールされたimakeを使用しました。が、実際の(ハマり中の…)作業では、コードに同梱されていた古いimakeでMakefileを生成しています。
xmkmfでのMakefile生成
$ sudo xmkmf mv -f Makefile Makefile.bak imake -DUseInstalled -I/usr/share/X11/config $ ls (略) -rw-r--r--. 1 root root 33580 May 9 07:35 Makefile
生成されたMakefileは、1326行でした。
imakeでのMakefile生成
$ whereis imake imake: /usr/bin/imake /usr/share/man/man1/imake.1x.gz $ sudo imake -I/usr/share/X11/config $ ls (略) -rw-r--r--. 1 root root 34403 May 9 10:03 Makefile
生成されたMakefileは、1333行でした。行数だけを見ると、差はほとんどありません。
差分の確認
xmkmfとimake、それぞれのコマンドで生成した2つのMakefileのdiffを取ってみました。
# diff {xmkmfで生成したMakefile} {imakeで生成したMakefile} > diff-xmkmf-imake # cat diff-xmkmf-imake 123,124c123,124 < IMAKE = imake < DEPEND = gccmakedep --- > IMAKE = $(IMAKESRC)/imake > DEPEND = $(DEPENDSRC)/makedepend 126c126 < REVPATH = revpath --- > REVPATH = $(CONFIGSRC)/util/revpath (略) 948c951 < FCCACHE = $(BINDIR)/fc-cache --- > FCCACHE = set -x; $(CLIENTENVSETUP) $(PRELOADXFTSETUP) FONTCONFIG_PATH=$(FONTCONFIGLIBSRC) $(XBUILDBINDIR)/fc-cache (略)
コマンドやパスの定数に設定された値が異なっています。
分からないこと
xmkmfとimakeのどちらを使えばよいのかは、ソースコードとマシン依存なので、がんばって確認して決めよう!てことでFAなのでしょうか。
また、xmkmfから生成したMakefileで、コマンド定数が直書きされていたのも気になります。あのMakefileをそのまま使うと、makeの再帰処理の中では、特殊なバージョンのimakeを適用することができなさそうです。これも、各自で修正して変数を使うべしってことなんですかね。
何かxmkmfなりimakeなりの実行時オプションを追加するか、あるいはImakefileを適切に変更すれば、カンタンに解決するのかな…とも思うものの、よく分かりません。。。
続きはまた今度
個別具体的なハマリについて泣き言を書くつもりでしたが、長くなったので今度に。
参考
- xmkmfコマンドの使い方: UNIX/Linuxの部屋
- Manpage of IMAKE: imakeのman(和訳)
- imake: imake on Cygwin
- Xウィンドウ・システム、バージョン11、リリース6.1 リリース・ノート
Imakefileの記述方法で参考になる資料は、ルールファイル、テンプレートファイル自体のコメント、config/cf以下のreadmeです。それ以外にはほとんど見当たりません。
# オライリーのmake本の付録にimakeの項があり、期待したのだけれど、「非常に広く使用されているツールとしては、imakeはいまだに異常なほど文書化されていません」とか書かれていて、ガックシ・・・。