2010-01-03 5 views
3

메이크 파일에서 define 지시문을 사용하여 변수를 정의합니다. 이 변수에는 실행하고자하는 명령의 구성 가능한 목록이 있습니다.메이크 파일 정의 : 재귀 확장 질문

이 변수는 파일 목록 (예 : .foo 개 파일)을 가져오고 싶습니다. 이 파일은 makefile 실행 중에 작성됩니다. 예를 들어 makefile :

MY_VAR = $(wildcard *.foo) 
define MY_VAR2 
    echo $(1) $(MY_VAR) 
endef 

foo: create_files 
    $(call MY_VAR2, ls) 
    rm -f *.foo 

create_files: 
    touch foo.foo 
    touch bar.foo 

원하는 결과가 표시되지 않습니다. 선언시에 MY_VAR2이 평가되는 것 같습니다.

원하는 동작을 얻는 방법이 있습니까?


편집 : sateesh 올바르게 지적

$(shell) 명령은, 위의 예를 들어 작동합니다. 그러나 아래 예제에서는 작동하지 않습니다. 이 예제의 가장 큰 차이점은 새 파일이 MY_VAR2 안에 생성된다는 것입니다.

MY_VAR = $(wildcard *.foo) 
TEST_VAR = $(shell ls *.foo) 

define MY_VAR2 
    @touch foo.foo 
    @touch bar.foo 
    @echo "MY_VAR" $(1) $(MY_VAR) 
    @echo "TEST_VAR" $(1) $(TEST_VAR) 
endef 

foo: 
    $(call MY_VAR2, ls) 
    @rm -f *.foo 

나는 규칙을 추가하여이를 해결할 수 있습니다. 더 간단한 방법이 있습니까?

답변

2

나는 당신이 make에서 쉘 스크립트를 작성하려고 애쓰는 것처럼 보입니다.

셸 스크립트를 작성하는 경우 셸 스크립트를 작성하십시오. 순서대로 명령을 실행하면 각 행을 실행할 때 어떤 파일이 있는지 알 수 있습니다. 당신이 메이크업의 사용을 다음 규칙 및 종속성을 갖고 싶어

다른 측면에서
touch foo.foo 
touch bar.foo 
your-command `ls *.foo` 

, 당신은 당신이 생각의 메이크업의 길을 갈 경우 정의 사용할 필요가 없습니다.

foo: create_files 
    your-command $(wildcard *.foo) 
    rm -f *.foo 

create_files: 
    touch foo.foo 
    touch bar.foo 
+0

나는 아주 잘 만들지도 모른다. 나는 내가하고 싶은 것을 설명하려고 노력할 것이다. 일부 규칙을 해결하기 전후에 몇 가지 작업을 수행하려고합니다. 두 번째 예제에서, 세 번째 (그리고 네 번째 ...) 규칙을 해석 할 때'foo'의 *** body ***을 실행하고 싶습니다. 제 생각에'define'은 꽤 많은 함수 선언입니다. 나는 그것에 대해 생각할 것이다. 어쩌면 쉘 스크립트가 가장 좋은 경로일지도 모르지만 그 상황은 좀 더 복잡 할 것입니다. –

0

필터 명령을 사용해 주시겠습니까? 예 : here을 찾을 수 있습니다.

1

4.4.3 기능 와일드 카드

와일드 카드 확장은 규칙에 자동으로 발생합니다. 그러나 와일드 카드 확장은 일반적으로 변수가 설정되거나 함수의 인수 내에서 수행되지 않습니다. 해당 위치에서 와일드 카드 확장을 수행하려면 와일드 카드 기능을 사용해야합니다.

eval 함수를 사용하여 멀리 떨어져있을 수도 있습니다.

이러한 생성 된 파일은 종속성 그래프가 올바르도록 다른 규칙의 종속성이어야합니다.

참고 :

+0

나는 몰랐다는했고'eval' 기능을 확인하십시오. 잘 알고 있습니다. 나는 그것 (그리고 rtfm)과 함께 놀 것이다. –

+0

사실 @sateesh처럼'$ (shell) '을 지적 할 수는 있었지만 어쨌든 당신의 예제가 정말로 당신이하고 싶은 것을 확신 할 수 없었습니다. (그냥 가짜 예제라고 생각했습니다). 일반적으로, 동적 makefile 구조는'$ (eval) '을 통해 이루어집니다. –

+0

예, 그것은 가짜 예제입니다. 나는 여전히'$ (shell)'이 내 목적에 부합하지 않을 것이라고 100 % 확신하지 못한다. –

2

난 당신이 GNU 확인 여기에 사용하고 있는지 여기 추정하고있다. GNU Make와 함께 제공되는 "쉘"내장 함수를 사용하여 원하는 결과를 얻을 수 있다고 생각합니다.
다음은

는 결과를 얻을 수있는 방법을 보여줍니다 메이크업 파일 조각입니다 :

MY_VAR = $(wildcard *.foo) 
TEST_VAR = $(shell ls *.foo) 

define MY_VAR2 
    @echo "MY_VAR" $(1) $(MY_VAR) 
    @echo "TEST_VAR" $(1) $(TEST_VAR) 
endef 

foo: create_files 
    $(call MY_VAR2, ls) 
    @rm -f *.foo 

create_files: 
    @touch foo.foo 
    @touch bar.foo 

대상 "foo는"에 대한 위 메이크 파일을 실행 한 결과는 다음과 같습니다 그래서

MY_VAR ls 
TEST_VAR ls bar.foo foo.foo 

설명 된대로 함수는 원하는 결과를 얻습니다.

shell 기능이 역 인용 부호 가장 쉘에서 수행 ('' ')와 동일한 기능을 수행합니다 : 그것은 명령 확장을 수행하는 GNU에서

는 문서를 확인하십시오. 즉, 셸 명령을 인수로 사용하고 명령 출력으로 평가됩니다. 유일한 처리는 에서 결과는 으로 각 개행 (또는 캐리지 리턴/개행 쌍)을 단일 공백으로 변환합니다.
...
쉘 함수 호출로 실행되는 명령은 함수 호출이 확장 될 때 실행됩니다. ... files : = $ (쉘 echo .c) 은 확장 파일을 ' .c'로 설정합니다. make가 매우 이상한 쉘을 사용하지 않는 한, '$ (와일드 카드 * .c)'(적어도 하나의 '.c'파일이 존재하는 한)와 동일한 결과를 나타냅니다.

그래서 재귀 적으로 확장 된 변수 (= 양식)를 쉘과 함께 사용한다고 생각하십시오. 함수 은 원하는 결과를 얻을 수 있습니다.

+0

유망 해 보입니다. 내가 맹렬한 말씨를 쓸 때까지 나는 의심을 품고 있었다 :-). 나는 그걸로 놀고있을거야 ... –

0

include를 사용하는 것이 어떻습니까?
요점은 make가 두 번 실행해야한다는 것입니다.
우선, 원하는 것을 만들어야합니다.
그러면 첫 번째 규칙 실행 후 다음에 두 번째 패스에서 생성 된 규칙을 구문 분석하도록합니다.

define MY_VAR2 
    echo $(1) $(MY_VAR) 
    $(1) $(MY_VAR) 
endef 

-include .listoffiles 

foo: create_files 
    $(call MY_VAR2, ls -al) 
    rm -f *.foo .listoffiles 

create_files: .listoffiles 

.listoffiles: 
    touch foo.foo 
    touch bar.foo 
    @echo "MY_VAR = \$$(wildcard *.foo)" > [email protected] 

그냥 원하는대로하는 것 같습니다.
2 회 통과로 평가한다고해서 make를 두 번 입력해야한다는 것은 아닙니다.
자동으로 make가 수행합니다.

% make -f test.mk 
touch foo.foo 
touch bar.foo 
echo ls -al bar.foo foo.foo 
ls -al bar.foo foo.foo 
ls -al bar.foo foo.foo 
-rw-rw-r-- 1 yo-hei clearusers 0 Jan 8 08:44 bar.foo 
-rw-rw-r-- 1 yo-hei clearusers 0 Jan 8 08:44 foo.foo 
rm -f *.foo .listoffiles 
+0

나는 실제로 이런 종류의 기능을 너무 악용한다 (eval을 너무 사용한다!) make 시스템은 빌드 시스템의 핵심 부분에서 최소한의 데이터와 규칙 템플릿으로 즉각적으로 규칙을 생성한다. . gnu make는 이렇게 깨끗하고 빠릅니다. 당신은 파이썬, 루비, ocaml이 필요하지 않습니다 .... 당신은 무료로, 아주 유용한 문자열 조작 방법에 대한 -j 병렬 처리를 얻을 것이지만 gnu에서 약간의 사탕 기능을 가지고 싶습니다. make ... – holmes

0

make가 아닌 쉘에서 확장을 수행하는 것은 어떨까요?

MY_VAR = $$(ls *.foo) 
define MY_VAR2 
    @echo $(1) $(MY_VAR) 
endef 

foo: create_files 
    $(call MY_VAR2, ls) 
    @rm -f *.foo 

create_files: 
    @touch foo.foo 
    @touch bar.foo 

더블 - $는 쉘이 파일 검색 부분을 확장 할 수 있습니다. 나는 이것을 할 수있는보다 우아한 방법에 대한 다른 게시물에 동의하지만 그 선택은 당신을위한 선택입니다. 너무 두 번째 예를 들어

작품 :

MY_VAR = $(wildcard *.foo) 
TEST_VAR = $$(ls *.foo) 

define MY_VAR2 
    @touch foo.foo 
    @touch bar.foo 
    @echo "MY_VAR" $(1) $(MY_VAR) 
    @echo "TEST_VAR" $(1) $(TEST_VAR) 
endef 

foo: 
    $(call MY_VAR2, ls) 
    @rm -f *.foo