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