余白の書きなぐり

aueweのブログ

Makefile文法ミニマム

自分用のメモとして、Makefileの文法で忘れがちな部分をまとめておく。

想定してるのは GNU make 4.2.1 で、LinuxMac OS X で普通に make コマンドを叩いたときに走るやつだ。 FreeBSDSolaris では gmake コマンドらしい。 Windowsでは http://gnuwin32.sourceforge.net/packages/make.htm からインストールできる。

以下では具体例として

$ gcc src/main.c -o obj/main.o
$ gcc src/A.c    -o obj/A.o
$ gcc obj/main.o    obj/A.o -o exec.out

を自動化するためのMakefileを考える。

文法ミニマム

CC    := gcc
ALL_C := $(wildcard src/*.c)                  # src/main.c src/A.c
ALL_O := $(patsubst src/%.c,obj/%.o,$(ALL_C)) # obj/main.o obj/A.o

exec.out: $(ALL_O) # 一番最初に設定した依存関係は、make (引数なし)で実行可
  $(CC) $^ -o $@

%.o: %.c           # パターンマッチ。他に A.o:... があれば、そちらが優先
  $(CC) -c $< -o $@

.PHONY: clean      # clean というファイルが存在しても、無視して make clean できる
clean:
   @rm -rf *.out ./obj/*.o     # @をつければ、結果が表示されない

ここで使った文法をまとめておこう。 以下の11項目を覚えるだけで、かなり高度なMakefileが作れるようになるぞ。 まずは文字列の扱いだが

  • HOGE := foo bar で定義し $(HOGE) で参照
  • ファイル検索は $(wildcard src/*.c)
  • 置換は $(patsubst a%b,c%d,aXXXb aYYYb) —> cXXXd cYYYd

patsubstは半角スペースも文字とみなすので、$(patsubst A, B, C) みたいに空白を入れてはいけない。 次に特殊変数だが

  • $@ は生成ファイル。アットマークは arrive atのatと同じ雰囲気
  • $< は依存ファイルのうち一番 <— 側に書かれたやつ
  • $^ は依存ファイル全て。^は左端から右端までをつまみ上げる雰囲気
  • %.o:... があれば、A.oが必要となった際、%をAに置換して実行される

例えば特殊変数 $@ の拡張子.oを.cに置換する場合は $(patsubst %.o,%.c,$@) とする。 そのほかの注意点は

  • .PHONY: clean しておけば、cleanというファイルが無視される
  • @rm -rf のように @ をつければサイレントモードになる

ちなみに今回は出現しなかったけど、他のファイルと連携する際は

  • Makefile から sub/Makefile に書かれた make hoge を実行するには cd sub && $(MAKE) hoge "CC=$(CC)"
  • 外部ファイル hoge を読み込むには -include hoge

ヘッダファイル

これだけだと「ヘッダファイル無いやんけ!」という指摘がくるので、記事を書いた。参考にしてくれ。 auewe.hatenablog.com

どうでもいい話。

Makefileの書き方が覚えられない。習得しても、なぜかすぐに忘れる。

Bitbucketの自分用リポジトリを調べたら、5年間あわせて25個のMakefileが見つかった。 普通これだけ書けば、自動的にメイクマスターになれるはずなのに、いまだに 「$@だっけ%@だっけ?」 などと悩んだり、置換やワイルドカードの使い方をググったりしている。 原因は、Makefileは文法がキモいうえに中途半端な機能が中途半端に揃っているせいだと思う。 メイクマスターになるためには、まず汎用性の高い便利な機能だけをしっかり覚えるのが重要なのではないか。

過去の自分と決別すべく、今回こそMakefile文法ミニマムをしっかり暗記しようと思う~