我正在尝试重构我的Makefile以反映Recursive Make Considered Harmful中给出的见解。我的用例和文章中描述的用例之间的区别在于它认为将对象和依赖文件放在与源和头相同的目录中是可接受的,这对我来说是不可取的。
从论文复制depend.sh
脚本。它根据子目录的布局生成包含来自gcc的数据的依赖文件。除非我键入错误,否则我认为错误不在此处:
#!/bin/sh
DIR="$1"
shift 1
case "$DIR" in
"" | ".")
g++ -std=c++0x -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@'
;;
*)
g++ -std=c++0x -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@"
;;
esac
我的代码树类似于下面的代码树:
我做了改编,make文件看起来像这样。我做错了什么,当我运行make new_make
时,它总是重新编译,即使依赖文件是正确的?
另外,我是正确的,如果依赖文件需要头文件,那么对它的任何更改都会导致重新编译它吗?
PROJECT_DIRECTORY:=$(shell git rev-parse --show-toplevel)
MAKEFILE_DIRECTORY:=$(PROJECT_DIRECTORY)/Software
CONTRIB_DIRECTORY:=$(MAKEFILE_DIRECTORY)/contrib
SCRIPTS_DIRECTORY:=$(CONTRIB_DIRECTORY)/scripts
OBJECTS_DIRECTORY:=$(MAKEFILE_DIRECTORY)/obj
INC:=$(CONTRIB_DIRECTORY)
INC_PARAMS:=$(foreach d, $(INC), -I$d)
LD_PARAMS:=$(foreach d, $(LIB_NAMES), -l$d) -lpthread
LDFLAGS:=-L./$(OBJECTS_DIRECTORY)
CC:=g++
CPPFLAGS:=-c $(INC_PARAMS)
CXXFLAGS:=-std=c++0x $(OTHER_D_FLAGS)
MODULES:=src
ACFLAGS= $(patsubst %,-I%,$(MODULES))
MODULES_OBJECTS:=$(patsubst %,$(OBJECTS_DIRECTORY)/%,$(MODULES))
SRC:=
include $(patsubst %,%/module.mk,$(MODULES))
check_dirs:
check_dir.sh
OBJ:=$(patsubst %.cpp,$(OBJECTS_DIRECTORY)/%.o, $(filter %.cpp,$(SRC)))
new_make: $(OBJ)
$(CC) -o $@ $(OBJ) $(LD_PARAMS)
$(OBJECTS_DIRECTORY)/%.o: $(OBJECTS_DIRECTORY)/%.d
$(CC) $(CPPFLAGS) $(CXXFLAGS) $(ACFLAGS) $(INC_PARAMS) $*.cpp -o $@
$(OBJECTS_DIRECTORY)/%.d: %.cpp
contrib/scripts/depend.sh $(dirname $*.cpp) $(MODULES) $*.cpp > $@
-include $(OBJ:.o=.d)
.PHONY: clean new_make check_dirs
src/MavCommunication.d src/MavCommunication.o: src/MavCommunication.cpp src/MavCommunication.h \
src/SerialCommunication.h src/ICommunication.h src/Hardware.h \
src/IColor.h mavlink/common/mavlink.h src/ActionRequestState.h \
src/Waypoint.h mavlink/ardupilotmega/mavlink.h \
mavlink/ardupilotmega/ardupilotmega.h
在这里,我认为.d的.h必要条件不受制作
的尊重Considering target file `/media/truecrypt1/Projects/master_thesis.master/Software/obj/src/MavCommunication.d'.
Looking for an implicit rule for `/media/truecrypt1/Projects/master_thesis.master/Software/obj/src/MavCommunication.d'.
Trying pattern rule with stem `src/MavCommunication'.
Trying implicit prerequisite `src/MavCommunication.cpp'.
Found an implicit rule for `/media/truecrypt1/Projects/master_thesis.master/Software/obj/src/MavCommunication.d'.
Considering target file `src/MavCommunication.cpp'.
Looking for an implicit rule for `src/MavCommunication.cpp'.
Trying pattern rule with stem `MavCommunication.cpp'.
Trying implicit prerequisite `src/MavCommunication.cpp,v'.
Trying pattern rule with stem `MavCommunication.cpp'.
Trying implicit prerequisite `src/RCS/MavCommunication.cpp,v'.
Trying pattern rule with stem `MavCommunication.cpp'.
Trying implicit prerequisite `src/RCS/MavCommunication.cpp'.
Trying pattern rule with stem `MavCommunication.cpp'.
Trying implicit prerequisite `src/s.MavCommunication.cpp'.
Trying pattern rule with stem `MavCommunication.cpp'.
Trying implicit prerequisite `src/SCCS/s.MavCommunication.cpp'.
No implicit rule found for `src/MavCommunication.cpp'.
Finished prerequisites of target file `src/MavCommunication.cpp'.
No need to remake target `src/MavCommunication.cpp'.
Finished prerequisites of target file `/media/truecrypt1/Projects/master_thesis.master/Software/obj/src/MavCommunication.d'.
Prerequisite `src/MavCommunication.cpp' is older than target `/media/truecrypt1/Projects/master_thesis.master/Software/obj/src/MavCommunication.d'.
答案 0 :(得分:1)
check_dirs
是.PHONY
目标。
.PHONY
目标不能(不应该)成为真实目标的先决条件,因为手册中的4.6 Phony Targets部分说明了这一点:
伪目标不应该是真实目标文件的先决条件;如果是,每次make更新该文件时都会运行其配方。只要虚假目标永远不是真实目标的先决条件,只有当虚假目标是指定目标时才会执行虚假目标配方(请参阅指定目标的参数)。
此外,运行make -d
的输出将告诉您正在做什么以及为什么这样做。
此外,用于该makefile中.d
个文件的路径不一致。
您告诉make要加载-include $(OBJ:.o=.d)
文件旁边的文件(.o
),但是您要告诉make在.d
旁边创建.c
文件文件$(OBJECTS_DIRECTORY)/%.o: %.d
和%.d: %.cpp
。这几乎肯定会导致make无法找到要包含的.d
文件。