有没有更好的方法来从makefile中设置env变量的脚本?如何在Makefile中编写脚本?
FLAG ?= 0
ifeq ($(FLAG),0)
export FLAG=1
/bin/myshell -c '<source scripts here> ; $(MAKE) [email protected]'
else
...targets...
endif
有没有更好的方法来从makefile中设置env变量的脚本?如何在Makefile中编写脚本?
FLAG ?= 0
ifeq ($(FLAG),0)
export FLAG=1
/bin/myshell -c '<source scripts here> ; $(MAKE) [email protected]'
else
...targets...
endif
要回答这个问题的问:你不能。
基本问题是子进程不能改变父进程的环境。 shell通过解决了这个问题,而不是在分割一个新进程时source
'ing,但只是在shell的当前版本中运行这些命令。这工作正常,但make
不是/bin/sh
(或脚本的任何shell),并不理解该语言(除了他们有共同的位)。
多德和Foo呸已经解决了一个可能的解决方法,所以我会建议其他(假设你正在运行GNU做):后期处理的shell脚本到兼容make文字和结果包括:
shell-variable-setter.make: shell-varaible-setter.sh
postprocess.py @^
# ...
else
include shell-variable-setter.make
endif
凌乱的细节留作练习。
如果你的目标仅仅设置环境变量作,为什么不把它放在Makefile的语法和使用include
命令?
include other_makefile
如果你必须调用shell脚本,拍摄效果在shell
命令:
JUST_DO_IT=$(shell source_script)
shell命令应该在目标之前运行。但是,这不会设置环境变量。
如果您想要在构建中设置环境变量,请编写一个单独的shell脚本来源环境变量和调用make。然后,在makefile中,让目标调用新的shell脚本。
例如,如果你原来的makefile有目标a
,那么你想要做这样的事情:
# mysetenv.sh
#!/bin/bash
. <script to source>
export FLAG=1
make "[email protected]"
# Makefile
ifeq($(FLAG),0)
export FLAG=1
a:
./mysetenv.sh a
else
a:
.. do it
endif
在shell
和GNU Make
中的一些构造是相同的。
var=1234
text="Some text"
您可以更改您的shell脚本以获取定义。它们都必须是简单的name=value
类型。
即,
[script.sh]
. ./vars.sh
[生成文件]
include vars.sh
然后,外壳脚本和生成文件可以共享相同的信息 '源'。我发现这个问题是因为我正在寻找一个可以在Gnu Make和shell脚本中使用的公共语法清单(我不关心哪个shell)。
编辑:贝壳和明白$ {var}。这意味着你可以连接等 var =“一个字符串” var = $ {var}“第二个字符串”
Err,像上面这样的shell脚本不会在接受的答案中创建**凌乱的细节**。它最终就像一个[tag:kbuild]文件。 –
这适用于我。将env.sh
替换为您想要的文件的名称。它通过在bash中获取文件并在格式化后输出修改后的环境,将其转换为名为makeenv
的文件,然后由该文件生成该文件。
IGNORE := $(shell bash -c "source env.sh; env | sed 's/=/:=/' | sed 's/^/export /' > makeenv")
include makeenv
使用GNU使3.81我可以化妆使用源shell脚本:
rule:
<tab>source source_script.sh && build_files.sh
build_files.sh “变” 由source_script.sh导出的环境变量。
注意,使用:
rule:
<tab>source source_script.sh
<tab>build_files.sh
将无法正常工作。每行都在其自己的子shell中运行。
如果你只需要一些已知的变量导出在生成文件可以是一个选项,这里是我正在使用的一个例子。
$ grep ID /etc/os-release
ID=ubuntu
ID_LIKE=debian
$ cat Makefile
default: help rule/setup/lsb
source?=.
help:
-${MAKE} --version | head -n1
rule/setup/%:
echo ID=${@F}
rule/setup/lsb: /etc/os-release
${source} $< && export ID && ${MAKE} rule/setup/$${ID}
$ make
make --version | head -n1
GNU Make 3.81
. /etc/os-release && export ID && make rule/setup/${ID}
make[1]: Entering directory `/tmp'
echo ID=ubuntu
ID=ubuntu
我对这个解决方案:(假设你有bash
,为[email protected]
语法是不同的tcsh
例如)
有一个脚本sourceThenExec.sh
,因为这样的:
#!/bin/bash
source whatever.sh
[email protected]
然后,在你的makefile中,前言你的目标TS与bash sourceThenExec.sh
,例如:
ExampleTarget:
bash sourceThenExec.sh gcc ExampleTarget.C
你当然可以把像STE=bash sourceThenExec.sh
在你的makefile的顶部和缩短这个:
ExampleTarget:
$(STE) gcc ExampleTarget.C
所有这一切工作,因为sourceThenExec.sh
打开一个子shell,但那么这些命令在相同的子shell中运行。
这种方法的缺点是文件来源于每个目标,这可能是不受欢迎的。
我真的很喜欢Foo Bah的答案,在那里调用脚本,脚本回调。为了扩大对这个问题的答案我这样做:
# Makefile
.DEFAULT_GOAL := all
ifndef SOME_DIR
%:
<tab>. ./setenv.sh $(MAKE) [email protected]
else
all:
<tab>...
clean:
<tab>...
endif
-
# setenv.sh
export SOME_DIR=$PWD/path/to/some/dir
if [ -n "$1" ]; then
# The first argument is set, call back into make.
$1 $2
fi
这在任何情况下使用$(MAKE)的优势是采用了独特的化妆程序,也将处理在命令行中指定的任何规则,而不必在SOME_DIR未定义的情况下复制每个规则的名称。
另一种可能的方法是创建一个sh脚本,例如run.sh
,获取所需脚本并在脚本中调用make。
#!/bin/sh
source script1
source script2 and so on
make
如果你想要得到的变量进入环境,让他们传递给子进程,那么你可以使用bash的set -a
和set +a
。前者的意思是,“当我设置一个变量时,也设置相应的环境变量。”因此,这对我的作品:
check:
bash -c "set -a && source .env.test && set +a && cargo test"
这将上cargo test
在.env.test
通过一切为环境变量。
请注意,这会让你将一个环境传递给子命令,但它不会让你设置Makefile变量(这是不同的东西)。如果你需要后者,你应该尝试其中一个建议。
Makefile默认shell是/bin/sh
,它不执行source
。
更改外壳/bin/bash
能够:
# Makefile
SHELL := /bin/bash
rule:
source env.sh && YourCommand
target: output_source
bash ShellScript_name.sh
试试这个它会工作,脚本是当前目录内。
听起来像你真正想要的是编写一个脚本,其源代码设置envvars然后运行make,而不是让源脚本本身... –