首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态Makefile变量赋值

动态Makefile变量赋值
EN

Stack Overflow用户
提问于 2012-02-08 10:25:07
回答 2查看 6.3K关注 0票数 2

我有以下Makefile,我想创建影响CPPFLAGS和CFLAGS中的值的"debug“和"optimal”目标,如下所示:

代码语言:javascript
复制
include Makefile.inc

DIRS    = applib
EXE_APPFS       = appfs
EXE_APPMOUNT    = appmount
EXE_APPINSPECT  = appinspect
EXE_APPCREATE   = appcreate
BUILD_APPFS     =
BUILD_APPMOUNT  = -DAPPMOUNT
OBJS_APPFS      = main.o appfs.o
OBJS_APPMOUNT   = main.o appmount.o
OBJS_APPINSPECT = appinspect.o
OBJS_APPCREATE  = appcreate.o
OBJLIBS = libapp.a
LIBS    = -L. -lpthread -lstdc++ -ldl -lrt -largtable2 -lm ./libapp.a     /usr/lib64/libfuse.a

# Optimization settings.
debug: CPPFLAGS=$(CPPFLAGS_DEBUG)
debug: CFLAGS=$(CFLAGS_DEBUG)
debug:
    @true

optimal: CPPFLAGS=$(CPPFLAGS_OPTIMAL)
optimal: CFLAGS=$(CFLAGS_OPTIMAL)
optimal:
    @true

appfs: appfs.o $(OBJLIBS)
    @echo "stuff is done here"

appmount: appmount.o $(OBJLIBS)
    @echo "stuff is done here"

appmount_optimal: optimal appmount

我遇到的问题是,"debug“和" optimal”中的变量赋值不会传递到其他目标(尽管如果我将@echo $(CPPFLAGS)放在optimal中就可以了)。无论是"make optimal appmount“还是"make appmount_optimal”都不能得到我所期望的结果。

当然,有一种方法可以根据您是否想要调试来定义CPPFLAGS和CFLAGS,对吧?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-08 14:06:09

如果您使用的是GNU make,那么您有两个选择(除了递归make调用之外,它具有上面概述的问题)。

第一个选项是使用特定于目标的变量。您在原始示例中使用了它们:

代码语言:javascript
复制
debug: CPPFLAGS=$(CPPFLAGS_DEBUG)
debug: CFLAGS=$(CFLAGS_DEBUG)

optimal: CPPFLAGS=$(CPPFLAGS_OPTIMAL)
optimal: CFLAGS=$(CFLAGS_OPTIMAL)

您遗漏的是特定于目标的变量是由它们的先决条件继承的。因此,您需要声明"debug“和"optimal”的先决条件(它们本身不必有配方;实际上,它们可以被声明为.PHONY)。举个例子:

代码语言:javascript
复制
debug: CPPFLAGS=$(CPPFLAGS_DEBUG)
debug: CFLAGS=$(CFLAGS_DEBUG)
debug: appfs appmount

optimal: CPPFLAGS=$(CPPFLAGS_OPTIMAL)
optimal: CFLAGS=$(CFLAGS_OPTIMAL)
optimal: appfs appmount

现在,如果您运行"make debug“,它将使用CPPFLAGS和CFLAGS的调试设置构建appfs和appmount;如果您运行"make optimal”,它将使用最优设置。

然而,这与对make的递归调用有相同的缺点;如果直接运行"make appfs“,那么这两个设置都不会被使用;特定于目标的变量是从导致在这个make调用中构建目标的父级继承而来的。如果这两个目标都不在父目标列表中,则不会使用它们特定于目标的变量。

第二个选项是使用MAKECMDGOALS变量来决定用户要求的是优化构建还是调试构建。例如,如下所示:

代码语言:javascript
复制
CPPFLAGS_debug = <debug CPPFLAGS>
CFLAGS_debug = <debug CFLAGS>

CPPFLAGS_optimal = <optimal CPPFLAGS>
CFLAGS_optimal = <optimal CFLAGS>

STYLE := $(firstword $(filter debug optimal,$(MAKECMDGOALS)))
$(if $(STYLE),,$(error No style "debug" or "optimal" set))

CPPFLAGS = $(CPPFLAGS_$(STYLE))
CFLAGS = $(CFLAGS_$(STYLE))

debug optimal:
.PHONY: debug optimal

或者,如果您愿意,您可以选择一个默认行为,而不是抛出错误;这将默认选择"debug“,例如:

代码语言:javascript
复制
STYLE := $(firstword $(filter optimal,$(MAKECMDGOALS)) debug)

然而,重要的是要注意到,这似乎很难做到的原因是,你所要求的是天生有缺陷的。建议根据构建时参数以两种不同方式之一构建目录中的单个派生文件是自找麻烦的。您如何知道最后使用的是哪种变体?假设您使用优化运行make,然后修改一些文件,然后再次运行make,这一次使用debug...现在,您的一些文件已优化,而另一些文件正在调试。

处理代码的不同构建变体的正确方法是确保派生文件是唯一的。这意味着调试目标被写入到一个目录,而优化的目标被写入到另一个目录。一旦做出了这样的区分,剩下的就很容易被忽略了:您只需在编写调试目标的规则时使用调试标志,在编写优化目标的规则时使用优化标志。

票数 6
EN

Stack Overflow用户

发布于 2012-02-08 10:33:23

一种可怕但相当有效的技术是:

代码语言:javascript
复制
# Optimization settings.
debug:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_DEBUG)" CFLAGS="$(CFLAGS_DEBUG)"

optimal:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_OPTIMAL)" CFLAGS="$(CFLAGS_OPTIMAL)"

这意味着make debug使用命令行上设置的调试标志重新调用make,而make optimal使用命令行上设置的最佳标志重新调用make

这并不完美;这意味着在重新调用make时将运行默认规则。

您可以使用以下命令来改变这一点:

代码语言:javascript
复制
# Optimization settings.
debug:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_DEBUG)" CFLAGS="$(CFLAGS_DEBUG)" debug_build

optimal:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_OPTIMAL)" CFLAGS="$(CFLAGS_OPTIMAL)" optimal_build

现在,它为调试构建和最佳构建运行两个不同的构建目标。其他规则,如cleandepend,则不会得到特殊处理。

命令行上的+符号表示“即使在make -n下也可以运行此规则”,这可能就是您想要的。$(MAKE)表示法也可以达到同样的效果。如果您的make不喜欢+标志,请尝试删除它们。

这不会让我在调试模式下执行'make debug appmount‘来构建appmount目标,不是吗?它只允许'make debug‘来构建调试中的所有目标。

你是对的;这就是为什么它不完美的原因。如果你幸运的话,其他人会想出更好的解决方案。有一种稍微有点偏颇的方法可以或多或少地实现你想要的:

代码语言:javascript
复制
BUILD_TARGET = all

# Optimization settings.
debug:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_DEBUG)" CFLAGS="$(CFLAGS_DEBUG)" $(BUILD_TARGET)

optimal:
    +$(MAKE) CPPFLAGS="$(CPPFLAGS_OPTIMAL)" CFLAGS="$(CFLAGS_OPTIMAL)" $(BUILD_TARGET)

现在,当您运行make debug时,它将默认使用调试选项重新运行并构建all目标。但是,您可以使用以下命令进行更改:

代码语言:javascript
复制
make optimal BUILD_TARGET="appmount totherprog"

这将构建两个具有最佳标志的命名目标。最初的命令行不是非常优雅,但它可以将您带到目的地--差不多。仔细选择缺省值和覆盖它们的能力应该会让你找到你需要的地方。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9186994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档