Makefile中的shell脚本无法按预期工作

时间:2015-02-26 10:15:19

标签: bash shell makefile

我在这里和其他地方找到了很多答案,但没有一个有效。请帮帮我。

我需要设置一些环境变量,部分是在一些脚本中完成的,从主脚本调用,部分直接调用。这是一个显示不需要的行为的最小Makefile:

FC := ifort

SHELL := /bin/bash

some_target: load_ifort
    $(FC) file.f

load_ifort:
    source /usr/local2/bin/ifort-compilervars.sh ia32
    export LM_LICENSE_FILE=/usr/local2/misc/intel2013/flexlm/server.lic

如果我调用make,我会收到“ifort:command not found”错误。如果我在调用make之前在命令行上手动执行两个comamnds,那么找到ifort并且一切都很好。

我缺少什么?

2 个答案:

答案 0 :(得分:2)

配方中的每一行都在一个单独的子shell中执行。所以你创建一个shell来源.sh文件,然后退出并忘记所有内容,然后另一个shell以一个干净的平板开始。

在您的情况下,直接的解决方案是在单个变量中收集所有这些命令。我已将LM_LICENSE_FILE分配考虑在内,因为可以直接在Make中完成,但您也可以将其包含在FC变量中。

LM_LICENSE_FILE := /usr/local2/misc/intel2013/flexlm/server.lic
export LM_LICENSE_FILE

FC := source /usr/local2/bin/ifort-compilervars.sh ia32; \
    ifort

some_target:
    $(FC) file.f

如果make命令可以直接运行shell命令,你可以include,或者可以通过一个简单的脚本将sh文件翻译成Make命令。

另一种选择是在PATH中创建一个简单的包装器;可以称之为fc

#!/bin/sh
. /usr/local2/bin/ifort-compilervars.sh ia32
ifort "$@"

然后只使用当前fc的{​​{1}}。 (如果$(FC)文件包含Bash结构,则无论名称如何,都应将shebang更改为ifort-compilervars.sh。)

答案 1 :(得分:1)

通常,只有单线程shell命令“工作”。从关于“bash”的评论来看,你似乎可能正在使用GNU make。在您的示例中,GNU make手册index中找不到“source”一词。 (如果你在一个有效的例子中找到了这个,那么从那开始会很有帮助)。有两种类型的感兴趣的变量:

  • makefile变量,存在于make程序中
  • 环境变量,即“导出”

后者将包括$ PATH,用于查找程序。要更新它,您需要shell命令。但是(在make程序中缺少一些特殊规定),shell脚本中的导出变量不会 up 传递给make程序,并且可用于makefile的下一行。

您可以重新组织makefile以提供一个规则,该规则将源命令和其他初始化组合到一个shell命令中,然后将该命令重复(将这些变量携带)到子进程中,然后进行编译。像

这样的东西
build:
    sh -c "source /usr/local2/bin/ifort-compilervars.sh ia32; \
           export LM_LICENSE_FILE=/usr/local2/misc/intel2013/flexlm/server.lic; \
           $(MAKE) some_target"
some_target: load_ifort
    $(FC) file.f