这是我正在研究的更为复杂的构建系统的一个简单例子。
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.c
和2/foo.o: 2/foo.c
规则正确创建了模式本身,但食谱本身不会被$T
扩展,直到它们实际执行为止;当然,$T
具有值2,即使在第一个配方中也是如此。
我知道强制变量在定义配方时扩展的唯一方法是将整个模式放在多行变量中,然后用$(eval)
展开它......这是怪诞的。
我意识到这里的答案可能是 no ,但还有其他方法可以强制$T
在上面的食谱中内联展开吗?
答案 0 :(得分:1)
据我所知,你有三个选择。
eval
等)。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中引入。