목표를 두 단어로 설정하세요

목표를 두 단어로 설정하세요

Makefile을 사용하여 컴파일하고 있습니다.깨끗한암호. 내 Clean 파일은 다음 형식의 파일 이름을 *.icl가지며 .icl.

$(EXE): % : %.icl | copy
    $(CLM) $(CLM_LIBS) $(CLM_INC) $(CLM_OPTS) $@ -o $@

이제 바이너리를 실행할 수 있는 규칙을 추가하고 싶습니다. 요즘은 자주 해요

make some_module && ./some_module

위의 규칙에 따라 모듈을 실행하는 make 대상을 원합니다. 하지만 모듈 이름 자체가 이미 별도의 컴파일 대상이므로 그대로 유지하고 싶습니다. 내가 원하는 것은 호출할 수 make run some_module있고 위의 규칙에 따라 실행할 수 있는 두 단어가 있는 대상입니다 ./some_module.

여러 단어가 포함된 타겟을 생성할 수 있나요?

나는 다음과 같은 규칙을 만들려고 했습니다(지금은 여전히 ​​종속성이 없습니다).

run $(EXE):
    ./$@

실행하면 make run some_module많은 레시피가 "덮어쓰기" 및 "무시"되어 궁극적으로 ./run존재하지 않게 됩니다.

Makefile:24: warning: overriding recipe for target 'tut7_2_2'
Makefile:21: warning: ignoring old recipe for target 'tut7_2_2'
Makefile:24: warning: overriding recipe for target 'support_check'
Makefile:21: warning: ignoring old recipe for target 'support_check'
[...]
Makefile:24: warning: overriding recipe for target 'drawingframe'
Makefile:21: warning: ignoring old recipe for target 'drawingframe'
./run
/bin/bash: ./run: No such file or directory
Makefile:24: recipe for target 'run' failed
make: *** [run] Error 127

답변1

당신은 사용할 수 있습니다$(MAKECMD 대상)run명령줄에 지정된 다른 대상 중에서 마지막으로 강제 실행합니다. 아래 예는 Clean을 모르기 때문에 C로 작성되었습니다.

EXE = a b c

%: %.c
    $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

all: $(EXE)

clean:
    rm -f $(EXE)

run: $(filter-out run, $(MAKECMDGOALS))
    @for i in $^; do ./$$i; done

.PHONY: all clean run

make run program항상 불필요한 출력을 생성하므로 약간 어색해 보일 수 있습니다 program is up to date.

$ cat a.c
#include <stdio.h>
int main(int argc, char **argv) { printf("This is %s\n", argv[0]); return 0; }
$ cp a.c b.c
$ cp a.c c.c

$ make run a b
cc  -o a a.c
cc  -o b b.c
This is ./a
This is ./b
make: 'a' is up to date.
make: 'b' is up to date.

make program run그러한 출력이 없으면 영어처럼 더 자연스러울 수도 있습니다.

$ make c run
cc  -o c c.c
This is ./c

답변2

당신은 할 수조사하다MAKECMDGOALS다른 목표를 설정하는 동안 하나의 목표의 존재를 감지합니다. %: %.icl실행이 target 의 존재를 감지 하도록 하거나 run, runtarget 이라고 불리는 실행 파일을 target 확인하도록 하십시오. 여러 실행 파일을 대상으로 전달하는 경우 첫 번째 방법을 사용하면 각 파일이 빌드 직후에 실행되고, 두 번째 방법을 사용하면 모든 실행이 마지막에 실행됩니다.

이 접근 방식의 단점은 다른 기능과 잘 확장되지 않는다는 것입니다. 예를 들어 여러 실행 파일이 있는 대상을 종속성으로 정의하면 run대상이 있는 메서드가 작동하지 않습니다.

EXE = foo bar experimental
released: foo bar
run: $(filter $(EXE), $(MAKECMDGOALS))
        set -e; for x in $^; do ./$x; done

여기서는 make released run아무것도 실행되지 않습니다 .

이런 상황에서 내가 일반적으로 하는 일은 각 실행 파일에 대한 "실행" 대상을 정의하는 것입니다. 이를 통해 각 목표를 단일 단어로 표현할 수 있다는 점이 큰 장점입니다. 간단하고 다른 기능을 손상시키지 않습니다.

$(EXE): %.run: %
        ./$(@:.run=)
all.run: $(EXE:=.run)

make {foo,bar}.runfoo그런 다음 빌드 하고 테스트하고 싶 bar거나 make all.run빌드하고 실행하려면 실행합니다.

관련 정보