makeで環境変数とMakefileの変数、引数の値の内どの値が参照されるか

linux
$ docker run -v `pwd`:/root -it ubuntu:20.04 /bin/sh
# apt update && apt install -y make
# make --version
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu

# cat Makefile 
HOGE:=aaa
foo:
        echo $(HOGE) $(FUGA) > /dev/null

フラグを付けないと引数の値 -> Makefileの変数 -> 環境変数の順で参照されるので、 makeの前に書いた環境変数ではMakefileの変数を上書きできず、後に書いて引数とすると上書きできる。

# export HOGE=ccc FUGA=ddd
# make foo
echo aaa ddd > /dev/null # (Makefileの変数 > 環境変数) (環境変数)

# HOGE=bbb FUGA=xxx make foo
echo aaa xxx > /dev/null # (Makefileの変数 > 環境変数) (環境変数)

# make foo HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null # (引数の値 > Makefileの変数) (引数の値)

-eフラグを付けて実行すると環境変数の優先度が上がり引数の値 -> 環境変数 -> Makefileの変数の順で参照されるようになる。

# make --help
...
  -e, --environment-overrides Environment variables override makefiles.

# make -e foo
echo ccc ddd > /dev/null # (環境変数 > Makefileの変数) (環境変数)

# make -e foo HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null # (引数の値 > Makefileの変数) (引数の値)

Makefileの変数にoverrideを付けるとその変数は最優先で参照される。 foo: AAA=BBBのように書くとターゲット特有の変数を定義することができ、overrideと組み合わせるとそのターゲット限定で値を固定できる。

# cat Makefile 
foo: override HOGE=@@@
foo:
        echo $(HOGE) $(FUGA) > /dev/null

bar:
        echo $(HOGE) $(FUGA) > /dev/null

# make foo HOGE=bbb FUGA=xxx
echo @@@ xxx > /dev/null # (Makefileの変数 > 引数の値) (引数の値)

# make bar HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null # (引数の値 > Makefileの変数) (引数の値)

ちなみに-Cフラグでパスを指定するとそこに移動してから実行されるが、そのときの$(PWD)は元のパスとなる。$(shell pwd)で移動した先のパスが取れる。

# cat dir1/Makefile
foo:
        echo $(PWD) $(shell pwd) > /dev/null

# make -C dir1 foo
make: Entering directory '/root/dir1'
echo /root /root/dir1 > /dev/null
make: Leaving directory '/root/dir1'

参考

GNU make 日本語訳(Coop編) - 変数の利用法