【问题标题】:Dealing with dependency poisoning in makefiles处理 makefile 中的依赖中毒
【发布时间】:2011-12-03 04:16:50
【问题描述】:

我正在重写一个最初“设计”(或不是,视情况而定)为递归的旧版本。作为序言,总有一天我们会转向更现代、更有表现力和更强大的东西(例如,scons)。然而,那一天不是现在。

作为这项工作的一部分,我正在将应该是通用变量/宏和目标/配方的内容整合到一些简洁的规则文件中,这些规则文件将作为主要构建的一部分包含在内。构建的每个子部分都将使用一个小的 makefile 来添加目标和依赖项,而在这些子 makefile 中添加的变量很少。顶级的 makefile 将包含所有的 makefile,允许所有内容都对依赖树做出贡献。

我必须承认,我完全不相信人们会在修改 makefile 时使用良好的判断力。作为我担心的一个例子:

CFLAGS = initial cflags
all: A.so
%.so %.o:
  @echo "${@}: ${CFLAGS} : ${filter 5.o,${^}} ${filter %.c,${^}"

%.c :
  true

%.o : %.c
A.so : B.so a1.o a2.o a3.o
B.so : b1.o b2.o b3.o
A.so : CFLAGS += flags specific to building A.so

如果我没有搞砸复制那个例子,情况是这样的:A.so 将链接到B.so,而A.so 的对象需要构建特殊标志;但是,B.soB 的对象将继承对 CFLAGS 的更改。

我宁愿有一个单一的目标来构建大多数(如果不是全部)目标文件,甚至可以专门为那些需要稍微不同标志的那些对象修改 CFLAGS,以促进对更通用目标的重用(如果只需要担心一个目标/配方,则调试会更容易)。

在我完成重新构建这个构建之后,我完全不相信有人不会做这种愚蠢的事情;更糟糕的是,如果我不在身边审核,它可能会通过同行评审。

我一直在考虑做这样的事情:

% : CFLAGS = initial cflags

... 这将防止依赖中毒,除非有人随后更新它:

% : CFLAGS += some naive attempt at altering CFLAGS for a specific purpose

但是,如果只有 1000 个目标(非常保守的估计),并且分配给变量的内存大约为 1k,那么我们将增加大约 1mb 的开销,这可能会显着影响查找 CFLAGS 值所需的时间通过配方工作(当然取决于 gmake 的架构)。

简而言之,我想我的问题是:在生成文件中防止依赖中毒的理智/好方法是什么?有比我概述的更好的策略吗?


编辑

如果有人尝试按照上述范围变量的路径进行研究,我会遇到一开始并不完全明显的细微差别。

% : INCLUDES :=
# ...
SOMEVAR := /some/path
% : INCLUDES += -I${SOMEVAR}
...
SOMEVAR :=

当使用:= 创建变量时,应立即评估:= 右侧的所有内容,而如果仅使用=,则会延迟评估,直到目标配方评估INCLUDES

但是,当评估目标配方时,SOMEVAR 的评估结果为空。如果您将定义更改为:

% : INCLUDES := whatever
# ...
SOMEVAR := /some/path
% : INCLUDES := ${INCLUDES} -I${SOMEVAR}
...
SOMEVAR :=

...然后它会强制立即评估 SOMEVAR 而不是延迟评估,但 INCLUDES 不会评估其先前范围的定义,而是评估全局定义。

$(flavor ...) 表示INCLUDESsimple,而$(origin ...) 返回file;无论您使用:= 还是+=,都会出现这种情况。

简而言之,如果您在作用域变量上使用+=,它只会使用作用域为该目标的变量的定义;它不看全局变量。如果你使用:=,它只使用全局变量。

【问题讨论】:

    标签: makefile dependencies


    【解决方案1】:

    如果您在文件名中避免使用不寻常的字符,则可以使用变量名替换选择特定于目标的变量:

    A.so_CFLAGS = flags specific to building A.so
    %.so %.o:
        @echo "${@}: ${CFLAGS} ${$@_CFLAGS} : ${filter %.o,${^}} ${filter %.c,${^}}"
    

    这显然不会将当前构建的存档的名称传播到为该库构建的对象,但我不知道这是否需要。

    这种方法自然有一些明显的缺陷,比如无法实际覆盖CFLAGS。但是,考虑到automake 也有同样的问题要解决,并且使用愚蠢的文本替换,我想很多人已经在这里找不到好的解决方案了。

    作为旁注,您可以考虑使用 automake 而不是重新设计它。

    【讨论】:

    • +1 表示 automake 备注;我并不完全认同命名这件事,但这也不是一个糟糕的主意。
    猜你喜欢
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    相关资源
    最近更新 更多