Makefile Gnu制造,虚假的先决条件
考虑一下这个MakefileMakefile 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
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)
出现在扩展上下文中时),都会对其进行扩展。