답변:
원하는 것을 정확하게 수행하는 방법을 모르지만 해결 방법은 다음과 같습니다.
run: ./prog
./prog $(ARGS)
그때:
make ARGS="asdf" run
# or
make run ARGS="asdf"
$(foo)' or
$ {foo} '는 유효한 참조입니다. 변수 'foo'. " $ () 만 사용되는 예제를 제공합니다. 아 잘
이 질문은 거의 3 살이지만 어쨌든 ...
GNU make를 사용한다면 쉽게 할 수 있습니다. 유일한 문제는 make
명령 행에서 비 옵션 인수를 대상으로 해석 한다는 것입니다. 해결책은 그것들을 아무것도하지 않는 목표로 바꾸는 것이므로 make
불평하지 않을 것입니다.
# If the first argument is "run"...
ifeq (run,$(firstword $(MAKECMDGOALS)))
# use the rest as arguments for "run"
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
# ...and turn them into do-nothing targets
$(eval $(RUN_ARGS):;@:)
endif
prog: # ...
# ...
.PHONY: run
run : prog
@echo prog $(RUN_ARGS)
이것을 실행하면 다음이 제공됩니다.
$ make run foo bar baz
prog foo bar baz
prog foo bar --baz
make
으로 해석하지 말아야합니다 . 수단 "이 후 모든 인수가 아닌 옵션입니다." --baz
make -- prog foo bar --baz
--
RUN_ARGS
이것을 사용하기 위해 기본값을 어떻게 정의 합니까?
else
지점을 추가하고 거기에 ifeq
설정할 RUN_ARGS
수 있습니까?
$(eval $(RUN_ARGS):dummy;@:)
더미 대상이 정의되지 않은 상태 에서 'eval'행을로 대체하십시오 .
아래와 같이 변수를 Makefile에 전달할 수 있습니다.
run:
@echo ./prog $$FOO
용법:
$ make run FOO="the dog kicked the cat"
./prog the dog kicked the cat
또는:
$ FOO="the dog kicked the cat" make run
./prog the dog kicked the cat
또는 베타에서 제공하는 솔루션을 사용하십시오 .
run:
@echo ./prog $(filter-out $@,$(MAKECMDGOALS))
%:
@:
용법:
$ make run the dog kicked the cat
./prog the dog kicked the cat
TL; DR은이 작업을 시도하지 않습니다
$ make run arg
대신 스크립트를 작성하십시오.
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
그리고 이것을하십시오 :
$ ./buildandrunprog.sh arg
명시된 질문에 대한 답변 :
레시피에서 변수를 사용할 수 있습니다
run: prog
./prog $(var)
그런 다음 변수 할당을 인수로 전달하여
$ make run var=arg
이것은 실행될 것이다 ./prog arg
됩니다.
함정에주의하십시오. 이 방법과 다른 방법의 함정에 대해 자세히 설명하겠습니다.
질문 뒤에 의도 된 의도에 대한 답변 :
가정 : 당신은 실행하고 싶어 prog
일부 인수 하고 싶지만 필요한 경우 실행하기 전에 다시 작성해야합니다.
대답 : 필요한 경우 다시 작성하고 args로 prog를 실행하는 스크립트를 작성하십시오.
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
이 스크립트는 의도를 매우 명확하게합니다. 그것은 make를 사용하여 좋은 일을합니다 : 건물. 셸 스크립트를 사용하여 일괄 처리에 적합한 작업을 수행합니다.
또한 makefile의 모든 경고없이 쉘 스크립트의 전체 유연성과 표현력으로 필요한 다른 작업을 수행 할 수 있습니다.
또한 호출 구문은 실제로 동일합니다.
$ ./buildandrunprog.sh foo "bar baz"
다음과 비교하십시오 :
$ ./prog foo "bar baz"
대조하다
$ make run var="foo bar\ baz"
배경:
make는 인수를 대상에 전달하도록 설계되지 않았습니다. 명령 행의 모든 인수는 목표 (일명 대상), 옵션 또는 변수 지정으로 해석됩니다.
따라서 이것을 실행하면 :
$ make run foo --wat var=arg
make는 그들의 레시피에 따라 업데이트 할 목표 (목표)로 해석 run
하고 해석 foo
합니다. --wat
make 옵션으로. 그리고 var=arg
변수 할당으로.
자세한 내용은 https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals를 참조하십시오.
용어는 https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction을 참조하십시오.
변수 할당 방법에 대해 그리고 내가 그것을 추천하는 이유
$ make run var=arg
레시피의 변수
run: prog
./prog $(var)
이것은 레시피에 인수를 전달하는 가장 "올 바르고"직접적인 방법입니다. 그러나 인수로 프로그램을 실행하는 데 사용할 수는 있지만 그런 식으로 사용되도록 설계되지는 않았습니다. 참조 https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding를
내 의견으로는 이것은 하나의 큰 단점이 있습니다 : 당신이하고 싶은 것은 prog
argument 으로 실행 하는 것 arg
입니다. 그러나 쓰는 대신 :
$ ./prog arg
글 쓰고 있구나:
$ make run var=arg
공백을 포함하는 여러 인수 또는 인수를 전달하려고하면 훨씬 더 어색합니다.
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
다음과 비교하십시오 :
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
기록을 위해 이것은 prog
다음과 같습니다.
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
또한 $(var)
makefile에 따옴표를 넣지 않아야합니다 .
run: prog
./prog "$(var)"
그런 다음 prog
항상 하나의 인수 만 얻습니다.
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
이 모든 것이 내가이 경로에 대해 추천하는 이유입니다.
완성도를 높이기 위해 "실행할 인수를 전달하는"다른 방법이 있습니다.
방법 1 :
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
매우 간단한 설명 : 목표 목록에서 현재 목표를 걸러냅니다. %
다른 목표를 조용히 무시하지 않는 모든 대상 ( )을 잡으십시오 .
방법 2 :
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
슈퍼 간단한 설명 : 대상이 run
첫 번째 목표를 제거하고을 사용하여 나머지 목표에 대한 대상을 만들지 않는 경우 eval
.
둘 다 이런 식으로 쓸 수 있습니다
$ make run arg1 arg2
더 자세한 설명은 make 매뉴얼을 참고 하십시오 : https://www.gnu.org/software/make/manual/html_node/index.html
방법 1의 문제점 :
대시로 시작하는 인수는 make로 해석되며 목표로 전달되지 않습니다.
$ make run --foo --bar
해결 방법
$ make run -- --foo --bar
등호가있는 인수는 make로 해석되며 전달되지 않습니다.
$ make run foo=bar
해결 방법 없음
공백이있는 인수는 어색합니다
$ make run foo "bar\ baz"
해결 방법 없음
인수가 run
(대상과 같음) 발생하면 제거됩니다
$ make run foo bar run
./prog foo bar
대신에 실행 됩니다./prog foo bar run
방법 2로 가능한 해결 방법
인수가 정당한 대상이면 실행됩니다.
$ make run foo bar clean
./prog foo bar clean
대상의 레시피도 실행됩니다 clean
(존재한다고 가정).
방법 2로 가능한 해결 방법
합법적 인 대상을 잘못 입력하면 모든 대상을 잡기 때문에 자동으로 무시됩니다.
$ make celan
그냥 조용히 무시할 것이다 celan
합니다.
해결 방법은 모든 것을 장황하게 만드는 것입니다. 무슨 일이 일어나는지 알 수 있습니다. 그러나 이는 합법적 인 출력에 많은 노이즈를 발생시킵니다.
방법 2의 문제 :
인수가 기존 대상과 이름이 같은 경우 make는 덮어 쓰고 있다는 경고를 인쇄합니다.
내가 아는 해결 방법이 없습니다.
등호가있는 인수는 여전히 make로 해석되며 전달되지 않습니다.
해결 방법 없음
공백이있는 인수는 여전히 어색합니다
해결 방법 없음
공백이있는 인수 eval
을 만들려는 대상을 수행하지 않습니다.
해결 방법 : 위와 같이 아무 것도 수행하지 않는 전역 캐치 모든 대상을 작성하십시오. 위와 같은 문제로 잘못 입력 된 합법적 인 목표를 다시 자동으로 무시합니다.
eval
런타임에 makefile을 수정하는 데 사용 됩니다. 가독성과 디버깅 가능성, 그리고 놀랍게도 적은 원리로 얼마나 더 나빠질 수 있습니까? ?
해결 방법 :이 작업을 수행하지 마십시오 !! 1 대신 make를 실행 한 다음 실행하는 쉘 스크립트를 작성하십시오 prog
.
나는 gnu make 만 사용하여 테스트했습니다. 다른 제조사들은 다른 행동을 할 수 있습니다.
TL; DR은이 작업을 시도하지 않습니다
$ make run arg
대신 스크립트를 작성하십시오.
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
그리고 이것을하십시오 :
$ ./buildandrunprog.sh arg
다음은 이러한 사용 사례 중 일부에 도움이되는 다른 솔루션입니다.
test-%:
$(PYTHON) run-tests.py $@
즉, 접두사 ( test-
이 경우)를 선택한 다음 대상 이름을 프로그램 / 러너로 직접 전달하십시오. 대상 이름을 기본 프로그램에 유용한 것으로 풀 수있는 러너 스크립트가있는 경우 이것이 대부분 유용하다고 생각합니다.
$*
를) 일치하는 대상의 일부만 전달 하는 데 사용할 수도 있습니다 %
.
명령 행에서 각 n 번째 인수를 명시 적으로 추출 할 수 있습니다. 이를 위해 변수 MAKECMDGOALS를 사용할 수 있으며 'make'에 제공된 명령 행 인수 목록을 보유하며 이는 대상 목록으로 해석됩니다. n 번째 인수를 추출하려면 "word"함수와 함께 해당 변수를 사용할 수 있습니다. 예를 들어 두 번째 인수를 원하는 경우 다음과 같이 변수에 변수를 저장할 수 있습니다.
second_argument := $(word 2, $(MAKECMDGOALS) )
make: *** No rule to make target 'arg'. Stop.
여기 내 예가 있습니다. Dev-Cpp와 함께 제공되는 mingw32-make.exe를 사용하여 Windows 7에서 작성하고 있습니다. (c : \ Windows \ System32 \ make.bat가 있으므로 명령은 여전히 "make"입니다.)
clean:
$(RM) $(OBJ) $(BIN)
@echo off
if "${backup}" NEQ "" ( mkdir ${backup} 2> nul && copy * ${backup} )
정기적 인 청소 사용법 :
make clean
mydir /에서 백업 정리 및 백업 사용법 :
make clean backup=mydir
이것을 자랑스럽게 생각하지는 않지만 환경 변수를 전달하고 싶지 않아 미리 준비된 명령을 실행하는 방법을 뒤집 었습니다.
run:
@echo command-you-want
실행하려는 명령이 인쇄되므로 서브 쉘에서 평가하십시오.
$(make run) args to my command
등호 (=)로 인수를 얻는 방법을 찾았습니다! 대답은 특히 @lesmana의 답변에 추가 된 것입니다. (여기에서 가장 완전하고 설명되어 있기 때문에) 주석으로 작성하기에는 너무 큽니다. 다시, 나는 그의 메시지를 반복합니다 : TL; DR이 작업을 시도하지 마십시오!
내 주장을 다룰 수있는 방법이 필요했습니다 --xyz-enabled=false
(기본값은 true이므로). 이것은 make 대상이 아니므로의 일부가 아니라는 것을 모두 알고 $(MAKECMDGOALS)
있습니다.
에코를 통해 make의 모든 변수를 살펴보면서 $(.VARIABLES)
다음과 같은 흥미로운 결과를 얻었습니다.
[...] -*-command-variables-*- --xyz-enabled [...]
이를 통해 두 가지 방법으로 갈 수 있습니다. 모든 것이 --
(귀하의 경우에 해당되는 경우) 시작하거나 GNU에서 특정 변수 ( 사용하지 않을 수도 있음 )를 살펴보십시오 -*-command-variables-*-
. ** 추가 옵션은 바닥 글을 참조하십시오. ** 제 경우에는이 변수가 다음과 같습니다.
--xyz-enabled=false
이 변수를 사용 $(MAKECMDGOALS)
하여 다음을 정의하여 기존 솔루션과 결합 할 수 있습니다 .
# the other technique to invalidate other targets is still required, see linked post
run:
@echo ./prog $(-*-command-variables-*-) $(filter-out $@,$(MAKECMDGOALS))`
그리고 그것을 다음과 함께 사용 (명확하게 인수 순서를 섞음) :
make run -- config --xyz-enabled=false over=9000 --foo=bar show isit=alwaysreversed? --help
반환 :
./prog isit=alwaysreversed? --foo=bar over=9000 --xyz-enabled=false config show --help
보시다시피, 우리는 인수의 총 순서를 느슨하게합니다. "할당"인수가있는 부분이 반전 된 것처럼 보이고 "대상"인수의 순서가 유지됩니다. 처음에 "할당"-args를 배치 했으므로 프로그램이 인수 위치를 신경 쓰지 않기를 바랍니다.
업데이트 : 다음은 변수를 유망하게 보이게합니다.
MAKEFLAGS = -- isit=alwaysreverse? --foo=bar over=9000 --xyz-enabled=false
MAKEOVERRIDES = isit=alwaysreverse? --foo=bar over=9000 --xyz-enabled=false