[英]Is it possible to use Makefile "define" to define a target plus its recipes?
I have a C/C++ project that contains different directories, each containing a set of objects executables to build from C/C++ source code.我有一个包含不同目录的 C/C++ 项目,每个目录都包含一组从 C/C++ 源代码构建的对象可执行文件。
To enable automatic dependency tracking (generating .d dependency files whenever my #include
header files change), I have defined the following variables in a common Makefile:为了启用自动依赖项跟踪(每当我的
#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)
So that when I write directory-specific Makefiles I can write:因此,当我编写特定于目录的 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)
Where objs
refers to the object files needed to build each executable.其中
objs
是指构建每个可执行文件所需的目标文件。
But I found that the block of lines I have presented above must be repeated for every Makefile that I use to build executables in each directory, which could be a hassle if there are many of them.但是我发现对于我用来在每个目录中构建可执行文件的每个 Makefile 都必须重复我上面介绍的行块,如果它们中有很多,这可能会很麻烦。
I then have tried to write this in the common Makefile:然后我尝试在通用的 Makefile 中写这个:
define CC_OBJ_COMPILE =
%.o: %.c
$(CC_WRITE_DEP)
endef
define CXX_OBJ_COMPILE =
%.o: %.cpp
$(CXX_WRITE_DEP)
endef
and to include them in building executables:并将它们包含在构建可执行文件中:
common := common/Makefile
-include $(common)
$(CC_OBJ_COMPILE)
$(CXX_OBJ_COMPILE)
But this does not work.但这不起作用。 When I ran
make -p --dry-run
in one directory for executables to see how those variables expanded, I saw these lines:当我在一个可执行文件的目录中运行
make -p --dry-run
以查看这些变量如何扩展时,我看到了以下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
# ...
This means that the text variables are properly included into my executable-specific Makefiles.这意味着文本变量已正确包含在我的可执行文件特定的 Makefile 中。
However the implicit rules are expanded as:然而,隐式规则被扩展为:
# Implicit Rules
%.o: %.c
cc -Wall -Werror -c "" -o "" -MT "" -MMD -MP -MF ""
%.o: %.cpp
g++ -Wall -Werror -c "" -o "" -MT "" -MMD -MP -MF ""
Which means that they fail to include the automatic $<
and $@
variables for targets .这意味着它们无法包含 target 的自动
$<
和$@
变量。
So is it possible to create reusable rules that can be define
d as variables and -include
d in other Makefiles using variable references?那么是否有可能创建可重用的规则,这些规则可以使用变量引用
define
d define
为变量并在其他 Makefile 中-include
d? Did I miss something here?我在这里错过了什么吗?
Make is an old grandpa - it is 45 years old. Make是一位老爷爷——今年45岁。 Consider moving to something newer - CMake, Scons, Meson, etc. Such tools will take care of dependencies automatically, will be portable, will come with a lot more features and will save you from endless (and pointless) hours of reinventing the wheel.
考虑转向更新的东西 - CMake、Scons、Meson 等。这些工具将自动处理依赖项,将是可移植的,将提供更多功能,并将使您免于重新发明轮子的无休止(和无意义)时间。
Is it possible to use Makefile "define" to define a target plus its recipes?
是否可以使用 Makefile“定义”来定义目标及其配方?
You have to eval the call.您必须评估通话。
define CXX_OBJ_COMPILE =
%.o: %.cpp
$(CXX_WRITE_DEP)
endef
$(eval $(CXX_OBJ_COMPILE))
Which means that they fail to include the automatic $< and $@ variables for targets.
这意味着它们无法包含目标的自动 $< 和 $@ 变量。
Sure it does - $@
is like "expanded first", they need to be left for expansion.当然可以 -
$@
就像“先扩展”一样,需要留下它们进行扩展。
CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$$<" -o "$$@" $(DEPFLAGS)
As I see it you have three options.在我看来,您有三个选择。
You could use the correct syntax for using "canned" code, as @KamilCuk directs.正如@KamilCuk 所指示的,您可以使用正确的语法来使用“罐头”代码。
Or you could put the rules in the common file rather than assigning them to variables, as @thebusybee suggested.或者您可以将规则放在公共文件中,而不是像@thebusybee 建议的那样将它们分配给变量。
Or you could omit the rules entirely and let Make use the default rule with your extra flags:或者你可以完全省略规则,让 Make 使用带有额外标志的默认规则:
CPPFLAGS += $(DEPFLAGS)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.