Makefile 请勿在Make命令中解释为Make变量

Makefile 请勿在Make命令中解释为Make变量,makefile,Makefile,我在Makefile中有以下代码: $(TCLNAME).batch.tcl: $(TCLNAME).tcl echo source $::env(TOOLS_DIR)/my.tcl > $@ 我想在$(TCLNAME)中打印的内容是: source$::env(TOOLS_DIR)/my.tcl 但是我得到了一个错误,因为$::env(TOOLS_DIR)被解释为Make变量,并且它在$之后需要() 如何使该行按原样打印,而不是将其解释为make变量? 我尝试使用转义字符,

我在Makefile中有以下代码:

$(TCLNAME).batch.tcl: $(TCLNAME).tcl
      echo source $::env(TOOLS_DIR)/my.tcl > $@
我想在
$(TCLNAME)
中打印的内容是:
source$::env(TOOLS_DIR)/my.tcl

但是我得到了一个错误,因为
$::env(TOOLS_DIR)
被解释为Make变量,并且它在
$
之后需要

如何使该行按原样打印,而不是将其解释为make变量?
我尝试使用转义字符,如
\$::env(TOOLS\u DIR)
,但也不起作用。

用另一个
$
转义
$
,用反斜杠转义括号:

$(TCLNAME).batch.tcl: $(TCLNAME).tcl
    echo source $$::env\(TOOLS_DIR\)/my.tcl > $@

用另一个
$
转义
$
,用反斜杠转义括号:

$(TCLNAME).batch.tcl: $(TCLNAME).tcl
    echo source $$::env\(TOOLS_DIR\)/my.tcl > $@

一种更普遍的逃逸方法,如疯狂科学家所建议的:

  • 将每个
    $
    替换为
    $
    $
    是Make对其进行特殊处理的唯一符号

  • 用单引号将整个字符串括起来。Make不关心它们,它们是用于shell的

    • 如果需要打印单引号,请将每个
      '
      替换为
      '\'
最终结果是:

echo 'source $$::env(TOOLS_DIR)/my.tcl' > $@

通过这种方式,只需将
$
加倍(以防止Make将其解释为变量)。其他所有内容都由单引号处理(单引号对Make没有特殊意义,用于shell)。

一种更通用的转义方法,如MadScientist所建议:

  • 将每个
    $
    替换为
    $
    $
    是Make对其进行特殊处理的唯一符号

  • 用单引号将整个字符串括起来。Make不关心它们,它们是用于shell的

    • 如果需要打印单引号,请将每个
      '
      替换为
      '\'
最终结果是:

echo 'source $$::env(TOOLS_DIR)/my.tcl' > $@

这样,只需将
$
加倍(以防止Make将其解释为变量)。其他所有内容都由单引号处理(单引号对Make没有特殊意义,用于shell).

这还不够:你也需要从shell中转义
$
。我建议在要回显的整个字符串周围使用单引号,而不是反斜杠。@MadScientist:我通常不会质疑你的帖子——你的Make技术知识比我的要好——但我看不出问题所在。我的解决方案怎么会失败?d它是否取决于shell的选择?如果我能验证错误,我将删除我的答案。在许多shell中,甚至可能是大多数shell中,它都可以正常工作,因为不带引号的
$
后面的字符不是有效字符,因此大多数shell不会展开它。也就是说,
$foo
作为shell变量展开(OP不想要的)但是对于大多数shell,
$:
没有展开,只是传递(OP想要的)。但是,根据POSIX,如果未引用的
$
后面的字符不是“正常”字符,则
sh的行为是是未指定的,这意味着shell可以做其他事情。最安全的方法是引用shell中的所有
$
,以避免扩展。@疯狂科学家:我没有发现失败案例,但我相信危险存在。我将删除此答案。编辑:我无法删除已接受的答案。这些注释必须足够。您可以编辑添加引号的问题;这就是所需要的。答案很好,只是可能更安全一点。这还不够:你还需要将
$
从shell中转义出来。我建议在整个字符串周围使用单引号来进行回显,而不是反斜杠。@MadScientist:我通常不会质疑你的帖子--y我们对Make的技术知识比我的要好——但我看不出问题所在。我的解决方案怎么会失败?这取决于shell的选择吗?如果我能验证错误,我将删除我的答案。在许多(甚至大多数)shell中,它可以正常工作,因为不带引号的
$
后面的字符不是有效字符,因此大多数shell我不会展开它。也就是说,
$foo
被展开为shell变量
foo
(OP不需要),但对于大多数shell,
$:
没有展开,只是传递(OP需要)但是,根据POSIX,如果不带引号的
$
后面的字符不是“正常”字符,则
sh
的行为是未指定的,这意味着shell可以做其他事情。最安全的方法是引用shell中的所有
$
,以避免扩展。@疯狂科学家:我没有发现失败案例,但我相信危险存在。我将删除此答案。编辑:我无法删除已接受的答案。这些注释必须足够。您可以编辑添加引号的问题;这就是所需要的。答案很好,只是可能更安全一点。