변수에서 이름을 계산하여 즉석에서 여러 대상을 만드는 상당히 큰 메이크 파일이 있습니다. (예 : foo $ (VAR) : $ (PREREQS)). gnu make가 이러한 변수를 확장 한 후 대상 목록을 뱉어 낼 수있는 방법이 있습니까?
임의의 메이크 파일에 대한 타겟을 얻고 싶습니다. 셸에 대한 완성 함수를 작성하려고합니다.
변수에서 이름을 계산하여 즉석에서 여러 대상을 만드는 상당히 큰 메이크 파일이 있습니다. (예 : foo $ (VAR) : $ (PREREQS)). gnu make가 이러한 변수를 확장 한 후 대상 목록을 뱉어 낼 수있는 방법이 있습니까?
임의의 메이크 파일에 대한 타겟을 얻고 싶습니다. 셸에 대한 완성 함수를 작성하려고합니다.
답변:
make -pn
(예 :)에서 출력을 구문 분석 할 수 있습니까 make --print-data-base --dry-run
? 모든 변수, 규칙, 암시 적 규칙 및 힘든 세부 사항으로 실행될 명령을 인쇄합니다.
make -pn | sed -rn '/^[^# \t\.%].*:[^=]?/p'
make -pnr
. 은 -r
묵시적 규칙을 제거합니다.
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
매력처럼 작동하는 make arg 완성에서 가져 왔습니다.
~/bin
별칭을 사용하는 대신 쉘 스크립트에 넣었습니다 . 훌륭하게 작동합니다. 감사!
alias mkl="make -qp | awk -F':' '/^[a-zA-Z0-9][^\$#\/\t=]*:([^=]|\$)/ {split(\$1,A,/ /);for(i in A)print A[i]}' | sort"
당신에게 :-) 인용 게임의 2 분 절약 할 수
| sort -u
더 유용 해 보인다 :)
이것이 gnu make 일인지 확실하지 않지만 잘 작동합니다.
make help
몇몇 응답자들은을 사용하여 make -pn
규칙 데이터베이스를 인쇄하지만 실행하지는 않습니다. 이 접근 방식의 문제 -n
는 여전히 모든 재귀 적 make를 호출하고 일반 빌드에서 호출했을 모든 명령을 인쇄하기 때문에 필요한 것보다 더 많은 작업을 수행한다는 것입니다. 보다 효율적인 솔루션은 다음 내용으로 간단한 makefile 인 dummy.mk를 만드는 것입니다.
__all_targets__: ; #no-op
이제 make를 make -p -f Makefile -f dummy.mk __all_targets__
. 실질적인 빌드에서 make에 의해 생성되는 산출량의 차이는 중요합니다. 예를 들면 :
$ gmake -pn | wc
138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
21673 93437 878985
실행 시간도 극적으로 향상되었습니다. 첫 번째 버전은 2.063 초, 두 번째 버전은 0.059 초였습니다.
time make -pn | wc -l
": 1338738 real 0m47.754s.
" time make -f Makefile -f dummy.mk -pn __all_targets__ | wc -l
": 938621 real 0m40.219s
.
make
즉, 비슷하지만 쉬운 무언가를 제안 할 것make -p -f/dev/null
-f /dev/null
하면 make
일반 메이크 파일을 구문 분석 하지 못 하므로 기본 제공 규칙 만 출력됩니다. 그래서 내 솔루션이 -f Makefile -f dummy.mk
. 하지만 그와 있기 때문에, 하나 충분하지 않아 -n
, make
가서 실제로 메이크의 규칙을 실행하기 시작뿐만 아니라 것입니다. 안타깝게도 원래 제시된대로 솔루션을 단순화 할 수있는 수정 사항은 없습니다.
-n
..."
편집 : 참고로 다른 답변의 debian bash 완료 git 저장소에는 이제 bash 완료 사용 사례에 맞게 조정 된이 스크립트의 향상된 버전이 통합됩니다.
#!/bin/bash
SCRIPT='
/^# Make data base/,/^# Files/d # skip until files section
/^# Not a target/,+1 d # following target isnt
/^\.PHONY:/ d # special target
/^\.SUFFIXES:/ d # special target
/^\.DEFAULT:/ d # special target
/^\.PRECIOUS:/ d # special target
/^\.INTERMEDIATE:/ d # special target
/^\.SECONDARY:/ d # special target
/^\.SECONDEXPANSION/ d # special target
/^\.DELETE_ON_ERROR:/ d # special target
/^\.IGNORE:/ d # special target
/^\.LOW_RESOLUTION_TIME:/ d # special target
/^\.SILENT:/ d # special target
/^\.EXPORT_ALL_VARIABLES:/ d # special target
/^\.NOTPARALLEL:/ d # special target
/^\.ONESHELL:/ d # special target
/^\.POSIX:/ d # special target
/^\.NOEXPORT:/ d # special target
/^\.MAKE:/ d # special target
# The stuff above here describes lines that are not
# explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
# should be output.
/^[^#\t:=%]+:([^=]|$)/ { # found target block
h # hold target
d # delete line
}
/^# File is an intermediate prerequisite/ { # nope
s/^.*$//;x # unhold target
d # delete line
}
/^([^#]|$)/ { # end of target block
s/^.*$//;x # unhold target
s/:.*$//p # write current target
d # hide any bugs
}
'
make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
| sort | uniq
이것은 질문이 요구하는 생성 된 규칙에 대한 결과를 제공하고 가장 많이 득표 한 답변 (데비안 git 서버의 데비안 bash 완료 스크립트)이 충분하지 않기 때문에 데비안 bash 완료 스크립트보다 훨씬 더 완전한 스크립트입니다.
이것은 내가 링크 한 원래 스크립트는 아니지만 훨씬 더 간단하고 터치가 더 빠릅니다.
이것은 Todd Hodes 솔루션을 기반으로하는 별칭에 대한 코드입니다.
alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
여기에 sed 및 egrep 마법이있는 아주 좋은 솔루션이 있습니다 : https://gist.github.com/pvdb/777954
내가이 파티에 좀 늦었 나봐요.하지만 특정 명령을 찾고 있다면 시도해 볼 수 있습니다
make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
이것은 대부분 작동하지만 vpath
지시문 과 같은 대상이 아닌 항목이 여전히 포함될 수 있습니다 . make
의 기본 제공 규칙 에 의존하지 않는 경우 make -qpR
파이프 라인에서 첫 번째 명령으로 사용할 수 있습니다 .
나는 솔라리스 10과 터보 C 쉘에서 일하고 있습니다. 주어진 솔루션이 내 메이크 파일 프로젝트에서 작동하지 않습니다. 위의 명령 줄을 tcsh 구문으로 변경 한 후에도. 그러나 나는 당신이 사용하여 쉬운 해결책을 얻을 수 있다는 것을 알았습니다.
remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´
리메이크 버전 :
remake --version
이다
GNU Make 3.82+dbg0.8
Built for sparc-sun-sparc2-9
기타 중요하지 않은 버전 데이터
다른 스레드에서이 솔루션을 찾았습니다.
sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""
다음 항목에 추가 할 수도 있습니다 Makefile
.
list:
sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""
그리고 실행하십시오 make list
.
알겠습니다.하지만 언제 뱉어 내길 원하나요?
규칙을 실행할 때 대상 이름을보고하려면 규칙에 다음 행을 입력하십시오.
foo$(VAR): $(PREREQS)
@echo now making the foo target: $@
do_other_stuff...
한 번에 모두 뱉어 내려면 별도의 PHONY 대상을 만들 수 있습니다.
.PHONY: show_vars
show_vars:
@echo foo$(VAR)
@echo bar$(PARAM) blah$(FLAG)
# and so on
그리고 이것은 기본 대상의 전제 조건이 될 수 있습니다.
all: show_vars
...
편집 :
당신은 임의의 메이크 파일의 가능한 모든 대상을 표시하는 방법을 원합니다. 잘...
이를 정확하게 수행하고 예를 들어 eval
문으로 구성된 규칙을 포함하는 정교한 메이크 파일에 대처할 수 있으려면 Make 에뮬레이터에 가까운 무언가를 작성해야합니다. 비현실적입니다.
간단한 규칙의 대상을 보려면 임의의 메이크 파일에서 작동하는 메이크 파일 스캐너 역할을하는 메이크 파일을 작성할 수 있습니다.
이것은 인상적인 작품이 될 것입니다. 목표가 노력할만한 가치가 있다고 확신합니까?
grep ^[a-z].*\:$ Makefile | sed s,:,,g
:=
)에 대해서도 거짓 긍정을 생성합니다 .