【发布时间】:2021-12-25 15:57:11
【问题描述】:
我有一个 C/C++ 项目,其中包含不同的目录,每个目录都包含一组可从 C/C++ 源代码构建的可执行对象。
为了启用自动依赖跟踪(每当我的 #include 头文件更改时生成 .d 依赖文件),我在一个通用 Makefile 中定义了以下变量:
# automatic prerequisite generation
# source: http://web.archive.org/web/20210820223028/http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
DEPFLAGS = -MT "$@" -MMD -MP -MF "$(@:.o=.d)"
CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$<" -o "$@" $(DEPFLAGS)
CXX_WRITE_DEP = $(CXX) $(CXXFLAGS) -c "$<" -o "$@" $(DEPFLAGS)
这样当我编写特定目录的 Makefile 时,我可以编写:
# common compile options
common := common/Makefile
-include $(common)
# automatic dependency tracking
deps = $(objs:.o=.d)
-include $(deps)
# compile all .cpp source code files into .o object files
%.o: %.cpp
$(CXX_WRITE_DEP)
# compile all .c source code files into .o object files
%.o: %.c
$(CC_WRITE_DEP)
其中objs 指的是构建每个可执行文件所需的目标文件。
但我发现,对于我用来在每个目录中构建可执行文件的每个 Makefile,必须重复上面介绍的行块,如果它们很多,这可能会很麻烦。
然后我尝试在通用 Makefile 中写这个:
define CC_OBJ_COMPILE =
%.o: %.c
$(CC_WRITE_DEP)
endef
define CXX_OBJ_COMPILE =
%.o: %.cpp
$(CXX_WRITE_DEP)
endef
并将它们包含在构建可执行文件中:
common := common/Makefile
-include $(common)
$(CC_OBJ_COMPILE)
$(CXX_OBJ_COMPILE)
但这不起作用。当我在一个可执行文件目录中运行 make -p --dry-run 以查看这些变量如何扩展时,我看到了这些行:
# ...
# makefile (from 'common/Makefile', line 16)
define CC_OBJ_COMPILE
%.o: %.c
$(CC_WRITE_DEP)
endef
# ...
# makefile (from 'common/Makefile', line 21)
define CXX_OBJ_COMPILE
%.o: %.cpp
$(CXX_WRITE_DEP)
endef
# ...
这意味着文本变量已正确包含在我的可执行文件特定的 Makefile 中。
然而隐含的规则被扩展为:
# Implicit Rules
%.o: %.c
cc -Wall -Werror -c "" -o "" -MT "" -MMD -MP -MF ""
%.o: %.cpp
g++ -Wall -Werror -c "" -o "" -MT "" -MMD -MP -MF ""
这意味着他们未能为目标包含自动的$< 和$@ 变量。
那么是否有可能创建可重用的规则,这些规则可以是 defined 作为变量,而 -included 在其他 Makefile 中使用变量引用?我错过了什么吗?
【问题讨论】:
-
您是否尝试将编译规则直接移动到一个通用的 Makefile 中?最后,它们总是相同的。