在Makefile命令中声明的访问变量

时间:2016-06-23 13:13:06

标签: bash shell makefile

我试图访问上一个命令声明的变量(在Makefile中)。

这里是Makefile

all:
  ./script1.sh
  ./script2.sh

这里是声明我想要访问的变量的脚本,script1.sh

#!/usr/bin/env bash
myVar=1234

此处的脚本试图访问之前定义的变量script2.sh

#!/usr/bin/env bash
echo $myVar

不幸的是,当我运行make时,myVar无法访问。还有另外一种方法吗?感谢。

2 个答案:

答案 0 :(得分:3)

Make将在自己的shell中运行每个shell命令。当shell退出时,它的环境就会丢失。

如果您希望下一个脚本中的变量可用,那么有一些构造可以执行此操作。例如:

all:
    ( . ./script1.sh; ./script2.sh )

这会导致Make启动一个shell来处理这两个脚本。

另请注意,您需要导出变量,以便在第二个脚本中显示变量;未导出的变量仅适用于本地脚本,而不适用于它启动的子shell。

更新(根据Kusalananda的评论):

如果希望shell命令填充MAKE变量而不仅仅填充环境变量,则可能有一些选项取决于您正在运行的Make版本。例如,在BSD make和GNU make中,你可以使用"变量赋值修饰符"包括(来自BSD制作手册页):

 !=      Expand the value and pass it to the shell for execution and
         assign the result to the variable.  Any newlines in the result
         are replaced with spaces.

因此,使用BSD make和GNU make,你可以这样做:

$ cat Makefile

foo!=   . ./script1.sh; ./script2.sh

all:
    @echo "foo=${foo}"

$
$ cat script1.sh
export test=bar
$
$ cat script2.sh
#!/usr/bin/env bash

echo "$test"
$
$ make
foo=bar
$

请注意,script1.sh不包含任何shebang,因为它是 sourced ,因此在调用shell中运行,无论是什么。这使得shebang线只是一个评论。如果您使用的是默认shell为POSIX但不是bash(如Ubuntu,Solaris,FreeBSD等)的系统,这应该仍然有效,因为POSIX shell都应该理解导出变量的概念。

答案 1 :(得分:1)

两个单独的脚本调用创建了两个独立的环境。第一个脚本在其环境中设置变量并退出(环境丢失)。第二个脚本在其环境中没有该变量,因此它输出一个空字符串。

除了父shell的环境与其子shell之间的环境之外,环境变量不能在环境之间传递(不是相反)。传递到子shell的变量只是 那些父shell具有export - ed的变量。因此,如果第一个脚本调用了第二个脚本,则会输出该值(如果它是export - 在第一个脚本中编辑)。

在shell中,您将source第一个文件在当前环境中设置变量(然后export!)。但是,在Makefile中,它有点棘手,因为没有方便的source命令。

相反,您可能需要阅读this StackOverflow question

根据@ ghoti的回答编辑:@ghoti有一个很好的解决方案,但我会在这里留下我的答案,因为它更详细地解释了环境变量以及我们可以做些什么,而不是在环境之间传递它们。