Makefile 问题记录

Posted by zhuizhuhaomeng Blog on May 7, 2023

设置并发上限

make 一般加上 -j 参数可以并发编译,提升编译的速度。但是我遇到一个并发数量太大导致 内存不足,最终进程别 OOM Killer 杀死的情况。因此就想现在并发数量。

下面是设置并发上限的示例

job=$(shell n=$$(nproc) && [ $$n -lt 16 ] && echo $$n || echo 16)

all:
	echo $(job)

几种不同赋值的差异

  1. ’=’ 递归展开的赋值方式
  2. ’:=’ 简单展开的赋值方式
  3. ’?=’ 是在变量未被赋值的情况下才对变量赋值,相当于一个 if 判断
  4. ’!=’ 用于执行 shell 命令
  5. ’:=’

递归展开和非递归展开的实例

1
2
3
4
5
6
7
8
9
10
11
abc := $(bar)
foo = $(bar)
bar = $(ugh)
ugh = Huh?
cha := '$(bar)'

all:
	echo "abc = $(abc)"
	echo "foo = $(foo)"
	echo "bar = $(bar)"
	echo "cha = $(cha)"

执行上面的命令得到如下结果

1
2
3
4
5
6
7
8
9
$ make
echo "abc = "
abc = 
echo "foo = Huh?"
foo = Huh?
echo "bar = Huh?"
bar = Huh?
echo "cha = 'Huh?'"
cha = 'Huh?'

也就是说,’:=’ 是立即展开,而 ‘=’ 是延迟展开的

多数情况下的结果是无差别的

A?=a
B:=b
C=c

all:
	echo "A = $(A)"
	echo "B = $(B)"
	echo "C = $(C)"

执行下面的命令,可以看到在没有重复赋值的情况下,大家都是赋值而已。

1
2
3
4
5
6
7
$ make
echo "A = a"
A = a
echo "B = b"
B = b
echo "C = c"
C = c

环境变量的影响

我们通过设置环境变量,可以看到 ?= 的赋值方式会受到环境变量的影响

1
2
3
4
5
6
7
A=1 B=2 C=3 make
echo "A = 1"
A = 1
echo "B = b"
B = b
echo "C = c"
C = c

如果我们通过 Makefile 参数方式传递变量,那么 Makefile 里面的赋值都不生效了。 命令行参数的值会覆盖 Makefile 文件中的值。

1
2
3
4
5
6
7
$ make A=1 B=2 C=3
echo "A = 1"
A = 1
echo "B = 2"
B = 2
echo "C = 3"
C = 3

命令行参数的影响

如果我们调用 Makefile 的时候加上 -e 参数,那么环境变量的比 Makefile 的优先了

1
2
3
4
5
6
7
$ A=1 B=2 C=3 make -e
echo "A = 1"
A = 1
echo "B = 2"
B = 2
echo "C = 3"
C = 3

override 的影响

1
2
3
4
5
6
7
8
A?=a
B:=b
override C=c

all:
        echo "A = $(A)"
        echo "B = $(B)"
        echo "C = $(C)"

可以看到,加上 override 之后,C 的值就使用 Makefile 中的值

1
2
3
4
5
6
7
make A=1 B=2 C=3 
echo "A = 1"
A = 1
echo "B = 2"
B = 2
echo "C = c"
C = c

让 Makefile 输出详细的执行命令

我们编译程序的时候,需要看到详细的命令行参数,可以使用如下的命令

1
make SHELL='sh -x'

参考资料

https://www.gnu.org/software/make/manual/html_node/Setting.html https://www.gnu.org/software/make/manual/html_node/Values.html