규칙 실행시 make 변수 정의


209

GNUmakefile에서 임시 디렉토리를 사용하는 규칙을 갖고 싶습니다. 예를 들면 다음과 같습니다.

out.tar: TMP := $(shell mktemp -d)
        echo hi $(TMP)/hi.txt
        tar -C $(TMP) cf $@ .
        rm -rf $(TMP)

작성된 바와 같이, 위의 규칙은 규칙이 구문 분석 될 때 임시 디렉토리를 작성합니다 . 즉, 내가 out.tar를 만들지 않아도 많은 임시 디렉토리가 만들어집니다. / tmp가 사용되지 않는 임시 디렉토리로 흩어지는 것을 피하고 싶습니다.

변수가 정의 될 때와 달리 규칙이 실행될 때만 변수를 정의 할 수있는 방법이 있습니까?

내 주요 생각은 mktemp와 tar를 쉘 스크립트에 덤프하는 것이지만 다소보기 흉한 것 같습니다.

답변:


322

당신의 예에서 TMP때마다 변수 설정 (임시 디렉토리 생성) 규칙 에 대해 out.tar평가됩니다. out.tar실제로 실행될 때만 디렉토리를 작성하려면 디렉토리 작성을 단계로 아래로 이동해야합니다.

out.tar : 
    $(eval TMP := $(shell mktemp -d))
    @echo hi $(TMP)/hi.txt
    tar -C $(TMP) cf $@ .
    rm -rf $(TMP)

평가 가 수동으로 메이크 파일에 입력 된 것처럼 함수는 문자열을 평가한다. 이 경우 TMP변수를 shell함수 호출 결과로 설정합니다 .

의견에 대한 답변으로 편집 :

고유 한 변수를 만들려면 다음을 수행하십시오.

out.tar : 
    $(eval $@_TMP := $(shell mktemp -d))
    @echo hi $($@_TMP)/hi.txt
    tar -C $($@_TMP) cf $@ .
    rm -rf $($@_TMP)

대상 이름 (이 경우 out.tar)을 변수 앞에 추가하여 name으로 변수를 생성합니다 out.tar_TMP. 바라건대, 그것은 갈등을 예방하기에 충분합니다.


2
몇 가지 설명이 필요합니다 ...이 목표에 TMP가 적용되지 않습니까? 따라서 자체 $ (TMP) 사용법을 가진 다른 규칙이있는 경우 (-j와 병행하여) 충돌이있을 수 있습니까? 또한 @echo가 필요한가요? 그냥 놔둘 수있을 것 같습니다.
Emil Sit

3
트릭을하는 것 같습니다 (평균이 아닌 비전문가에게는 약간 불투명하지만 :-) 감사합니다!
Emil Sit

29
이 솔루션에주의하십시오! 규칙 파일 순서가 아닌$(eval $@_TMP := $(shell mktemp -d)) Makefile을 처음 평가할 때 발생 합니다. 다시 말해, 생각보다 빨리 일어납니다. 이 예제에서는 문제가되지 않지만이 방법을 사용하면 일부 순차적 작업에 문제가 발생할 수 있습니다. $(eval ...)
JamesThomasMoon1979

1
@ JamesThomasMoon1979 당신은 이러한 한계를 극복하는 방법을 알고 있습니까?
Vadim

2
내 자신의 질문에 대답 : 해결 방법은 첫 번째 규칙 실행 중에 파일을 만들고 두 번째 규칙의 첫 번째 단계에서 파일을 평가하려고했습니다.
Vadim Kotov 2016 년

63

비교적 쉬운 방법은 전체 시퀀스를 쉘 스크립트로 작성하는 것입니다.

out.tar:
   set -e ;\
   TMP=$$(mktemp -d) ;\
   echo hi $$TMP/hi.txt ;\
   tar -C $$TMP cf $@ . ;\
   rm -rf $$TMP ;\

https://stackoverflow.com/a/29085684/86967에서 관련 팁을 통합했습니다.


3
이것은 확실히 간단한 따라서 가장 좋은 대답 (피입니다 @eval같은 일을하고). 값이 명령에 올바르게 전달되었지만 출력에 $TMP(예 tar -C $TMP ...:)가 표시됩니다.
Karl Richter

이것이 일반적인 방법입니다. 실제로 아무도 받아 들여지지 않은 사람의 모든 노력을 다하지 않기 때문에 사람들 이이 대답을 보길 바랍니다.
pmos

쉘 특정 명령을 사용하는 경우 어떻게해야합니까? 이 경우 쉘 명령은 make를 호출하는 것과 동일한 쉘 언어 여야합니다. 나는 shebang과 함께 makefile을 보았습니다.
ptitpion

@ptitpion : SHELL := /bin/bashmakefile에서 BASH 관련 기능을 활성화 할 수도 있습니다.
nobar

31

다른 가능성은 규칙이 실행될 때 변수 만들기를 위해 별도의 줄을 사용하는 것입니다.

예를 들어 다음은 두 가지 규칙이있는 makefile입니다. 규칙이 실행되면 임시 디렉토리가 작성되고 TMP가 임시 디렉토리 이름으로 설정됩니다.

PHONY = ruleA ruleB display

all: ruleA

ruleA: TMP = $(shell mktemp -d testruleA_XXXX)
ruleA: display

ruleB: TMP = $(shell mktemp -d testruleB_XXXX)
ruleB: display

display:
    echo ${TMP}

코드를 실행하면 예상되는 결과가 생성됩니다.

$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile  testruleB_Y4Ow

다시 말해, GNU make에는 이 접근 방식을 보완하는 데 필요한 주문 전용 전제 조건에 대한 구문 이 있습니다.
anol

11
이 솔루션에주의하십시오! ruleA: TMP = $(shell mktemp -d testruleA_XXXX)그리고 ruleB: TMP = $(shell mktemp -d testruleB_XXXX)메이크가 먼저 평가 될 때 발생합니다. 다시 말해, ruleA: TMP = $(shell ...생각보다 빨리 일어납니다. 이 특정 경우에는 작동하지만이 방법을 사용하면 일부 순차적 작업에 문제가 발생할 수 있습니다.
JamesThomasMoon1979

1

나는 "하지 마라"라는 답변을 싫어하지만 ... 그렇지 않습니다.

make의 변수는 전역 변수이며 실행 단계가 아니라 makefile의 "구문 분석"단계에서 평가되어야합니다.

이 경우 단일 대상에 대한 로컬 변수 인 경우 @nobar의 답변 을 따라 쉘 변수로 만듭니다.

대상별 변수도 kati , Mozilla pymake 와 같은 다른 make 구현에서는 유해한 것으로 간주됩니다 . 이로 인해 독립형으로 빌드되었는지 또는 대상별 변수가있는 상위 대상의 종속성에 따라 대상을 다르게 빌드 할 수 있습니다. 그리고 이미 구축 된 것을 모르기 때문에 어떤 방식 인지 알 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.