执行 bash 个脚本的变量中的 makefile 变量

makefile variables within variables executing bash scripts

我有一个 makefile,我想 运行 对抗 linux (debian/Ubuntu) 和 Windows/Cygwin.

我需要根据 运行ning 环境做一些稍微不同的事情,我得出了以下代码,它应该在变量中存储一个字符串,如果是 foo OS 是 linux,否则 foo.exe:

EXECUTABLE_FILENAME=bash -c 'os_type=`uname`; if [ $os_type == "Linux" ]; then echo "foo"; else echo "foo.exe"; fi'

然后我想在另一个变量中使用该变量,例如:

GODEPBUILD=$(godep go build -o $(EXECUTABLE_FILENAME))

上一个 with/without 通过 $(...some stuff...) 进行的评估(请参阅下文了解我为完成这项工作所做的所有测试)

最后我想 "run" 在 makefile 的任务中的其他地方执行该命令,例如:

build-all:
   @echo -e "build my project"
   $(GODEPBUILD)

我试过很多不同的组合

但我收到各种 bash 错误,例如:

我正在执行这一系列步骤,因为我需要将 go 工具链的许多命令包装到另一个名为 godep 的工具中,我还需要将其与操作的一些特定功能结合起来系统(例如我坚持使用的文件名)。我在 makefile 的开头定义了 go 工具链的许多不同 "commands",例如:

GODEP_VERSION=godep version
GODEPRESTORE=godep restore
GODEPTEST=godep go test -v
GOCLEAN=go clean

我在 makefile 任务中将这些 "commands" 称为 $(GODEP_VERSION)(或者 -$(GODEP_VERSION),如果我需要忽略 stderr),对我来说很高兴以类似的方式添加 "build command"。

make版本是:

这件事有可能吗?

我如何实现不同 "small scripts" 的这种组合来构建 make 应该 运行 在任务中的最终命令?

您当然希望 bash 命令的 output 作为文件名,对吧?您正在使用 bash 命令本身作为文件名。即 $(EXECUTABLE_FILENAME) 是由几个单词组成的字符串。当您将其传递给 godep 命令时,它会作为多个参数传递:

godep go build -o $(EXECUTABLE_FILENAME)

变为:

godep go build -o bash -c 'os_type=`uname`; if [ s_type == "Linux" ]; then echo "foo"; else echo "foo.exe"; fi'

这完全是胡说八道(请注意,$o 被扩展为 make 变量,但这是你的问题中最少的)。

您肯定要运行 bash 命令来决定文件名。您可以使用 make 的 $(shell ...) 函数 运行 一个 shell 命令:

EXECUTABLE_FILENAME = $(shell os_type=`uname` ; if [ $$os_type == Linux ]; then echo foo ; else echo foo.exe ; fi)

注意我使用 $$os_type 来引用 shell 变量,因此 make 在调用 shell.[=37= 之前不会尝试扩展 $os_type ]

但我会将其简化为:

EXECUTABLE_FILENAME = foo$(shell [ `uname` == Linux ] || echo .exe)

或者也许:

EXECUTABLE_SUFFIX = $(shell [ `uname` == Linux ] || echo .exe)
EXECUTABLE_FILENAME = foo$(EXECUTABLE_SUFFIX)

现在 make 变量 $(EXECUTABLE_FILENAME) 将扩展为文件名。

下一个问题在这里:

GODEPBUILD=$(godep go build -o $(EXECUTABLE_FILENAME))

这是什么意思?为什么将它包含在 $(...) 中?尝试 运行 一个名为 godepmake 函数,当然你只是想要:

GODEPBUILD = godep go build -o $(EXECUTABLE_FILENAME)

然后当您在食谱中使用它时,它会扩展为:

build-all:
   @echo -e "build my project"
   godep go build -o foo

或者:

build-all:
   @echo -e "build my project"
   godep go build -o foo.exe

N.B。作为可选(但推荐)的改进,您应该使用 := 来设置 make 变量,否则每次使用时它们都会扩展。这意味着每次您引用使用 $(EXECUTABLE_SUFFIX) 的变量时,shell 命令又是 运行。将其更改为使用 := 将意味着它被评估一次:

EXECUTABLE_SUFFIX := $(shell [ `uname` == Linux ] || echo .exe)

同样,您也可以对其他变量使用 :=

EXECUTABLE_FILENAME := foo$(EXECUTABLE_SUFFIX)
GODEPBUILD := godep go build -o $(EXECUTABLE_FILENAME)

(这些并不重要,只要 EXECUTABLE_SUFFIX 使用 := 并且已经包含文件名即可)。