我正在尝试使用make来创建带有子目录的项目,我使递归的make部分起作用了,但是由于某种原因,它似乎采用了源文件依赖项的先决条件,并将.o
附加到了它们然后尝试编译它们,但显然不起作用,为什么这样做呢?
有问题的规则如下:
operations_cache.o : memory_management/operations_cache.cpp memory_management/operations_cache.hpp \
function.hpp operations/operation_base.hpp
cd memory_management && $(MAKE) $@
编译operations
目录的规则如下:
operation_%.o : function.hpp
cd operations && $(MAKE) $@
由于某种原因,make一直试图说operations/operation_base.hpp.o
是一个有效的目标,即使我没有在make文件中的任何地方列出它。我已经阅读了该文档的文档,但在文档中没有看到任何有关尝试根据必备文件名隐式定义对象的信息,因此,我对于使它执行此操作的原因感到非常困惑。
我得到的错误是:
g++ -c -o main.o main.cpp
g++ -c -o node.o node.cpp
cd memory_management && make unique_table.o
make[1]: Entering directory './memory_management'
g++ -o ../unique_table.o -c unique_table.cpp
make[1]: Leaving directory './memory_management'
cd operations && make operations/operation_base.hpp.o
make[1]: Entering directory './operations'
g++ -o ../operations/operation_base.hpp.o -c
g++: fatal error: no input files
compilation terminated.
Makefile:10: recipe for target 'operations/operation_base.hpp.o' failed
make[1]: *** [operations/operation_base.hpp.o] Error 1
make[1]: Leaving directory './operations'
Makefile:24: recipe for target 'operations/operation_base.hpp.o' failed
make: *** [operations/operation_base.hpp.o] Error 2
应用户要求,这是我3个目录的完整文件。
./ Makefile
CC = g++
objects = main.o node.o unique_table.o operations_cache.o function.o operation_base.o operation_and.o
# shared_lib = nodelib.so
all : edit # $(shared_lib)
edit : $(objects)
$(CC) -o edit $(objects)
main.o : main.cpp node.hpp memory_management/unique_table.hpp memory_management/operations_cache.hpp
node.o : node.cpp node.hpp
unique_table.o : memory_management/unique_table.cpp memory_management/unique_table.hpp node.hpp
cd memory_management && $(MAKE) $@
operations_cache.o : memory_management/operations_cache.cpp memory_management/operations_cache.hpp \
function.hpp operations/operation_base.hpp
cd memory_management && $(MAKE) $@
function.o : function.cpp function.hpp node.hpp memory_management/unique_table.hpp
operation_%.o : function.hpp
cd operations && $(MAKE) $@
.PHONY : clean
clean :
rm edit $(objects)
./ operations / Makefile
CC = g++
objects = operation_base.o operation_and.o operation_or.o operation_xor.o operation_restrict.o operation_composition.o operation_satisfy.o operation_satisfy_all.o
proj_dir = ../
operation_base.o : operation_base.cpp operation_base.hpp $(proj_dir)function.hpp
operation_and.o : operation_and.cpp operation_and.hpp operation_base.hpp $(proj_dir)function.hpp
operation_or.o : operation_or.cpp operation_or.hpp operation_base.hpp $(proj_dir)function.hpp
operation_xor.o : operation_xor.cpp operation_xor.hpp operation_base.hpp $(proj_dir)function.hpp
operation_composition.o : operation_composition.cpp operation_composition.hpp operation_base.hpp $(proj_dir)function.hpp
operation_restrict.o : operation_restrict.cpp operation_restrict.hpp operation_base.hpp $(proj_dir)function.hpp
operation_satisfy.o : operation_satisfy.cpp operation_satisfy.hpp operation_base.hpp $(proj_dir)function.hpp
operation_satisfy_all.o : operation_satisfy_all.cpp operation_satisfy_all.hpp operation_satisfy.hpp
%.o :
$(CC) -o $(proj_dir)$@ -c $<
./ memory_management / Makefile
CC = g++
objects = operations_cache.o unique_table.o
proj_dir = ../
operations_cache.o : operations_cache.cpp operations_cache.hpp \
$(proj_dir)function.hpp $(proj_dir)operations/operation_base.hpp
unique_table.o : unique_table.cpp unique_table.hpp $(proj_dir)node.hpp
%.o :
$(CC) -o $(proj_dir)$@ -c $<
从memory_management/operations_cache.cpp memory_management/operations_cache.hpp function.hpp operations/operation_base.hpp
行中删除operations_cache.o
可以解决问题,它不能解释为什么会出现错误,但是可以,但是我仍然想了解为什么会发生这种情况。 / p>
答案 0 :(得分:1)
那是因为您的operations/operation_base.hpp
恰好符合operation_%.o
规则,并且是由于内置规则的事实:
.o:
# Builtin rule
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
它是这样工作的:
operations/operation_base.hpp
,%: %.o
),operations/operation_base.hpp.o
是否可以解决(候选人:operation_%.o: functions.hpp
)functions.hpp
是否可以解决(是,文件存在)operation_%.o: functions.hpp
和主干operations/base.hpp
(执行失败的配方)。我准备了一个简化的Makefile
来重现该问题。它要求同时存在functions.hpp
并启用内置规则。
all: operations/operation_base.hpp
operation_%.o: functions.hpp
echo Making $@ from $<
输出:
# Only Makefile (no functions.hpp)
$ ls
Makefile
$ make
make: *** No rule to make target 'operations/operation_base.hpp', needed by 'all'. Stop.
# Create functions.hpp to fulfill pattern rule (this is the case in question)
$ touch functions.hpp
$ make
echo Making operations/operation_base.hpp.o from functions.hpp
Making operations/operation_base.hpp.o from functions.hpp
# The following output comes from built-in rule %: %.o
cc operations/operation_base.hpp.o -o operations/operation_base.hpp
make: cc: Command not found
<builtin>: recipe for target 'operations/operation_base.hpp' failed
# The same, but with disabled built-in rules
$ make -r
make: *** No rule to make target 'operations/operation_base.hpp', needed by 'all'. Stop.
通常,当您不知道为什么make决定做某事时,使用-d
来运行它以调试决策,并使用-p
来获得最终解决的Makefile
很有用。它确认了场景:
$ make -d
…
No implicit rule found for 'all'.
Considering target file 'operations/operation_base.hpp'.
File 'operations/operation_base.hpp' does not exist.
Looking for an implicit rule for 'operations/operation_base.hpp'.
…
Trying implicit prerequisite 'operations/operation_base.hpp.o'.
Looking for a rule with intermediate file 'operations/operation_base.hpp.o'.
Avoiding implicit rule recursion.
Trying pattern rule with stem 'base.hpp'.
Trying rule prerequisite 'functions.hpp'.
Found an implicit rule for 'operations/operation_base.hpp'.
…
No need to remake target 'functions.hpp'.
Considering target file 'operations/operation_base.hpp.o'.
File 'operations/operation_base.hpp.o' does not exist.
Pruning file 'functions.hpp'.
Finished prerequisites of target file 'operations/operation_base.hpp.o'.
Must remake target 'operations/operation_base.hpp.o'.
echo Making operations/operation_base.hpp.o from functions.hpp
…
Successfully remade target file 'operations/operation_base.hpp.o'.
Finished prerequisites of target file 'operations/operation_base.hpp'.
Must remake target 'operations/operation_base.hpp'.
cc operations/operation_base.hpp.o -o operations/operation_base.hpp
…
make: cc: Command not found
…
<builtin>: recipe for target 'operations/operation_base.hpp' failed
已解决的Makefile
(make -p
)的片段:
operations/operation_base.hpp: operations/operation_base.hpp.o
# Implicit rule search has been done.
# Implicit/static pattern stem: 'operations/operation_base.hpp'
# Modification time never checked.
# File has been updated.
# Failed to be updated.
# automatic
# @ := operations/operation_base.hpp
# automatic
# % :=
# automatic
# * := operations/operation_base.hpp
# automatic
# + := operations/operation_base.hpp.o
# automatic
# | :=
# automatic
# < := operations/operation_base.hpp.o
# automatic
# ^ := operations/operation_base.hpp.o
# automatic
# ? := operations/operation_base.hpp.o
# variable set hash-table stats:
# Load=8/32=25%, Rehash=0, Collisions=1/22=5%
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
operations/operation_base.hpp.o: functions.hpp
# Implicit rule search has been done.
# Implicit/static pattern stem: 'operations/base.hpp'
# File is an intermediate prerequisite.
# File does not exist.
# File has been updated.
# Successfully updated.
# automatic
# @ := operations/operation_base.hpp.o
# automatic
# % :=
# automatic
# * := operations/base.hpp
# automatic
# + := functions.hpp
# automatic
# | :=
# automatic
# < := functions.hpp
# automatic
# ^ := functions.hpp
# automatic
# ? := functions.hpp
# variable set hash-table stats:
# Load=8/32=25%, Rehash=0, Collisions=1/13=8%
# recipe to execute (from 'Makefile', line 4):
echo Making $@ from $<