정의에 변수를 포함하는 GNU make의 목표 / 타겟 나열


100

변수에서 이름을 계산하여 즉석에서 여러 대상을 만드는 상당히 큰 메이크 파일이 있습니다. (예 : foo $ (VAR) : $ (PREREQS)). gnu make가 이러한 변수를 확장 한 후 대상 목록을 뱉어 낼 수있는 방법이 있습니까?

임의의 메이크 파일에 대한 타겟을 얻고 싶습니다. 셸에 대한 완성 함수를 작성하려고합니다.

답변:


79

make -pn(예 :)에서 출력을 구문 분석 할 수 있습니까 make --print-data-base --dry-run? 모든 변수, 규칙, 암시 적 규칙 및 힘든 세부 사항으로 실행될 명령을 인쇄합니다.


이 답변은 다른 답변보다 훨씬 좋아 보입니다.
Matt Joiner

나는 이것이 훨씬 더 좋다는 데 동의합니다. 내가 기대했던 것보다 더 많은 일이 있지만, 다른 것은 합리적이지 않고 GNU make가 내가 원하는 것에 대한 편리한 플래그를 가지고 있지 않기 때문에 답으로 표시하겠습니다.
BitShifter

6
Makefile이 대상을 동적으로 생성하는 경우 출력은 지정한 대상에 따라 달라질 수 있습니다. 출력은 환경 변수의 값에 따라 달라 지거나 make 명령으로 지정된 변수를 만들 수 있습니다.
reinierpost 2011 년

6
나는 간결함을 좋아합니다. +1 (아래 답변에 기술) 내 자신의 스핀을 추가 :make -pn | sed -rn '/^[^# \t\.%].*:[^=]?/p'
제이미

제안하십시오 make -pnr. 은 -r묵시적 규칙을 제거합니다.
sjbx

114
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

매력처럼 작동하는 make arg 완성에서 가져 왔습니다.


2
나는 이것에 대한 별칭을 만들고 큰 따옴표로 묶으려고했지만 첫 번째 쉼표에 구문 오류가있는 awk가 발생합니다 ... 셸 (bash) 별칭에 대해 올바르게 이스케이프하는 방법에 대한 생각이 있습니까?
drfrogsplat 2012 년

3
나는 그것이 정의 된 곳과 관련이 있다고 생각합니다. 별칭으로 정의되면 작업 디렉토리가 정의 된 디렉토리가되고 분명히 awk 부분은 숨겨진 디렉토리의 점을 좋아하지 않습니다. 함수 정의가 작동합니다.
Ibrahim

~/bin별칭을 사용하는 대신 쉘 스크립트에 넣었습니다 . 훌륭하게 작동합니다. 감사!
mpontillo

3
별칭 alias mkl="make -qp | awk -F':' '/^[a-zA-Z0-9][^\$#\/\t=]*:([^=]|\$)/ {split(\$1,A,/ /);for(i in A)print A[i]}' | sort"당신에게 :-) 인용 게임의 2 분 절약 할 수
치로 틸리郝海东冠状病六四事件法轮功

1
| sort -u더 유용 해 보인다 :)
sherpya

14

이것이 gnu make 일인지 확실하지 않지만 잘 작동합니다.

make help


이것은 다른 방법 중 하나에 대한 사용자 지정 별칭보다 매우 편리하고 기억하기 훨씬 쉽습니다.
Ibrahim

8
실제로 GNU Make 3.81에서 작동하지 않습니다. makefile의 타겟 일 것입니다. "make : *** 타겟`help '를 만드는 규칙이 없습니다. Stop"
a1an

8
이것은 Makefile에서 "help"대상을 호출합니다. 존재하는 경우 ( 전체 대상 목록이 아닌) 무언가를 인쇄하고 , 존재하지 않는 경우 (일반적인 상황) 구제 조치합니다.
pfalcon 2013

2
좋은 소식은 cmake가 읽기 쉬운 "도움말"대상을 생성하는 것 같다는 것입니다.
Stéphane 2014 년

굉장합니다! : 이동 cmake
Jeef

10

몇몇 응답자들은을 사용하여 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 초였습니다.


1
깔끔한 아이디어, 거대한 빌드 시스템으로 작업하는 모든 사람이 감사 할 것입니다. Android Gingerbread 트리에 대한 통계 (재귀 적 만들기를 사용하지 않으므로 비용을 크게 절약 할 수 없습니다. 그저 좋음) : " 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.
pfalcon 2013

좋은 지적. 에 대한 매뉴얼 페이지 make즉, 비슷하지만 쉬운 무언가를 제안 할 것make -p -f/dev/null
다비드

제대로 작동하지 않는 @Davide : 지정 -f /dev/null하면 make일반 메이크 파일을 구문 분석 하지 못 하므로 기본 제공 규칙 만 출력됩니다. 그래서 내 솔루션이 -f Makefile -f dummy.mk. 하지만 그와 있기 때문에, 하나 충분하지 않아 -n, make가서 실제로 메이크의 규칙을 실행하기 시작뿐만 아니라 것입니다. 안타깝게도 원래 제시된대로 솔루션을 단순화 할 수있는 수정 사항은 없습니다.
Eric Melski

물론 당신이 옳습니다. 그러나 make man 페이지에는 "파일을 다시 만들지 않고 데이터베이스를 인쇄하려면 make -p -f / dev / null을 사용하십시오."라는 버그가 있습니다.
Davide

내 이전 의견에 약간의 수정 : 그것은 "때문에 ... 읽어야 하지 않고 -n ..."
에릭 Melski


7

편집 : 참고로 다른 답변의 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 완료 스크립트보다 훨씬 더 완전한 스크립트입니다.

이것은 내가 링크 한 원래 스크립트는 아니지만 훨씬 더 간단하고 터치가 더 빠릅니다.


BTW, mods, 텍스트의 뉘앙스로 인해이 답변이 모든 정책과 완전히 일치하지 않으면 삭제하기 전에 의견을 말하십시오. 이 질문이 실제로 완전하고 유효한 답변을 얻을 수 있도록 필요한 합법적 인 조정을 할 것입니다.
코드 샷

빠른 테스트로 gcc 소스 코드를 가져와 ./configure && time ~ / makecomp.sh | wc -l 여기서 ~ / makecomp.sh는 내 대답입니다. ... 출력 구성 ... config.status : Makefile 생성 3312 real 0m0.401s user 0m0.412s sys 0m0.028s
codeshot

또 다른 테스트로 codeshot.blogspot.co.uk/2012/08/… 에서 데모 메이크 파일을 사용했습니다.이 파일은 단위 테스트 통과를 빌드하고 확인하기위한 의사 규칙을 생성합니다. 이 예제는 일반적인 크로스 플랫폼 autoconf 프로젝트보다 더 많은 make 기능을 사용하므로이 답변의 스크립트는 14 개의 실제 대상을 반환하는 반면 우분투에서 make에 대한 bash 완료는 2 개의 유용한 규칙과 5 개의 소스 파일 만 반환합니다.
codeshot

4

이것은 Todd Hodes 솔루션을 기반으로하는 별칭에 대한 코드입니다.

alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'

3

이것은 좋은 출력을 줄 것입니다 :

make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort


2

내가이 파티에 좀 늦었 나봐요.하지만 특정 명령을 찾고 있다면 시도해 볼 수 있습니다

make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'

이것은 대부분 작동하지만 vpath지시문 과 같은 대상이 아닌 항목이 여전히 포함될 수 있습니다 . make의 기본 제공 규칙 에 의존하지 않는 경우 make -qpR파이프 라인에서 첫 번째 명령으로 사용할 수 있습니다 .


freetz (.org)로 시도했습니다. 포함 된 많은 메이크 파일을 나열하고 모든 대상을 나열하지 않았습니다.
Robert Siemer 2012-06-02

1

Ruby 솔루션 :

`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}

1

나는 솔라리스 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

기타 중요하지 않은 버전 데이터


0

나는 같은 질문을 찾아서이 스핀을 생각 해냈다.

make -pn | sed -rn '/^[^# \t\.%].*:/p'

이렇게하면 모든 주석 줄, 패턴 규칙 (탭으로 시작하는 줄), 모든 내장 (예제 .c.o%.o: %.c패턴)이 제거됩니다.


수락 된 답변에서 댓글을 읽지 않았습니다. 잭의 답변에 +1 ... gist.github.com/777954 – pvandenberk 1 월 13 일 14:47
Jamie

0

다른 스레드에서이 솔루션을 찾았습니다.

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.


-1

알겠습니다.하지만 언제 뱉어 내길 원하나요?

규칙을 실행할 때 대상 이름을보고하려면 규칙에 다음 행을 입력하십시오.

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 에뮬레이터에 가까운 무언가를 작성해야합니다. 비현실적입니다.

간단한 규칙의 대상을 보려면 임의의 메이크 파일에서 작동하는 메이크 파일 스캐너 역할을하는 메이크 파일을 작성할 수 있습니다.

  1. sed를 사용하여 메이크 파일에서 모든 대상 이름을 가져옵니다.
  2. 변수를 확장하는 데 사용하려면 makefile을 '포함'하십시오.
  3. `show_ % :; 모든 대상을 인쇄하려면 echo $$ *`

이것은 인상적인 작품이 될 것입니다. 목표가 노력할만한 가치가 있다고 확신합니까?


내가 원하는 것이 아닙니다. 내가 가지고있을 수있는 임의의 makefile에 대한 대상 목록을 만들 수 있기를 바랍니다. 내 셸에 대한 인수 완료 함수를 작성하려고하는데 현명한 도움이되는 makefile에 의존 할 수 없습니다.
BitShifter

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.