2019年11月29日金曜日

最小の makefile を作りたい

小さいCプログラムのための makefile を作りたい、という話。
 

カレントディレクトリに main.c という簡単な C プログラムがあったとき、これをコンパイルして main という実行ファイルを作ることを考えます。 まあ cc main.c -o main で終わり、なので、

てことになるわけですが、やれここでコンパイル時にデバッグフラグだの、数学関数をリンクするだの言い始めると途端にオプションが増えます。

そんなときによく使われるのが makefile に書かれる変数なのですが、これもまた雑に調べるとオプションを指定する環境変数がごちゃごちゃしていて分かりにくい。 特に LDFLAGS と LDLIBS の扱いで混乱してしまい、困ってしまいました。 リンクするライブラリ(-lmなど)はソースファイルの後に書かなければいけないのですが、 LDFLAGSに書けばいいよみたいな資料が若干見当たり、その通りに書くとコンパイルできない(リンクに失敗する)という…

こんなとき役に立つのが make のデフォルトルールの表示です。 Linux の make (GNU make) には オプション -p があるので、
であることが分かります。一方、FreeBSDのmake (BSD make) はオプションと挙動が違いまして、 となります。このデバッグ出力は標準エラー出力に吐き出されますので注意してください。

いずれにせよ「.c ルールはソースファイル foo.c から実行ファイル foo を作る、というルールなので、program: foo.c などとだけ makefile に書いてもルールに合致しないので何も起こらない」 「LDFLAGSはソースファイルより前に付く」「LDLIBSはソースファイルより後に付く」ことが分かりますから、
LDFLAGS にはライブラリの所在を表すパス(-L オプション)などを書き、
LDLIBS にはリンクしたいライブラリの実体なり -l オプションなりを書く、
という使い方であることが分かるわけです。

オブジェクトファイル .o を作る場合はどうなるのか? については、上記ルールの表示から探してみて、CFLAGS の付けかたについて考えてみるとよいでしょう。例えば、プログラム中で自作関数などが呼び出された回数や処理時間を計測するプロファイラ gprof を用いる場合は、コンパイラとして gcc を想定し、コンパイル時とリンク時の両方に -pg オプションが必要なので、



という書き方になります。(FreeBSDでは cc が clang の時に -pg オプションを付けると、正しく動作しない実行ファイルが出来て困ったので、念のため。 )
gmake には .c.out ルールが標準で備わっていなかったんですね。知らなかった……

0 件のコメント: