Afraid of Makefiles? Don't be!

Matthias Endler

Makefileが怖い?心配いりません!

服とMakefileに何の関係があるの?この記事で解説します!
服とMakefileに何の関係があるの?この記事で解説します!
出典: Anindyanfitri氏によるイラスト - Freepik.com

ここ数年、たくさんの優秀なソフトウェアエンジニアと一緒に仕事をする機会に恵まれました。その中で印象的だったのは、Makefileについての実践的な知識や、なぜそれが便利なのかを知らない方が意外と多いということです。

ビルド工程を自動化しようとすると、彼らは自作のシェルスクリプトを用意することがよくあります。プロジェクトフォルダの中にbuild.shrun.shdoall.shといった名前で置かれているのが定番です。

それらのスクリプトは、毎回同じような基本的な機能を実装しています。

  • 入力パラメータや環境変数の解析。
  • ビルド手順間の依存関係の手動管理。
  • エラー処理(……一応、あれば)。

そして、その過程で同じような基本的なミスを繰り返しています。

こうした問題を解決するために発明されたのがMakefileです。

Makefileは怖い!

makeは怖いと思っているなら、きっと大規模なソフトウェアプロジェクトの複雑なビルド機構を思い浮かべているのでしょう。しかし、本来はそうである必要はありません。makeの作者であるStuart Feldman自身の言葉を聞いてみましょう。

始まりは依存関係を解析する大がかりなアイデアでしたが、ずっとシンプルなものに煮詰められ、その週末にMakeになりました。まだ出来たてのツールをどんどん使っていくのが当時の文化でした。Makefileは魔法のようにエンコードされたバイナリではなくテキストファイルでした。なぜなら、それがUnixの精神、すなわち表示でき、デバッグでき、理解できるもの、だったからです。

The Art of Unix Programming (2003)

Makeは、繰り返し発生する問題をシンプルな方法で解決するために、たった一つの週末で作られたのです。

Makefileはシンプル!

家を出る前に、私は着替えなければなりません。毎回同じシンプルな手順で服を着ます。下着、ズボン、シャツ、セーター、靴下、靴、ジャケットの順です。あなたの手順は違うかもしれませんが、きっとあなたにも毎日の習慣があるはずです。

これらのステップの中には、互いに依存し合っているものがあります。
Makeは依存関係を扱うのに役立ちます。
私の着替えの手順をMakefileで表現してみましょう。

dress: trousers shoes jacket
	@echo "All done. Let's go outside!"

jacket: pullover
	@echo "Putting on jacket."

pullover: shirt
	@echo "Putting on pullover."

shirt:
	@echo "Putting on shirt."

trousers: underpants
	@echo "Putting on trousers."

underpants:
	@echo "Putting on underpants."

shoes: socks
	@echo "Putting on shoes."

socks: pullover
	@echo "Putting on socks."

このMakefileを実行すると、次のような出力が得られます。

$ make dress
Putting on underpants.
Putting on trousers.
Putting on shirt.
Putting on pullover.
Putting on socks.
Putting on shoes.
Putting on jacket.
All done. Let's go outside!

何が起きたのでしょうか?

ステップが正しい順序で実行されたことにお気づきでしょうか。ステップ間の依存関係を素直に書き下すだけで、makeが正しい順序で実行してくれるのです。

各ビルドステップは次のような構造をしています。

target: [dependencies]
	<shell command to execute>
	<shell command to execute>
	...
  • Makefileの最初のターゲットは、makeを実行したときにデフォルトで実行されます。

  • ターゲットの記述順は関係ありません。

  • シェルコマンドはタブでインデントしなければなりません。

  • 実行されるコマンド自体の出力を抑制するには、行頭に@を付けます。

  • targetが生成したいファイルではない場合は、ビルドステップの最後に.PHONY <target>を追加してください。よく使われるPHONYターゲットには clean、install、run などがあります。そうしないと、誰かがinstallというディレクトリを作ったときに、ビルド対象がすでに存在するものとしてmakeが何もせず静かに失敗してしまいます。

    .PHONY: install
    install:
    	npm install

おめでとうございます!これでmakeについて知っておくべきことの90%は学べました。

次のステップ

実際のMakefileはもっと多くのことができます。全体を再ビルドするのではなく、変更されたファイルだけをビルドしてくれますし、可能な限り並列で処理を実行してくれます。ただ、できるだけシンプルに保つようにしてください。

原文は Matthias Endler により に公開されました。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。