そんな今日この頃の技術ネタ

本家側に書くほどでもない小ネタ用

Makefileに定形作業をまとめて横着をする

月イチ更新を目標にしてたのに気づけばサボりにサボって約半年・・・そんなわけで、今回はリハビリがてら軽めのネタで。


makeというと普段Webの浅瀬でピチャピチャしてる系のエンジニアからすると縁遠いものな印象があるものの、その実態はMakefileにコマンドの依存関係を記述して実行できる仕組みである。大抵の環境にデフォで入っていて言語を問わず使えるので、プロジェクトの定形作業を記述するのに便利だったりするのだ。

Makefileの記述

Makefileは以下のようなフォーマットで記述していく。

all: [makeコマンドで実行したいターゲットを列挙]

[ターゲット名]: [依存するターゲットを列挙]
    [実行するシェルコマンド]


下記のMakefileを例に進める。

all: step1 step2

step1:
    echo step1

step2: step1
    echo step2

step3: step1
    echo step3

.PHONY: all step1 step2 step3
  • 通常の作業ではstep1とstep2を実行する必要があり、たまに選択的にstep3を実行する
  • step2とstep3はそれぞれ事前にstep1を実行する必要がある

という状況を想定した記述。

makeは本来は何かしらコードをビルドしてターゲット名=その成果物の有無で処理をスキップしたりできるのだが、今回の用法ではむしろ意図せぬファイル名の一致があると困るので、それを無視する.PHONY項にひたすらターゲット名を記述する。


通常実行

何も考えずMakefileがあるディレクトリでmakeコマンドを実行すれば良い。

$ make
echo step1
step1
echo step2
step2

allの記述に従い、step1の後にstep2が実行される。

選択しての実行

また、引数としてターゲット名を渡すことで特定の動作だけをさせることもできる。

step3を指定すると、依存するstep1と共にstep3が実行される。

$ make step3
echo step1
step1
echo step3
step3

例えばクラウドサービスの操作などでの認証コマンドなんかはstep1のように依存するターゲットとして記述しておくと、認証切れでの再実行みたいなストレスが軽減できる。

また、一時ファイルの一括削除などといったたまに必要になる作業は、今回のstep3のようにallから外して記述すると良いのではないだろうか。


ちなみに同じstep1に依存するstep2とstep3をそれぞれ指定しても、step1はちゃんと1回しか実行されない。

$ make step2 step3
echo step1
step1
echo step2
step2
echo step3
step3


並列実行

依存性が無い作業なんかは-jオプションで並列に実行させることもできる。

$ make step2 step3 -j
echo step1
step1
echo step2
echo step3
step2
step3

表示からstep2の結果を待たずにstep3が実行されていることが確認できる。



エリアスは他人に展開できないし、シェルスクリプトで色んなパターンを網羅した記述をするのは割と辛い。 READMEやWikiに長大な手順を書くのはメンテナンスするのも読むのも苦痛だし、コマンドヒストリー頼りというのもスマートさに欠ける。

そんな場面でMakefileは便利に活用できるんじゃないかと思う。書式にクセはあるものの、ステップ自体は普通にコマンドを記述するだけなの読み解くのは苦にならないし、実際に動かすものだから記述の乖離も起きない。何より新たにツールを導入してもらう必要もないから布教しやすい。

GNU Make 第3版

GNU Make 第3版