Makefileをシェルスクリプト代わりに使う。

基本

Makefile
hoge:
    echo hoge

fuga:
    echo fuga

インデントは<TAB>で。MakefileでもmakefileでもOK(makefile優先)。

$ make
echo hoge
hoge
$ make fuga
echo fuga
fuga

コマンドがエコーバックされるのが邪魔なら、make --silentで抑止可能(短縮形は-s)。特定のターゲットのみ黙らせたいなら、.SILENTターゲットに記述。

.SILENT: fuga

あるいは、コマンドごとに@を前置。

hoge:
    @echo hoge

もし、偶然hogeファイルが存在してたらコマンドが実行されないので、.PHONYターゲットを記述。

.PHONY: hoge fuga

最初のルールがデフォルトで使われるので、usageを書く。コマンドを複数行に分けるときは、行末に\を。

all:
    @echo Usage: make COMMAND
    @echo -e COMMAND:\
        \\n'   hoge: echo hoge'\
        \\n'   fuga: echo fuga'

使い方を間違ったときのために、全捕捉のターゲットに何もしないコマンドを記述。

%:
    @:

%はワイルドカード。:は「何もしない」シェルコマンド。

変数

MSG1 = hey
MSG2 ?= hey
MSG3 := ${MSG2}

msg:
    @echo $(MSG1)
    @echo $(MSG2)
    @echo ${MSG3}

=は変数の定義。?=は未定義の場合のみ定義。環境変数を優先したいときに便利。

=?=で定義した変数を参照すると、参照するたびに、値が再計算される。参照先で別の変数を参照してたり、関数を呼んでるときに便利。

一方、:=で定義すると、その時点で値が確定する。

$ MSG1=hi MSG2=yo make msg
hey
yo
yo

変数を参照するときは、$()でも${}でも可。

if分岐

ifeq ($(FLAG),1)
    MSG := ON
else
    MSG := OFF
endif

関数

$(dir hoge/fuga/piyo.txt)        hoge/fuga/
$(notdir hoge/fuga/piyo.txt)     piyo.txt
$(wildcard *.clj)                a.clj b.clj
$(shell find . -name '*.clj')    ./a.clj ./b.clj ./hoge/core.clj
$(word 1,$(MAKEFILE_LIST))

イディオム

カレントディレクトリのフルパスを得る。

$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
$(abspath .)
$(shell pwd)

実例

DKIMG := kindlei
DKCON := chona
CURPATH := $(shell pwd)
WORKPATH := $(CURPATH)/books

CMD_LIST := image dev shell attach

all:
    @echo Usage: make COMMAND
    @echo -e COMMAND:\
        \\n'  image:  Build the docker image.'\
        \\n'  dev:    Start REPL.'\
        \\n'  shell:  Start the container to kindlegen.'\
        \\n'  attach: Attach to the container.'

.PHONY: $(CMD_LIST)
.SILENT: $(CMD_LIST)

image:
    cd docker && docker build --tag=$(DKIMG) .

dev:
    clojure -Adev

shell:
    mkdir -p $(WORKPATH)
    docker run --rm -it \
        -v $(WORKPATH):/tmp/kin \
        --name $(DKCON) \
        --workdir /tmp/kin \
        $(DKIMG) /bin/sh

attach:
    docker exec -it $(DKCON) /bin/sh

%:
    @: