【メモ】Makefile

Makefileについて調べた際のメモです。

www.gnu.org

  • Microsoft nmake、Borland make、GNU make、Solaris makeなどいろんな種類があるらしい
  • フォーマットはターゲット名: 依存ファイル名を書いて次の行からコマンドを書いていく。
    • 「作りたいもの、必要な材料、作り方」の順
  • コマンド行の先頭はタブで空ける必要がある(ほんとに? 本当だった。vs codeの場合勝手にタブにしてくれた。)
  • ターゲットが複数の場合別々に書けば変更があったファイルだけビルドし直すので効率がいい。
  • makeだけで実行した場合、先頭にあるターゲットが実行される。
    • 先頭のターゲットとしてall: 本当のターゲットを書く習慣がある。
  • TOOLCHAIN = arm-none-eabiというように変数を定義できる。これをマクロと呼ぶ。
  • 必ずしもターゲットで指定した名前のファイルがコマンドにより作られる必要はない。
    • cleaninstallなどの命名でターゲットが定義されることも多い。
  • 依存ファイルがない場合はなにも書かなくていいし、ターゲットと同じ行に書いてもいい。
  • コマンド行のないターゲットを書くこともでき、主に複数のターゲットをまとめる際に使われる。
  • CFLAGSという変数が定義されている場合、*.c*.oコンパイルするときに暗黙的に使用される。
  • その他デフォルトのルールや変数は山ほどあり、make -pで確認することができる。
  • ビルドし直すべきかどうかをファイルの更新日時を使って判断する。
    • 再ビルドを矯正したいときはターゲットのファイルに対してtouchコマンドを実行すればいい。
  • 必ずしもC言語のプログラムである必要はなく、材料とそれから作りたいものがあるときにはかなり汎用的に使えるコマンドになっている。
  • -fオプションで対象のファイルを指定し、省略した場合GNUmakefilemakefileMakefileの順で探す。
  • 依存ファイルがなく、生成するファイルもないターゲットのことをphony targetと呼ぶ。phony tagetは同名のファイルが存在すると動かなくなってしまうため、.PHONY: ターゲット名を書くことでこれを回避できる。
    • .PHONYはまとめてどこか一箇所に書いておけばオッケー。
  • ヘッダファイルを依存ファイルに含めることで、ヘッダファイルだけの更新があったときでもリビルドを走らせることができる。
  • コマンド内で$@によりターゲット名を参照できる。これを内部マクロという。また$<では依存ファイルの先頭のファイル名を参照できる。
  • .SUFFIX: 依存先の拡張子 依存元拡張子のフォーマットで拡張子ごとの依存関係を記述できる。
  • 発展形としてOSごとの差異を吸収したツールも存在する。
  • シェルスクリプトと同様に\で改行できる。
  • ターゲット名は複数書いてもよく、これは単に複数のルールをまとめて書いたことになる。
  • 関数が用意されている。see: GNU make: Functions
  • shell関数を使うことでマクロ定義の際などでコマンドを実行することができる。
  • コマンドの先頭に@をつけるとその行の出力を省略できる。-をつけるとコマンド失敗を無視できる。
  • 慣例として変更の可能性があるマクロは大文字、Makefile内で閉じているマクロは小文字で書く。
  • マクロ宣言の際にコロンをイコールの前につけて:=とすると、定義内のマクロが即時展開される。それ以外では実行の際に展開される。
  • ?=により値が定義されていないときだけ新たに定義する、という動作にできる。
  • makedependコマンドよりルールを動的に生成することができる。
  • includeで他のMakefileをインクルードできる。
  • ifdefifeqなどの分岐分を使える。

Refs