在模式定义时间

时间:2015-05-19 20:54:33

标签: gnu-make

这是我正在研究的更为复杂的构建系统的一个简单例子。

T := 1

$T/foo.o: $T/foo.c
  touch $T/foo.o  # yes, I know I can use $@, this is an example

T := 2

$T/foo.o: $T/foo.c
  touch $T/foo.o  # yes, I know I can use $@, this is an example

(两种模式都在包含文件中定义,因此它们必须是相同的文本。)

这不起作用。虽然使用1/foo.o: 1/foo.c2/foo.o: 2/foo.c规则正确创建了模式本身,但食谱本身不会被$T扩展,直到它们实际执行为止;当然,$T具有值2,即使在第一个配方中也是如此。

我知道强制变量在定义配方时扩展的唯一方法是将整个模式放在多行变量中,然后用$(eval)展开它......这是怪诞的。

我意识到这里的答案可能是 no ,但还有其他方法可以强制$T在上面的食谱中内联展开吗?

1 个答案:

答案 0 :(得分:1)

据我所知,你有三个选择。

  1. 目标特定变量
  2. 解析时规则定义(eval等)。
  3. 构造变量名称。
  4. 使用特定于目标的变量

    T := 1
    
    $T/foo.o: T:=$T
    $T/foo.o: $T/foo.c
      touch $T/foo.o  # yes, I know I can use $@, this is an example
    
    T := 2
    
    $T/foo.o: T:=$T
    $T/foo.o: $T/foo.c
      touch $T/foo.o  # yes, I know I can use $@, this is an example
    

    正如所讨论的in the comments所讨论的目标特定变量对所讨论目标的所有先决条件都是可见的(除非使用GNU make 3.82 private功能),这可能并不总是你想要的

    使用解析时规则定义

    define foorule
    $T/foo.o: $T/foo.c
            touch $T/foo.o  # yes, I know I can use $$$$@, this is an example
    endef
    
    T := 1
    $(eval $(foorule))
    
    T := 2
    $(eval $(foorule))
    

    但是(正如问题中所提到的)这并不是很漂亮,需要偶尔仔细协商扩展(对于那些希望在配方时扩展的东西,与那些不需要扩展的东西相比)。

    使用构造变量名称

    T := 1
    
    T$(T) := $T
    $T/foo.o: $T/foo.c
      touch $(T1)/foo.o  # yes, I know I can use $@, this is an example
    
    T := 2
    
    T$T := $T
    $T/foo.o: $T/foo.c
      touch $(T2)/foo.o  # yes, I know I can use $@, this is an example
    

    这与使用private具有相同的非传播效果,代价是将值“泄漏”到每个目标(在构造名称下)。

    你可以将它包装在一个定义中,以删除变量的手动构造和使用(尽管在大多数情况下,仅仅使用定义本身对你有什么好处)。

    可以将私有和定义或构造的makefile组合用于make版本兼容性。但是,private中未指明对.FEATURES的支持,因此需要使用oneshell作为代理,因为它也在make 3.82中引入。