Makefile Gnu制造,虚假的先决条件

Makefile Gnu制造,虚假的先决条件,makefile,gnu-make,Makefile,Gnu Make,考虑一下这个Makefile all: a.out a.out: group_1 group_2 group_1: CXXFLAGS = -Wall group_2: CXXFLAGS = -Wextra group_1: a.o b.o group_2: c.o 虽然它可能会工作得很好,但我想知道写它的正确方式是什么,因为根据GNU Make docs,group1和group2必须是。虚假的目标,因为它们不是真正的目标,只是用相同的配置对一组目标进行分组的一种方式 但是,与此同时,.PH

考虑一下这个Makefile

all: a.out

a.out: group_1 group_2
group_1: CXXFLAGS = -Wall
group_2: CXXFLAGS = -Wextra
group_1: a.o b.o
group_2: c.o
虽然它可能会工作得很好,但我想知道写它的正确方式是什么,因为根据GNU Make docs,
group1
group2
必须是
。虚假的目标,因为它们不是真正的目标,只是用相同的配置对一组目标进行分组的一种方式

但是,与此同时,
.PHONY
目标不应被用作文档推荐的其他目标的先决条件。所以我不知道用什么方法来指定这样的依赖结构

这样做的目的是,如果我没有错的话,优化的目的。我希望
cxflags
的计算量尽可能少,并且我假设
Makefile
类似

all: a.out

a.out: a.o b.o c.o
a.o b.o: CXXFLAGS = -Wall
c.o: CXXFLAGS = -Wextra

将对每个先决条件评估一次
cxflags
,而使用前面的方法,每个组只评估一次,因此我的第一个
Makefile
应该运行得更快(外推到更大的依赖树)。

对于目标,您无法轻松做到这一点。问题是
a.out
将取决于两个文件
group_1
group_2
。这些文件从不存在,因此
a.out
将始终被视为过时

关于变量展开问题,你的假设是不正确的。即使在第一个示例中,
cxflags
也将在每次构建任何目标时进行评估。必须如此,因为变量赋值可能类似于:

group_1: CXXFLAGS = -DNAME='$@'
CXXFLAGS_1 := -Wall
CXXFLAGS_2 := -Wextra

GROUP_1 := a.o b.o
GROUP_2 := c.o

a.out: $(GROUP_1) $(GROUP_2)
$(GROUP_1): CXXFLAGS := $(CXXFLAGS_1)
$(GROUP_2): CXXFLAGS := $(CXXFLAGS_2)
我不知道为什么您觉得变量的扩展会对性能产生影响,但是如果它们确实需要很长时间(可能调用
shell
或其他什么),并且您确定这些变量没有对正在构建的特定目标的任何引用,并且您只想强制它们扩展一次,你可以这样做:

group_1: CXXFLAGS = -DNAME='$@'
CXXFLAGS_1 := -Wall
CXXFLAGS_2 := -Wextra

GROUP_1 := a.o b.o
GROUP_2 := c.o

a.out: $(GROUP_1) $(GROUP_2)
$(GROUP_1): CXXFLAGS := $(CXXFLAGS_1)
$(GROUP_2): CXXFLAGS := $(CXXFLAGS_2)

是的,我在其他情况下也会使用这种方法。原因是我正在做一个大量使用模板的GNU Make库,很快就会添加到github中,我希望尽可能减少模板扩展。但我有一个疑问,在您的解决方案中,
cxflags
是否仅在考虑先决条件时才进行扩展,还是在解析Makefile时应用
:=
呢?如果使用
:=
,它将在make读取Makefile时进行一次扩展。如果使用
=
,则每次需要变量值时(例如,每次
$(cxflags)
出现在扩展上下文中时),都会对其进行扩展。