如何防止make / shell中的字符串评估?

时间:2017-09-27 13:04:26

标签: bash shell makefile gnu-make

我有这个makefile:

echo:
    echo "PASS=$(PASS)"

我调用的是:

PASS='MYPA$$' make

这告诉我:

echo "PASS=MYPA$"
PASS=MYPA$

有人正在评估$$ - > $

这是外壳吗?不是在输入值时,因为我使用单引号,阻止shell对其进行评估。

也许make调用的shell正在执行此操作...

或者它可能是make本身?

我该如何避免呢?

1 个答案:

答案 0 :(得分:4)

make变量

最好将make变量视为,而不是传统变量(实际上在某些版本的make中,变量称为宏)。原因是,每次引用变量时,it is expanded

文档中的示例说明了标准recursively expanded variables行为:

foo = $(bar)
bar = $(ugh)
ugh = Huh?

all:
    echo $(foo)

# echoes: Huh?
# `$(foo)' expands to `$(bar)' which expands to `$(ugh)' which finally expands to `Huh?'

如果您使用的是GNU make,则避免进一步扩展的一种方法是使用simply expanded variables

  

简单扩展变量由使用:=的行定义(请参阅设置变量一节)。简单扩展变量的值是一次扫描,当定义变量时,扩展对其他变量和函数的任何引用。简单扩展变量的实际值是扩展您编写的文本的结果。它不包含对其他变量的任何引用;它包含了定义此变量时的值。

虽然简单地扩展变量在大多数编程语言中的行为更像变量,但它们的唯一用法并不能解决环境变量的问题。此处进行扩展,因为即使第一个引用var := $(PASS)也会从$$环境变量中展开PASS

避免扩展环境变量

我们可以使用make中的shell函数来读取shell中的环境变量(而不是在make中展开它):

expanded := $(shell echo "$$PASS")

test:
    echo 'PASS=$(expanded)'
    echo "PASS=$$PASS"

shell函数将在shell中执行echo "$PASS"$$在执行函数时由$扩展为make,以及结果( shell变量PASS)的值将存储在make变量expanded中。现在可以在make的其他地方自由使用此变量,而无需进一步扩展。

在将结果替换为周围文本之前,结果上唯一的处理make是将每个换行符或回车符/换行符对转换为单个空格。它还会删除尾随(回车和换行)换行符,如果它是结果中的最后一行。

上面的示例说明了如何在{{1}中使用make变量 expanded 和环境变量 PASS 脚本:

Makefile