Makefile 中的多行环境变量

Multiline environment variable in Makefile

我试图从 Makefile 中将一个多行变量传递给一个 cli 程序,但无法这样做。

生成文件

.PHONY: test
test: ## Run the Tests locally
        @echo $(SOME_VAR)
        r=$(echo $(SOME_VAR) | sed 's/"/\"/g')
        python3 test_env_var.py "$(r)"

其中 SOME_VAR 是一个包含多行文本字符串的环境变量(最后,我希望这个变量包含多行 JSON)。您能否建议我如何在 Makefile 中实现此目的?

Python代码:

import sys

print(sys.argv[1])

如果你的 SOME_VAR 确实是一个环境变量——也就是说,在它的环境中从外部提供给 make —— 那么你可以只依靠你的配方在它自己的环境中继承它:

选项 0

test:
        @echo "$${SOME_VAR}"
        python3 test_env_var.py "$${SOME_VAR}"

注意 $ 字符加倍以避免 make 对其进行解释,以便 shell 执行插值。


但我怀疑你的意思是你在 make 变量中有数据。在这种情况下,您的 echo $(SOME_VAR) 的问题与 python3 test_env_var.py $(SOME_VAR) 的原因几乎相同:不仅是换行符(如果您确实有换行符),还有其他对 [=57= 重要的字符],也会被误解。更重要的是,make 实现通常在单独的 shell 中执行配方的每一行,因此您不能指望在配方的一行中设置 shell 变量并在其中读回其值单独一行。

选项 1

如果您准备假设变量的值不包含任何单引号,那么您可以简单地用它引用:

test:
        @echo '$(SOME_VAR)'
        python3 test_env_var.py '$(SOME_VAR)'

JSON 数据应该在内部只使用双引号,所以从这个意义上说你应该没问题,但如果数据本身中有任何单引号,那将会中断。

但是请注意,单引号和双引号并不完全类似于 shell。例如,变量扩展、命令替换和反斜杠转义在双引号内被识别,而在单引号内则没有特殊字符被识别。因此,您真的应该考虑使用单引号,完全独立于这些字符在 JSON.

中的不同意义

选项 2

如果你愿意依赖GNUmake,那么你可以使用它的subst功能:

test:
        @echo '$(subst ','\'',$(SOME_VAR))'
        python3 test_env_var.py '$(subst ','\'',$(SOME_VAR))'

将数据中的每个单引号转换为四字符序列 '\''。由于所有内容都包含在单引号中,这些字符的每次出现都会关闭一个单引号字符串,呈现一个反斜杠转义的单引号(不能出现在单引号字符串内)并开始一个新的单引号字符串。

选项 3

但也不考虑。特别是如果你真的想要多行数据,考虑把它放在一个文件中,然后让配方从那里读取它。如果需要,可以是构建文件。

test:
        @echo "$$(cat test-arg)"
        python3 test_env_var.py "$$(cat test-arg)"

再次注意 $ 字符的加倍。