在 Makefile 中,早期或后期扩展变量是否更好,特别是在配方中(并与 eval 函数结合使用)



我在 Makefile 中使用了一个带有 eval 的变量,它在项目的每个子目录中创建一个静态模式规则。但是我有两种方法可以处理它。

define  STATIC_OBJ_RULE
$(OBJ_$(DIR)): $(OBJ_LOCAL_DIR)%.o: $(SRC_LOCAL_DIR)%.c $(DEP_LOCAL_DIR)%.dep 
| $(OBJ_LOCAL_DIR) $(DEP_LOCAL_DIR)
    $(COMPILE)
    $(POSTCOMPILE)
    $(RM) $$(word 2,$$^).tmp
    $(TOUCH) $$@
endef

或者那样

define  STATIC_OBJ_RULE
$(OBJ_$(DIR)): $(OBJ_LOCAL_DIR)%.o: $(SRC_LOCAL_DIR)%.c $(DEP_LOCAL_DIR)%.dep 
| $(OBJ_LOCAL_DIR) $(DEP_LOCAL_DIR)
    $$(COMPILE)
    $$(POSTCOMPILE)
    $(RM) $$(word 2,$$^).tmp
    $(TOUCH) $$@
endef

(区别在于第三行,转义或不转义 COMPILE 和 POSTCOMPILE,它们生成目标文件和相应的依赖文件,并对依赖关系进行一些后处理)

对于第一种情况,每次运行目标文件的配方时,都会减少扩展,但我需要使用$(其中的自动变量)转义其他变量(组成 COMPILE 和 POSTCOMPILE)

另一方面,由于make的目的是避免重新编译(当然是不必要的),这真的能实现什么吗?

那么,您是否认为一个是最佳实践而不是另一个?(或者我只是想太多了不值得的事情?

我很确定你必须用第二种方式来做:第一种方法是行不通的。

为什么? 因为如果你有一个扩展到编译行的变量COMPILE,该变量的值必须包含自动变量,如$@$<等,否则它就不能工作。 例如,它可能是这样的:

COMPILE = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

什么的。

如果您使用第一种方法,则在解析配方时将扩展COMPILE变量,这意味着自动变量将展开,然后在运行规则时不会扩展,这意味着它们将为空,并且您的配方将不起作用。

一般来说,当像这样使用 define/eval 时,我更喜欢转义食谱的内容,这样 tose 食谱的所有工作方式都与 tose 食谱的工作方式相同,如果您直接不使用 define/eval 编写它们,它会起作用。

最新更新