说我有以下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@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
尝试“提出”它认为适合目标的命令?
答案 0 :(得分:0)
最后一条规则似乎被忽略或误解,因此make会依赖于其对cpp文件的隐式规则(参见Catalogue of Implicit Rules)。
它可以使用这种语法解决:
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
,否则只会构建第一个目标。
答案 1 :(得分: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.