Programing

"만들기"에 대한 인수 전달

lottogame 2020. 3. 6. 08:15
반응형

"만들기"에 대한 인수 전달


나는 Makefiles를 사용합니다.

나는라는 대상이 run빌드 대상을 실행합니다. 단순화하면 다음과 같습니다.

prog: ....
  ...

run: prog
  ./prog

다시 앉아 나는 이것이 독창적이라는 것을 알고 있지만 기립 박수는 필요하지 않습니다.

이제 내 질문은-인수를 전달할 방법이 있습니까? 그래서

make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat

감사!


원하는 것을 정확하게 수행하는 방법을 모르지만 해결 방법은 다음과 같습니다.

run: ./prog
    ./prog ${ARGS}

그때:

make ARGS="asdf" run

이 질문은 거의 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

표준 적으로 다음과 같은 매크로를 정의하여 인수를 전달할 수 있습니다.

make run arg1=asdf

다음과 같이 사용하십시오

run: ./prog $(arg1)
   etc

Microsoft NMake만들기 위한 참고 자료


아래와 같이 변수를 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를 사용하여 좋은 일을합니다 : 건물. 쉘 스크립트를 사용하여 일괄 처리를 위해 유용한 작업을 수행합니다.

또한 호출 구문은 실제로 동일합니다.

$ ./buildandrunprog.sh foo "bar baz"

다음과 비교하십시오 :

$ ./prog foo "bar baz"

또한 makefile의 모든 경고없이 쉘 스크립트의 전체 유연성과 표현력으로 필요한 다른 작업을 수행 할 수 있습니다.


배경:

make는 대상을 실행하고 해당 대상에 인수를 전달하도록 설계되지 않았습니다. 명령 행의 모든 ​​인수는 목표 (일명 대상), 옵션 또는 변수 지정으로 해석됩니다.

따라서 이것을 실행하면 :

$ make run foo bar --wat var=arg

메이크업 해석됩니다 run, foobar갱신에 대한 목표 (목표)로 자신의 조리법에 따라. --watmake 옵션으로. 그리고 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를

내 의견으로는 이것은 하나의 큰 단점이 있습니다 : 당신이하고 싶은 것은 progargument 으로 실행 하는 것 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 매뉴얼을 참고 하십시오 : https://www.gnu.org/software/make/manual/html_node/index.html

방법 1의 문제점 :

  • 대시로 시작하는 인수는 make로 해석되며 목표로 전달되지 않습니다.

    $ make run --foo --bar
    

    해결 방법

    $ make run -- --foo --bar
    
  • 인수가 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 run foo "bar\ baz"
    

    해결 방법 없음

  • 합법적 인 대상을 잘못 입력하면 모든 대상을 잡기 때문에 자동으로 무시됩니다.

    $ make celan
    

    그냥 자동으로 무시 celan합니다.

    해결 방법은 모든 것을 장황하게 만드는 것입니다. 무슨 일이 일어나는지 알 수 있습니다. 그러나 이는 합법적 인 출력에 많은 노이즈를 발생시킵니다.

방법 2의 문제 :

  • 인수가 기존 대상과 이름이 같은 경우 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-이 경우)를 선택한 다음 대상 이름을 프로그램 / 러너로 직접 전달하십시오. 대상 이름을 기본 프로그램에 유용한 것으로 풀 수있는 러너 스크립트가있는 경우 이것이 대부분 유용하다고 생각합니다.


아니요. GNU make의 맨 페이지에서 구문을 보면

[-f makefile] [옵션] ... [대상] ...

여러 대상을 지정할 수 있으므로 '아니오'(지정한 정확한 방식으로는 아니오)입니다.


명령 행에서 각 n 번째 인수를 명시 적으로 추출 할 수 있습니다. 이를 위해 변수 MAKECMDGOALS를 사용할 수 있으며, 'make'에 제공된 명령 행 인수 목록을 보유하며 이는 대상 목록으로 해석됩니다. n 번째 인수를 추출하려면 "word"함수와 함께 해당 변수를 사용할 수 있습니다. 예를 들어 두 번째 인수를 원하는 경우 다음과 같이 변수에 변수를 저장할 수 있습니다.

second_argument := $(word 2, $(MAKECMDGOALS) )

곧이 , run: ./prog오른쪽 부분이 대상이되어야 정도로, 조금 이상한 보이는 run: prog더 나은 보인다.

나는 간단하게 제안 할 것이다 :

.PHONY: run

run:
        prog $(arg1)

그리고 나는 인수가 전달 될 수 있다고 덧붙이고 싶습니다.

  1. 인수로 : make arg1="asdf" run
  2. 또는 환경으로 정의하십시오. arg1="asdf" make run

여기 내 예가 있습니다. 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

내가 사용하는 또 다른 트릭 은 건식 실행 -n을 지시 하는 플래그 make입니다. 예를 들어

$ make install -n 
# Outputs the string: helm install stable/airflow --name airflow -f values.yaml
$ eval $(make install -n) --dry-run --debug
# Runs: helm install stable/airflow --name airflow -f values.yaml --dry-run --debug

참고 URL : https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run



반응형