gpt4 book ai didi

makefile - GNU make 中的错误 : target-specific variables are not expanded in implicit rules?

转载 作者:行者123 更新时间:2023-12-02 11:14:10 25 4
gpt4 key购买 nike

我一直致力于设计一个多配置 Makefile(支持单独的“调试”和“发布”目标的文件),并且遇到了一个奇怪的问题,它似乎是 GNU make 中的一个错误。

当在隐式规则中引用这些变量时,GNU make 似乎没有正确扩展目标特定变量。这是一个显示此问题的简化 Makefile:

all:
@echo specify configuration 'debug' or 'release'

OBJS := foo.o bar.o

BUILDDIR = .build/$(CONFIG)

TARGET = $(addprefix $(BUILDDIR)/,$(OBJS))

debug: CONFIG := debug
release: CONFIG := release

#CONFIG := debug

debug: $(TARGET)
release: $(TARGET)

clean:
rm -rf .build

$(BUILDDIR)/%.o: %.c
@echo [$(BUILDDIR)/$*.o] should be [$@]
@mkdir -p $(dir $@)
$(CC) -c $< -o $@

当指定要创建的目标“debug”时,CONFIG 设置为“debug”,并且 BUILDDIR 和 TARGET 同样会正确扩展。但是,在从对象构建源文件的隐式规则中,$@ 会展开,就好像 CONFIG 不存在一样。

这是使用此 Makefile 的输出:

$ make debug
[.build/debug/foo.o] should be [.build//foo.o]
cc -c foo.c -o .build//foo.o
[.build/debug/bar.o] should be [.build//bar.o]
cc -c bar.c -o .build//bar.o

这表明 BUILDDIR 正在被很好地扩展,但生成的 $@ 却没有。如果我然后注释掉目标变量规范并手动设置 CONFIG := debug (上面的注释行),我会得到我所期望的:

$ make debug
[.build/debug/foo.o] should be [.build/debug/foo.o]
cc -c foo.c -o .build/debug/foo.o
[.build/debug/bar.o] should be [.build/debug/bar.o]
cc -c bar.c -o .build/debug/bar.o

我已经在 Gentoo 和 MinGW 上使用 make-3.81 以及 Gentoo 上的 make-3.82 对此进行了测试。所有人都表现出相同的行为。

我发现很难相信我会是第一个遇到这个问题的人,所以我猜我可能只是做错了什么——但我会说实话:我不明白我是如何做到的可能。 :)

是否有任何制作专家可以解释这个问题?谢谢!

最佳答案

基本上,Make 会计算出依赖关系的 DAG,并创建一个必须在运行任何规则之前运行的规则列表。。分配特定于目标的值是 Make 在运行规则时执行的操作(稍后进行)。这是一个严重的限制(我和其他人之前已经提示过),但我不会将其称为错误,因为它在文档中进行了描述。根据 GNUMake 手册:

6.11 Target-specific Variable Values :“与自动变量一样,这些值仅在目标配方的上下文中可用(以及其他特定于目标的分配)。”

“目标配方的上下文”指的是命令,而不是先决条件:

10.5.3 Automatic variables :“[自动变量]无法在规则的先决条件列表中直接访问。”

有几种方法可以解决这个问题。您可以使用Secondary Expansion ,如果你的 Make GNUMake 版本有它(3.81 没有,我不知道 3.82)。或者您可以不使用特定于目标的变量:

DEBUG_OBJS = $(addprefix $(BUILDDIR)/debug/,$(OBJS))
RELEASE_OBJS = $(addprefix $(BUILDDIR)/release/,$(OBJS))

debug: % : $(DEBUG_OBJS)
release: $(RELEASE_OBJS)

$(DEBUG_OBJS): $(BUILDDIR)/debug/%.o : %.cc
$(RELEASE_OBJS): $(BUILDDIR)/release/%.o : %.cc

$(DEBUG_OBJS) $(RELEASE_OBJS):
@echo making $@ from $^
@mkdir -p $(dir $@)
$(CC) -c $< -o $@

关于makefile - GNU make 中的错误 : target-specific variables are not expanded in implicit rules?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4069515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com