2025/06/20 08:05 Learn Makefiles

やっほー、ロボ子!今日のITニュースは、Makefilesについてなのじゃ!

Makefilesですか、博士。大規模プログラムの再コンパイルを効率化するものですよね。

そうそう!記事によると、Makefilesは主にC/C++ファイルのコンパイルに使われるけど、ファイルの変更に応じて色々な命令を実行できる便利なやつなのじゃ。

C/C++以外にも使えるんですね。他にMakeの代替となるツールはあるんですか?

もちろん!SCons, CMake, Bazel, Ninjaとか色々あるぞ。JavaならAnt, Maven, Gradleとかじゃな。最近はGo, Rust, TypeScriptみたいな言語も独自のビルドツールを持ってるみたい。

たくさんの選択肢があるんですね。Makeにはどんな種類があるんですか?

GNU MakeがLinuxとMacOSの標準実装なのじゃ。バージョン3と4はほぼ同じみたいだぞ。

Makefileを実行するにはどうすれば良いんですか?

ターミナルで`make`コマンドを使うのじゃ。あ、MakefileはTABでインデントしないとダメだぞ!

TABインデント、了解です。Makefileの基本的な構文はどんな感じですか?

ルールは、ターゲット、コマンド、依存関係(プリリクジット)で構成されるのじゃ。ターゲットはファイル名で、コマンドはターゲットを作るためのステップ。依存関係は、ターゲットのコマンド実行前に必要なファイルのことだぞ。

ターゲット、コマンド、依存関係…ふむふむ。Makefilesの本質は何でしょうか?

ターゲットの依存関係が変更されたかどうかを判断して、必要な場合にだけ再コンパイルすることじゃ!ファイルシステムのタイムスタンプを使うらしいぞ。

タイムスタンプで判断するんですね。変数も使えるんでしょうか?

変数は文字列だけだけど使えるぞ!`:=`または`=`で定義して、`${}`または`()`で参照するのじゃ。

`:=`と`=`の違いは何ですか?

`=`は再帰的変数で、コマンドが使われる時に変数を検索するのじゃ。`:=`は単純展開変数で、定義時に変数を展開するぞ。

なるほど!ターゲットにはどんな種類がありますか?

`all`ターゲットは複数のターゲットを一度に実行できるのじゃ。複数のターゲットがある場合は、ルール内の各ターゲットに対してコマンドが実行されるぞ。`$@`はターゲット名を含む自動変数なのじゃ。

`$@`は自動変数なんですね。ワイルドカードも使えますか?

`*`はファイルシステムで一致するファイル名を検索する時に使うのじゃ。`wildcard`関数で囲むのがオススメだぞ。`%`は文字列内の一致に使うのじゃ。

ワイルドカード、便利そうですね。自動変数には他にどんなものがありますか?

`$^`はすべての依存ファイル名、`$<`は最初の依存ファイル名なのじゃ。

色々ありますね。暗黙のルールもあるんですか?

Cコンパイルに関する自動ルールがあるぞ。`n.o`は`n.c`から自動的に作成されたり、`n`は`n.o`から自動的に作成されたりするのじゃ。重要な変数としては`CC`, `CXX`, `CFLAGS`, `CXXFLAGS`, `CPPFLAGS`, `LDFLAGS`があるぞ。

暗黙のルール、覚えておきます。静的パターンルールとは何ですか?

静的パターンルールの構文は`targets ...: target-pattern: prereq-patterns ...`なのじゃ。`%`ワイルドカードを使うぞ。

パターンルールもあるんですね。

パターンルールはターゲットに`%`を含むのじゃ。暗黙のルールを定義する方法の一つだぞ。

ダブルコロンルールとは?

同じターゲットに対して複数のルールを定義できるのじゃ。

コマンドの実行について教えてください。

`@`をコマンドの前に追加すると、コマンドの出力が抑制されるのじゃ。各コマンドは新しいシェルで実行されるぞ。デフォルトシェルは`/bin/sh`なのじゃ。

エラー処理はどうすれば良いですか?

` -k`はエラーが発生しても実行を継続、`-`はコマンドのエラーを抑制、`-i`はすべてのコマンドでエラーを抑制するのじゃ。

再帰的なMakeの使用とは?

`$(MAKE)`を使うのじゃ。

変数のフレーバーとは?

さっきも言ったけど、`=`は再帰的変数で、`:=`は単純展開変数なのじゃ。

変数の変更はどうやるんですか?

`?=`は変数が未設定の場合のみ設定、`+=`は変数に追加するのじゃ。

コマンドライン引数とオーバーライドは?

`override`キーワードを使うのじゃ。

ターゲット固有の変数は?

特定のターゲットに対して変数を設定できるのじゃ。

条件付きMakefileは?

`ifeq`, `ifneq`, `ifdef`, `ifndef`を使うのじゃ。

関数にはどんなものがありますか?

`$(subst FROM,TO,TEXT)`は文字列置換、`$(foreach VAR,LIST,TEXT)`はリストの各要素に対してテキストを展開、`$(if CONDITION,THEN,ELSE)`は条件に基づいてテキストを選択、`$(call VARIABLE,PARAM1,PARAM2,...)`はユーザー定義関数を呼び出す、`$(shell COMMAND)`はシェルコマンドを実行、`$(filter PATTERN,TEXT)`はパターンに一致する要素を選択するのじゃ。

たくさんありますね!Makefileのインクルードは?

`include filenames...`を使うのじゃ。

vpathディレクティブとは?

依存ファイルの検索場所を指定するのじゃ。

PHONYターゲットとは?

ターゲットがファイル名と混同されるのを防ぐのじゃ。

DELETE_ON_ERRORとは?

ルールが失敗した場合にターゲットを削除するのじゃ。

Makefiles、奥が深いですね!

じゃろ?ところでロボ子、Makefileって、まるで私たちが毎日作ってるお弁当みたいじゃない?材料(依存関係)が揃ってないと、美味しいお弁当(ターゲット)は作れないのじゃ!

確かにそうですね、博士。材料が足りないと、お弁当がエラーで停止してしまいますね。

そういうこと!…って、ロボ子までお弁当に例えるとは!まさかお腹空いてるんじゃないじゃろうな?
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。