【问题标题】:Is it possible to use Makefile "define" to define a target plus its recipes?是否可以使用 Makefile“定义”来定义目标及其配方?
【发布时间】: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 ""

这意味着他们未能为目标包含自动的$&lt;$@ 变量

那么是否有可能创建可重用的规则,这些规则可以是 defined 作为变量,而 -included 在其他 Makefile 中使用变量引用?我错过了什么吗?

【问题讨论】:

  • 您是否尝试将编译规则直接移动到一个通用的 Makefile 中?最后,它们总是相同的。

标签: c++ c linux makefile


【解决方案1】:

Make 是一位年迈的爷爷——今年 45 岁。考虑迁移到更新的东西——CMake、Scons、Meson 等。这些工具将自动处理依赖关系,将是可移植的,将具有更多功能,并将使您免于无休止(且毫无意义)的重新发明轮子的时间。

是否可以使用 Makefile "define" 来定义目标及其配方?

您必须评估通话。

define CXX_OBJ_COMPILE =
%.o: %.cpp
    $(CXX_WRITE_DEP)
endef

$(eval $(CXX_OBJ_COMPILE))

这意味着它们没有包含目标的自动 $

确实如此 - $@ 就像“先扩展”,它们需要留待扩展。

CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$$<" -o "$$@" $(DEPFLAGS)

【讨论】:

  • 谢谢!我正在从事一些大学项目,我确信在学习 C/C++、数据结构或 OS 编程时,我的本科教育不会教授 CMake 或 Automake 或其他构建工具。我需要在大学之外单独了解那些高级构建工具。
【解决方案2】:

在我看来,你有三个选择。

您可以按照@KamilCuk 的指示使用正确的语法来使用“罐装”代码。

或者您可以将规则放在公共文件中,而不是像 @thebusybee 建议的那样将它们分配给变量。

或者您可以完全省略规则,让 Make 使用带有额外标志的默认规则:

CPPFLAGS += $(DEPFLAGS)

【讨论】:

    猜你喜欢
    • 2011-07-15
    • 2018-01-30
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多