program tip

Makefile에서 스크립트를 소싱하는 방법은 무엇입니까?

radiobox 2020. 11. 7. 09:12
반응형

Makefile에서 스크립트를 소싱하는 방법은 무엇입니까?


makefile 내에서 env vars를 설정하는 스크립트를 소싱하는 더 좋은 방법이 있습니까?

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

질문에 답하려면 할 수 없습니다 .

기본적인 문제는 자식 프로세스가 부모의 환경을 변경할 수 없다는 것입니다. 쉘은 'ing' 할 때 새 프로세스를 포크하지 않고source 현재 쉘의 구현에서 해당 명령을 실행함으로써이 문제를 해결합니다. 그것은 잘 작동하지만, make하지 /bin/sh(또는 스크립트입니다 쉘 무엇이든)와 (옆 그들이 공통적으로 가지고있는 비트)에서 해당 언어를 이해하지 못합니다.

Chris Dodd와 Foo Bah가 한 가지 가능한 해결 방법을 다루었으므로 다른 방법을 제안합니다 (GNU make를 실행한다고 가정) : 쉘 스크립트를 사후 처리하여 호환 가능한 텍스트를 만들고 결과를 포함합니다.

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

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

연습으로 남겨진 지저분한 세부 사항.


메이크 기본 쉘은 /bin/sh구현하지 않는다 source.

쉘을 변경 /bin/bash하면 다음이 가능합니다.

# Makefile

SHELL := /bin/bash

rule:
    source env.sh && YourCommand

목표가 단순히 Make에 대한 환경 변수를 설정하는 것이라면 Makefile 구문으로 유지하고 include명령을 사용하지 않는 이유는 무엇입니까?

include other_makefile

쉘 스크립트를 호출해야하는 경우 shell명령 에서 결과를 캡처하십시오 .

JUST_DO_IT=$(shell source_script)

쉘 명령은 대상보다 먼저 실행되어야합니다. 그러나 이것은 환경 변수를 설정하지 않습니다.

빌드에서 환경 변수를 설정하려면 환경 변수를 소싱하고 make를 호출하는 별도의 셸 스크립트를 작성합니다. 그런 다음 makefile에서 대상이 새 셸 스크립트를 호출하도록합니다.

예를 들어, 원본 메이크 파일에 target 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

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

작동하지 않을 것이다. 각 라인은 자체 서브 쉘에서 실행됩니다.


이것은 나를 위해 작동합니다. env.sh소싱하려는 파일의 이름으로 대체 하십시오. bash에서 파일을 소싱하고 수정 된 환경을 형식화 한 후 makeenvmakefile에서 제공하는 라는 파일로 출력하여 작동합니다 .

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

일부 구성은 shell및에서 동일합니다 GNU Make.

var=1234
text="Some text"

정의를 소싱하도록 쉘 스크립트를 변경할 수 있습니다. 모두 단순한 name=value유형 이어야합니다 .

즉,

[script.sh]

. ./vars.sh

[메이크 파일]

include vars.sh

그러면 쉘 스크립트와 Makefile이 동일한 정보 '소스'를 공유 할 수 있습니다. Gnu Make 및 셸 스크립트에서 사용할 수있는 공통 구문의 매니페스트를 찾고 있었기 때문에이 질문을 찾았습니다 (어떤 셸은 상관 없음).

편집 : 쉘 및 이해 $ {var} . 즉, var = "One string"var = $ {var} "Second string"등을 연결할 수 있습니다.


나는 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이 정의되지 않은 경우 각 규칙의 이름을 복제하지 않고도 명령 줄에 지정된 모든 규칙을 처리합니다. .


My solution to this: (assuming you're have bash, the syntax for $@ is different for tcsh for instance)

Have a script sourceThenExec.sh, as such:

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

Then, in your makefile, preface your targets with bash sourceThenExec.sh, for instance:

ExampleTarget:
    bash sourceThenExec.sh gcc ExampleTarget.C

You can of course put something like STE=bash sourceThenExec.sh at the top of your makefile and shorten this:

ExampleTarget:
    $(STE) gcc ExampleTarget.C

All of this works because sourceThenExec.sh opens a subshell, but then the commands are run in the same subshell.

The downside of this method is that the file gets sourced for each target, which may be undesirable.


If you want to get the variables into the environment, so that they are passed to child processes, then you can use bash's set -a and set +a. The former means, "When I set a variable, set the corresponding environment variable too." So this works for me:

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

That will pass everything in .env.test on to cargo test as environment variables.

Note that this will let you pass an environment on to sub-commands, but it won't let you set Makefile variables (which are different things anyway). If you need the latter, you should try one of the other suggestions here.


If you need only a few known variables exporting in makefile can be an option, here is an example of what I am using.

$ 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


Depending on your version of Make and enclosing shell, you can implement a nice solution via eval, cat, and chaining calls with &&:

ENVFILE=envfile

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

And a quick test:

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

Another possible way would be to create a sh script, for example run.sh, source the required scripts and call make inside the script.

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

make 

target: output_source
    bash ShellScript_name.sh

try this it will work, the script is inside the current directory.

참고URL : https://stackoverflow.com/questions/7507810/how-to-source-a-script-in-a-makefile

반응형