0

我有一个makefile我想在 linux (debian/Ubuntu) 和 Windows/Cygwin 上运行的。

我需要根据运行环境做一些稍微不同的事情,我得到了以下代码,它应该在变量中存储一个字符串,foo如果操作系统是 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))

前一个有/没有评估通过$(...some stuff...)(见下文我为完成这项工作所做的所有测试)

最后,我想在任务中的其他地方“运行”该命令makefile,例如:

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

我尝试了许多不同的组合

  • 有/无$(some stuff here)
  • 带/不带单引号'
  • 带/不带 bash "`"
  • 带/不带包装bash -c '...some commands here...'

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

  • invalid option -- 'c'
  • go编译器抱怨此消息为EXECUTABLE_FILENAME空:flag needs an argument: -o
  • 无声地忽略$(GODEPBUILD)(我相信因为它以某种方式计算为一个空命令)

我正在执行这一系列步骤,因为我需要将go工具链的许多命令包装到另一个名为godep. 我go在开头定义了工具链的许多不同“命令”,makefile例如:

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

makefile我在任务中调用这些“命令” $(GODEP_VERSION)(或者-$(GODEP_VERSION)如果我需要忽略stderr),对我来说,以类似的方式添加“构建命令”是件好事。

make版本是:

  • 4.1 在 Ubuntu 上
  • 4.2.1 在 Cygwin 上

这件事有可能吗?

我怎样才能实现不同“小脚本”的这种组合来构建make应该在任务中运行的最终命令?

4

1 回答 1

1

当然,您希望 bash 命令的输出作为文件名,对吗?您正在使用 bash 命令本身作为文件名。ie$(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 命令来决定文件名。$(shell ...)您可以使用 make 的功能运行 shell 命令:

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

注意我曾经引用一个 shell 变量,所以 make在调用 shell 之前$$os_type不会尝试扩展。$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))

这是什么意思?你为什么把它附在里面$(...)?这试图运行一个make名为 的函数godep,当然你只是想要:

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

NB 作为一个可选的(但推荐的)改进,您应该使用它:=来设置 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使用过:=并且已经包含文件名)。

于 2017-10-10T16:55:19.127 回答