1

假设我有以下生成文件:

TARGETS = a b c

all: $(TARGETS)
    @echo Done.

%.o: %.cpp
    @echo Compiling $@...
    touch $@

%: %.o
    @echo Building $@...
    touch $@

我希望这应该没有问题运行:该all规则将触发%, 规则,该规则将触发该%.o规则,生成a.o,b.oc.o文件,然后最终生成a,b和文件。c

但是,运行make会导致以下输出:

ghb@Nemo:~/Downloads$ make
g++     a.cpp   -o a
/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/../../../crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [a] Error 1

g++为什么我突然想跑?我对此没有任何规定。此外,运行make a.o后跟make a运行正常,但运行make a会导致上述行为。

我能做些什么来防止make试图“想出”它认为适合目标的命令?

4

2 回答 2

0

这里涉及三个规则,你写的两个:

%.o: %.cpp
    @echo Compiling $@...
    touch $@

%: %.o
    @echo Building $@...
    touch $@

还有一个是“内置”的:

%: %.cpp
    $(CXX) $< -o $@     # There's a little more to it, but never mind.

当您尝试构建a时,Make 会检查其规则列表并提出两个候选者:

%: %.o    # yours
%: %.cpp  # built in

如果a.o已经存在,那么您的规则优先(这就是为什么您的链make a.o首先起作用的原因)。如果不是,则 Make 选择第二个,因为a.cpp 确实存在。

如果您不希望 Make 在构建目标时考虑这些内置规则,请使用make -r,也称为make --no-builtin-rules.

于 2012-06-07T00:08:43.403 回答
0

最后一条规则似乎被忽略或误解了,因此 make 回退到它对 cpp 文件的隐式规则(请参阅隐式规则目录)。
可以使用以下语法解决它:

TARGETS := a b c

all: $(TARGETS)
        @echo Done.

%.o: %.cpp
        @echo Compiling $@...
        touch $@

define make_target
$(1): $(1).o
        @echo Building $$@...
        touch $$@
endef
$(foreach tgt, $(TARGETS), $(eval $(call make_target, $(tgt))))

顺便说一句,使用make all代替make或仅构建第一个目标。

于 2012-06-06T08:20:32.997 回答