Programming

명령 출력을 Makefile 변수에 지정하는 방법

procodes 2020. 5. 14. 21:26
반응형

명령 출력을 Makefile 변수에 지정하는 방법


설치된 Python이 특정 버전 (예 : 2.5)보다 큰 경우에만 일부 make 규칙을 조건부로 실행해야합니다.

나는 실행과 같은 것을 할 수 있다고 생각했다.

python -c 'import sys; print int(sys.version_info >= (2,5))'

그런 다음 ifeqmake 문 에서 출력 (확인 인 경우 '1', 그렇지 않으면 '0')을 사용합니다.

간단한 bash 쉘 스크립트에서는 다음과 같습니다.

MY_VAR=`python -c 'import sys; print int(sys.version_info >= (2,5))'`

그러나 그것은 Makefile에서 작동하지 않습니다.

어떤 제안? 나는 이것을 달성하기 위해 다른 합리적인 해결 방법을 사용할 수 있습니다.


다음 shell과 같이 Make 내장을 사용하십시오.MY_VAR=$(shell echo whatever)

me@Zack:~$make
MY_VAR IS whatever

me@Zack:~$ cat Makefile 
MY_VAR := $(shell echo whatever)

all:
    @echo MY_VAR IS $(MY_VAR)

과제를 포장하는 eval것이 나를 위해 일하고 있습니다.

# dependency on .PHONY prevents Make from 
# thinking there's `nothing to be done`
set_opts: .PHONY
  $(eval DOCKER_OPTS = -v $(shell mktemp -d -p /scratch):/output)

문제를 해결하는 실제 구문에 대한 가시성을 높이는 답변을 작성 중입니다. 불행히도, 누군가가 사소한 것으로 볼 수있는 것은 합리적인 질문에 대한 간단한 답변을 찾는 사람에게 매우 심각한 두통이 될 수 있습니다.

다음을 "Makefile"파일에 넣으십시오.

MY_VAR := $(shell python -c 'import sys; print int(sys.version_info >= (2,5))')

all:
    @echo MY_VAR IS $(MY_VAR)

보고 싶은 동작은 다음과 같습니다 (최근에 파이썬이 설치되어 있다고 가정).

make
MY_VAR IS 1

위의 텍스트를 복사하여 Makefile에 붙여 넣으면 얻을 수 있습니까? 아마 아닙니다. 여기에보고 된 것과 같은 오류가 발생합니다.

makefile : 4 : *** 구분 기호가 없습니다. 중지

이유 : 개인적으로 정품 탭을 사용했지만 스택 오버플로 (도움이 되려고 시도)는 탭을 여러 공백으로 변환합니다. 좌절 한 인터넷 시민 여러분, 이제 제가 사용한 것과 같은 텍스트를 가지고 있다고 생각하여 이것을 복사하십시오. make 명령은 이제 공백을 읽고 "all"명령의 형식이 잘못되었음을 발견합니다. 따라서 위의 텍스트를 복사하여 붙여 넣은 다음 "@echo"앞의 공백을 탭으로 변환하면이 예제가 도움이 될 것입니다.


다음은 레시피 내부에 배관 및 변수 할당을 사용하는 좀 더 복잡한 예입니다.

getpodname:
    # Getting pod name
    @eval $$(minikube docker-env) ;\
    $(eval PODNAME=$(shell sh -c "kubectl get pods | grep profile-posts-api | grep Running" | awk '{print $$1}'))
    echo $(PODNAME)

이와 같은 요리법을 조심하십시오

target:
    MY_ID=$(GENERATE_ID);
    echo $MY_ID;

두 가지가 잘못되었습니다. 레시피의 첫 번째 라인은 두 번째 라인과 별도의 쉘 인스턴스에서 실행됩니다. 그 동안 변수가 손실됩니다. 두 번째로 잘못된 것은 $이스케이프되지 않는다는 것입니다.

target:
    MY_ID=$(GENERATE_ID); \
    echo $$MY_ID;

Both problems have been fixed and the variable is useable. The backslash combines both lines to run in one single shell, hence the setting of the variable and the reading of the variable afterwords, works.

I realize the original post said how to get the results of a shell command into a MAKE variable, and this answer shows how to get it into a shell variable. But other readers may benefit.

One final improvement, if the consumer expects an "environment variable" to be set, then you have to export it.

my_shell_script
    echo $MY_ID

would need this in the makefile

target:
    export MY_ID=$(GENERATE_ID); \
    ./my_shell_script;

Hope that helps someone. In general, one should avoid doing any real work outside of recipes, because if someone use the makefile with '--dry-run' option, to only SEE what it will do, it won't have any undesirable side effects. Every $(shell) call is evaluated at compile time and some real work could accidentally be done. Better to leave the real work, like generating ids, to the inside of the recipes when possible.


With GNU Make, you can use shell and eval to store, run, and assign output from arbitrary command line invocations. The difference between the example below and those which use := is the := assignment happens once (when it is encountered) and for all. Recursively expanded variables set with = are a bit more "lazy"; references to other variables remain until the variable itself is referenced, and the subsequent recursive expansion takes place each time the variable is referenced, which is desirable for making "consistent, callable, snippets". See the manual on setting variables for more info.

# Generate a random number.
# This is not run initially.
GENERATE_ID = $(shell od -vAn -N2 -tu2 < /dev/urandom)

# Generate a random number, and assign it to MY_ID
# This is not run initially.
SET_ID = $(eval MY_ID=$(GENERATE_ID))

# You can use .PHONY to tell make that we aren't building a target output file
.PHONY: mytarget
mytarget:
# This is empty when we begin
    @echo $(MY_ID)
# This recursively expands SET_ID, which calls the shell command and sets MY_ID
    $(SET_ID)
# This will now be a random number
    @echo $(MY_ID)
# Recursively expand SET_ID again, which calls the shell command (again) and sets MY_ID (again)
    $(SET_ID)
# This will now be a different random number
    @echo $(MY_ID)

참고URL : https://stackoverflow.com/questions/2019989/how-to-assign-the-output-of-a-command-to-a-makefile-variable

반응형