是否可以使用 Makefile "define" 来定义目标及其配方?
Is it possible to use Makefile "define" to define a target plus its recipes?
我有一个包含不同目录的 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 ""
这意味着它们未能包含目标.
的自动$<
和$@
变量
那么是否可以创建可重用的规则,这些规则可以 define
d 作为变量并 -include
d 在其他使用变量引用的 Makefile 中?我在这里错过了什么吗?
Make是一位老爷爷——今年45岁。考虑转向更新的东西——CMake、Scons、Meson 等。这些工具将自动处理依赖关系,将是可移植的,将具有更多功能,并将使您免于无休止(且毫无意义)的重新发明轮子的时间。
Is it possible to use Makefile "define" to define a target plus its recipes?
您必须评估通话。
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.
当然可以 - $@
就像“先展开”,需要留下来进行展开。
CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$$<" -o "$$@" $(DEPFLAGS)
据我所知,您有三个选择。
您可以按照@KamilCuk 的指示使用正确的语法来使用“固定”代码。
或者您可以将规则放在公共文件中,而不是像@thebusybee 所建议的那样将它们分配给变量。
或者您可以完全省略规则,让 Make 使用带有额外标志的默认规则:
CPPFLAGS += $(DEPFLAGS)
我有一个包含不同目录的 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 ""
这意味着它们未能包含目标.
的自动$<
和$@
变量
那么是否可以创建可重用的规则,这些规则可以 define
d 作为变量并 -include
d 在其他使用变量引用的 Makefile 中?我在这里错过了什么吗?
Make是一位老爷爷——今年45岁。考虑转向更新的东西——CMake、Scons、Meson 等。这些工具将自动处理依赖关系,将是可移植的,将具有更多功能,并将使您免于无休止(且毫无意义)的重新发明轮子的时间。
Is it possible to use Makefile "define" to define a target plus its recipes?
您必须评估通话。
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.
当然可以 - $@
就像“先展开”,需要留下来进行展开。
CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$$<" -o "$$@" $(DEPFLAGS)
据我所知,您有三个选择。
您可以按照@KamilCuk 的指示使用正确的语法来使用“固定”代码。
或者您可以将规则放在公共文件中,而不是像@thebusybee 所建议的那样将它们分配给变量。
或者您可以完全省略规则,让 Make 使用带有额外标志的默认规则:
CPPFLAGS += $(DEPFLAGS)