make执行makefile中未指定的命令
假设我有以下生成文件:make执行makefile中未指定的命令,makefile,Makefile,假设我有以下生成文件: TARGETS = a b c all: $(TARGETS) @echo Done. %.o: %.cpp @echo Compiling $@... touch $@ %: %.o @echo Building $@... touch $@ 我希望这在运行时不会出现问题:all规则将触发%,规则将触发%.o规则,生成a.o、b.o和c.o文件,然后将最终生成a、b和c文件 但是,运行make会导致以下输出: ghb@Ne
TARGETS = a b c
all: $(TARGETS)
@echo Done.
%.o: %.cpp
@echo Compiling $@...
touch $@
%: %.o
@echo Building $@...
touch $@
我希望这在运行时不会出现问题:all
规则将触发%
,规则将触发%.o
规则,生成a.o
、b.o
和c.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
尝试“想出”它认为适合目标的命令 最后一条规则似乎被忽略或误解,因此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
,否则只生成第一个目标 这里有三条规则,你写了两条:
%.o: %.cpp
@echo Compiling $@...
touch $@
%: %.o
@echo Building $@...
touch $@
一个是“内置的”:
如果a.o
已经存在,那么您的规则将优先(这就是为什么如果您首先创建a.o
,链将起作用)。如果没有,则Make选择第二个,因为a.cpp
确实存在
如果你不想在构建你的目标时考虑这些内置的规则,请使用<代码> ---R/<代码>,也称为“代码>使-没有内置规则。< /代码>
这太酷了!但是,请您解释一下您的解决方案中发生了什么,以及为什么它有效而不是我的?实际上,我无法解释为什么忽略“%:%o”规则。但是,如果将其替换为“%.exe:%o”(与每个目标名称一起),它将正常工作!我的解决方案为每个目标(使用define..endef)定义了一个通用规则,$(foreach..,$(eval..)宏为目标的每个元素展开它(请参见…中的描述)。。。。为了回答您的初始问题,由于忽略了“%:%.O”规则,请回到它的C++隐式编译规则(参见),这就是令人惊讶的G++调用的来源。%: %.cpp
$(CXX) $< -o $@ # There's a little more to it, but never mind.
%: %.o # yours
%: %.cpp # built in