web-dev-qa-db-ja.com

Makefileでスクリプトをソースする方法は?

メイクファイル内から環境変数を設定するスクリプトをソースするより良い方法はありますか?

FLAG ?= 0
ifeq ($(FLAG),0)
export FLAG=1
/bin/myshell -c '<source scripts here> ; $(MAKE) $@'
else
...targets...
endif
67
brooksbp

質問に答えるには:できません

基本的な問題は、子プロセスが親の環境を変更できないことです。シェルは、source 'ingのときに新しいプロセスをフォークしないで、これを回避しますが、現在のインカネーションでこれらのコマンドを実行するだけです。シェル。これは正常に機能しますが、make/bin/sh(またはスクリプトのシェル)ではなく、その言語を理解していません(共通する部分は別として)。

Chris DoddとFoo Bahは考えられる回避策の1つに取り組んでいるので、別の方法を提案します(GNU make)を実行している場合:Shellスクリプトを後処理して互換性のあるテキストを作成し、結果を含めます:

Shell-variable-setter.make: Shell-varaible-setter.sh
    postprocess.py @^

# ...
else
include Shell-variable-setter.make
endif

演習として残された厄介な詳細。

41
dmckee

Makefileのデフォルトのシェルは、sourceを実装しない/bin/shです。

シェルを/bin/bashに変更すると、次のことが可能になります。

# Makefile

Shell := /bin/bash

rule:
    source env.sh && YourCommand
63
PureW

単にMakeの環境変数を設定することが目的であれば、Makefile構文でそれを維持し、includeコマンドを使用してみませんか?

include other_makefile

シェルスクリプトを呼び出す必要がある場合は、Shellコマンドで結果をキャプチャします。

JUST_DO_IT=$(Shell source_script)

shellコマンドは、ターゲットの前に実行する必要があります。ただし、これは環境変数を設定しません。

ビルドで環境変数を設定する場合は、環境変数を取得してmakeを呼び出す別のシェルスクリプトを記述します。次に、メイクファイルで、ターゲットが新しいシェルスクリプトを呼び出すようにします。

たとえば、元のmakefileにターゲットaがある場合、次のようなことを行います。

# mysetenv.sh
#!/bin/bash
. <script to source>
export FLAG=1
make "$@" 

# Makefile
ifeq($(FLAG),0)
export FLAG=1
a: 
    ./mysetenv.sh a
else
a:
    .. do it
endif
21
Foo Bah

GNU Make 3.81を使用すると、makeからシェルスクリプトを取得できます。

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

動作しないでしょう。各行は、独自のサブシェルで実行されます。

17
Samuel

これは私のために動作します。代替env.shソースを取得するファイルの名前。これは、bashでファイルをソーシングし、それをフォーマットした後、変更された環境をmakeenvと呼ばれるファイルに出力することで機能します。

IGNORE := $(Shell bash -c "source env.sh; env | sed 's/=/:=/' | sed 's/^/export /' > makeenv")                         
include makeenv   
10
gdw2

いくつかの構造は、ShellGNU Makeで同じです。

var=1234
text="Some text"

シェルスクリプトを変更して、定義を取得できます。それらはすべて単純なname=value型でなければなりません。

すなわち、

[script.sh]

. ./vars.sh

[メイクファイル]

include vars.sh

その後、シェルスクリプトとMakefileは同じ「ソース」の情報を共有できます。この質問を見つけたのは、Gnu MakeおよびShellスクリプトで使用できる一般的な構文のマニフェストを探していたからです(どのShellでも構いません)。

編集:シェルと理解$ {var}。これは、var = "One string" var = $ {var} "Second string"などを連結できることを意味します

5
artless noise

Makeがスクリプトを呼び出し、スクリプトがmakeをコールバックするFoo Bahの答えが本当に好きです。その答えを拡張するために、私はこれをしました:

# Makefile
.DEFAULT_GOAL := all 

ifndef SOME_DIR

%:
<tab>. ./setenv.sh $(MAKE) $@

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プログラムを使用している場合に$(MAKE)を使用するという利点があり、SOME_DIRが定義されていない場合に各ルールの名前を複製することなく、コマンドラインで指定されたルールも処理します。

3
Samuel

これに対する私の解決策:(bash$@は、たとえばtcshでは異なります)

スクリプトを持っているsourceThenExec.sh、 など:

#!/bin/bash
source whatever.sh
$@

次に、メイクファイルで、ターゲットの前にbash sourceThenExec.sh、 例えば:

ExampleTarget:
    bash sourceThenExec.sh gcc ExampleTarget.C

もちろん、STE=bash sourceThenExec.shメイクファイルの先頭で、これを短くします。

ExampleTarget:
    $(STE) gcc ExampleTarget.C

これはすべて、sourceThenExec.shはサブシェルを開きますが、コマンドは同じサブシェルで実行されます。

この方法の欠点は、ファイルがターゲットごとに取得されることです。これは望ましくない場合があります。

1
Chris

変数をenvironmentに取得して、子プロセスに渡す場合は、bashのset -aおよびset +aを使用できます。前者は、「変数を設定するときに、対応する環境変数も設定する」という意味です。だからこれは私のために働く:

check:
    bash -c "set -a && source .env.test && set +a && cargo test"

これは.env.testのすべてをcargo testに環境変数として渡します。

これにより、環境をサブコマンドに渡すことができますが、Makefile変数を設定することはできません(とにかく異なるものです)。後者が必要な場合は、ここで他の提案のいずれかを試してください。

1

別の可能な方法は、shスクリプトを作成することです。たとえば、run.sh、必要なスクリプトを入手し、スクリプト内でmakeを呼び出します。

#!/bin/sh
source script1
source script2 and so on

make 
1
Veera

使用しているMakeおよびシェルのバージョンに応じて、evalcat、および&&を使用した呼び出しのチェーンを介してNiceソリューションを実装できます。

ENVFILE=envfile

source-via-eval:
  @echo "FOO: $${FOO}"
  @echo "FOO=AMAZING!" > $(ENVFILE)
  @eval `cat $(ENVFILE)` && echo "FOO: $${FOO}"

そして簡単なテスト:

> make source-via-eval
FOO:
FOO: AMAZING!
0
tankthinks

Makefileでエクスポートする既知の変数をいくつかしか必要としない場合は、ここで私が使用しているものの例を示します。

$ 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

- http://rzr.online.fr/q/gnumake

0
RzR