有沒有更好的方法來從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,而不是讓源腳本本身... –