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

# HOGE=bbb FUGA=xxx make foo
echo aaa xxx > /dev/null

# make foo HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null

-eフラグを付けて実行すると環境変数の値がMakefileの変数よりも優先して参照される。

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

# make -e foo
echo ccc ddd > /dev/null

# make -e foo HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null

Makefileの変数にoverrideを付けるとMakefileの変数が引数の値よりも、また、-eを付けても環境変数より優先して参照される。 foo: AAA=BBBのように書くとターゲット特有の変数を定義することができ、overrideと組み合わせるとそのターゲット限定で値を固定できる。

# cat Makefile 
foo: override [email protected]@@
foo:
        echo $(HOGE) $(FUGA) > /dev/null

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

# make foo HOGE=bbb FUGA=xxx
echo @@@ xxx > /dev/null

# make bar HOGE=bbb FUGA=xxx
echo bbb xxx > /dev/null

-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編) - 変数の利用法