[makefile] makefile에서 대상 목록을 어떻게 얻습니까?

나는 약간의 갈퀴를 사용했고 (Ruby make 프로그램), 사용 가능한 모든 대상의 목록을 얻는 옵션이 있습니다.

> rake --tasks
rake db:charset      # retrieve the charset for your data...
rake db:collation    # retrieve the collation for your da...
rake db:create       # Creates the databases defined in y...
rake db:drop         # Drops the database for your curren...
...

그러나 GNU make에서 이것을 할 수있는 옵션이없는 것 같습니다.

분명히 코드는 2007 년 http://www.mail-archive.com/help-make@gnu.org/msg06434.html 현재 거의 있습니다 .

어쨌든, makefile에서 대상을 추출하기 위해 약간의 핵을 만들었습니다. makefile에 포함시킬 수 있습니다.

list:
    @grep '^[^#[:space:]].*:' Makefile

정의 된 대상 목록을 제공합니다. 그것은 단지 시작일뿐입니다. 예를 들어 의존성을 걸러 내지 않습니다.

> make list
list:
copy:
run:
plot:
turnin:



답변

이것은 다음과 같이 @nobar의 훌륭한 접근 방식 을 개선하려는 시도입니다 .

  • 어떤 희망 가양 방지 (및 불필요한 멀리 않는 대상 이름을 추출하기 위해보다 강력한 명령을 사용하여 sh -c)
  • 현재 디렉토리 의 makefile을 항상 대상으로하지 않습니다 . 명시 적으로 지정된 makefile을 존중-f <file>
  • 숨겨진 대상 제외-관례에 따라 이름은 문자 나 숫자로 시작하지 않는 대상입니다.
  • 차종은 함께 할 하나의 가짜 대상
  • @실행 전에 에코되지 않도록 명령 접두사

흥미롭게도 GNU make에는 makefile에 정의 된 대상 이름 만 나열하는 기능이 없습니다. 이 -p옵션은 모든 대상을 포함하는 출력을 생성하지만 다른 많은 정보로 저장합니다.

GNU의 makefile에 다음 규칙을 배치하십시오. makelist 알파벳순으로 모든 대상 이름을 나열하는 이름 지정된 대상을 구현할 수 있습니다 ( 예 : invoke asmake list :

.PHONY: list
list:
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

중요 사항 : 붙여 넣기시 때 마지막 줄에 정확히 1 개의 실제 탭 문자 가 들여 쓰기되어 있는지 확인하십시오 . (공백이 작동 하지 않습니다 ) .

참고 정렬 이후 목표의 결과 목록하는 것이 가장 좋은 방법입니다 하지 대상이 메이크 파일에 나타나는 순서가 있는지에 도움이 순서를 생성하지 않습니다 정렬 되지 보존.
또한 여러 대상을 포함하는 규칙의 하위 대상은 항상 개별적으로 출력 되므로 정렬로 인해 일반적으로 나란히 표시 되지 않습니다. 예를 들어, a z:will으로 시작하는 규칙 없는 목표를 가지고 az나와 서로 옆에 추가 대상이있는 경우, 출력에.

규칙 설명 :

  • .PHONY: list
    • 대상 목록에 가짜 대상, 즉 파일을 참조 하지 않는 대상을 선언 하므로 레시피가 무조건 호출되어야합니다.
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • makemakefile에서 파생 된 데이터베이스를 인쇄하고 구문 분석하기 위해 다시 호출 합니다.
      • -p 데이터베이스를 인쇄
      • -Rr 내장 규칙 및 변수의 포함을 억제합니다
      • -q대상의 최신 상태 만 테스트하지만 (아무것도 만들지 않음) 모든 경우에 레시피 명령의 실행을 막지는 않습니다. 그 후:
      • -f $(lastword $(MAKEFILE_LIST))을 (를) 내재적으로 또는 명시 적으로 대상화했는지 여부에 관계없이 원래 호출에서와 동일한 메이크 파일을 대상으로합니다 -f ....
        주의 사항 : makefile에 include지시문이 포함되어 있으면 중단됩니다 . 주소이에, 변수를 정의 THIS_FILE := $(lastword $(MAKEFILE_LIST)) 하기 전에 모든 include지침과 사용 -f $(THIS_FILE)대신.
      • :A는 의도적으로 잘못된 대상 을 의미한다 어떤 명령이 실행되지 않도록은 ; 2>/dev/null결과 오류 메시지를 표시하지 않습니다. 참고 : -p그럼에도 불구하고 이것은 GNU make 3.82의 경우와 같이 데이터베이스 인쇄에 의존합니다 . 슬프게도에 GNU 메이크 제공 직접적인 옵션을 바로 하지 않고, 데이터베이스를 인쇄 기본 (또는 제공) 작업을 실행; 특정 Makefile을 타겟팅 할 필요가없는 경우 페이지 make -p -f/dev/null에서 권장 하는대로을 사용할 수 있습니다 man.
  • -v RS=

    • 이것은 비어 있지 않은 빈 라인의 블록으로 입력을 나누는 어색한 관용구입니다.
  • /^# File/,/^# Finished Make data base/
    • 모든 대상을 포함하는 출력의 행 범위와 일치합니다 (GNU make 3.82에서 참).이 범위로 구문 분석을 제한하면 다른 출력 섹션의 오 탐지를 처리 ​​할 필요가 없습니다.
  • if ($$1 !~ "^[#.]")
    • 블록을 선택적으로 무시합니다 :
      • # … 블록으로 시작하는 비 타겟을 무시합니다. # Not a target:
      • . … 특별한 목표를 무시
    • 다른 모든 블록은 각각 명시 적으로 정의 된 대상 이름과 그 뒤에 오는 이름 만 포함하는 줄로 시작해야합니다. :
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$' 출력에서 원하지 않는 대상을 제거합니다.
    • '^[^[:alnum:]]'… 일반적으로 문자 나 숫자로 시작하지 않는 대상인 숨겨진 대상은 제외합니다 .
    • '^$@$$'list대상 자체는 제외

실행 make list하면 모든 대상이 각각 고유 한 행에 인쇄됩니다. xargs공백으로 구분 된 목록을 작성 하기 위해 파이프로 연결할 수 있습니다 .


답변

Bash (적어도)에서 이것은 탭 완성으로 자동으로 수행 할 수 있습니다.

make spacetabtab


답변

이것은 많은 경우에 효과가 없지만 MakefileCMake에 의해 생성 된 경우 실행할 수 있습니다 make help.

$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... install
etc


답변

나는 https://stackoverflow.com/a/9524878/86967https://stackoverflow.com/a/7390874/86967 이라는 두 가지 답변을 결합
하여 makefile 내부에서 사용할 수 있도록 탈출했습니다.

.PHONY: no_targets__ list
no_targets__:
list:
    sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"

.

$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run


답변

bash 완료를 make설치 한 경우 완료 스크립트가 기능을 정의합니다 _make_target_extract_script. 이 기능은 sed대상을 목록으로 얻는 데 사용할 수 있는 스크립트 를 작성 하기위한 것입니다.

다음과 같이 사용하십시오.

# Make sure bash completion is enabled
source /etc/bash_completion

# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile


답변

으로 mklement0 점 밖으로 , 모든 메이크 목표를 나열하는 기능은 GNU-메이크업에서 누락되고, 그의 대답하고 다른 사람이 작업을 수행하는 방법을 제공합니다.

그러나, 원래의 게시물도 언급 레이크 누구의 작업 전환 바로 rakefile에서 모든 작업을 나열보다 약간 다른 무언가를합니다. Rake는 관련 설명이있는 작업 목록 만 제공합니다. 설명 이없는 작업 은 표시되지 않습니다 . 이를 통해 저자는 사용자 정의 된 도움말 설명을 제공하고 특정 대상에 대한 도움말을 생략 할 수 있습니다.

각 대상에 대한 설명을 제공하는 레이크의 동작을 에뮬레이션하려면 간단한 방법이 있습니다. 설명하려는 각 대상에 대한 설명에 설명을 포함시킵니다.

다음과 같이 대상 옆에 설명을 넣거나 종종 대상 위의 PHONY 사양 옆에 설명을 넣을 수 있습니다.

.PHONY: target1 # Target 1 help text
target1: deps
    [... target 1 build commands]

.PHONY: target2 # Target 2 help text
target2:
    [... target 2 build commands]

...

.PHONY: help # Generate list of targets with descriptions
help:
    @grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20

어느 것이 생산할 것인가

$ make help
target1             Target 1 help text
target2             Target 2 help text

...
help                Generate list of targets with descriptions

이 요지여기 에서도 짧은 코드 예제를 찾을 수 있습니다 .

다시 말하지만, 모든 대상을 Makefile에 나열하는 문제는 해결되지 않습니다. 예를 들어, 생성되었거나 다른 사람이 작성한 큰 Makefile이 있고 대상을 파지 않고 대상을 빠르게 나열하는 방법을 원한다면 도움이되지 않습니다.

그러나 Makefile을 작성 중이고 일관된 자체 문서화 방식으로 도움말 텍스트를 생성하는 방법을 원하는 경우이 기술이 유용 할 수 있습니다.


답변

@nobar의 답변탭 완성을 사용하여 makefile의 대상을 나열하는 방법을 보여줍니다 .

  • 기본적 으로이 기능을 제공하는 플랫폼 (예 : Debian, Fedora )에 적합합니다.

  • 다른 플랫폼 (예 : Ubuntu ) 에서는 에서는 @ hek2mgl의 답변에 의해 암시 된 것처럼이 기능을 명시 적으로로드 .

    • . /etc/bash_completion 에 대한 기능을 포함하여 여러 탭 완성 기능을 설치합니다. make
    • 또는 다음에 대한 탭 완성 설치하려면 다음을 수행 하십시오 make.
      • . /usr/share/bash-completion/completions/make
  • 들어 모두에서이 기능을 제공하지 않는 플랫폼 등, OSX , 당신은 할 수 있습니다 다음 명령을 소스 (에서 adapated 여기 )를 구현하는 :
_complete_make() { COMPREPLY=($(compgen -W "$(make -pRrq : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($1 !~ "^[#.]") {print $1}}' | egrep -v '^[^[:alnum:]]' | sort | xargs)" -- "${COMP_WORDS[$COMP_CWORD]}")); }
complete -F _complete_make make
  • 참고 : 이것은 Linux 배포판과 함께 제공되는 탭 완성 기능만큼 정교하지는 않습니다. 특히 명령 줄이로 다른 makefile을 대상으로하는 경우에도 항상 현재 디렉토리 의 makefile을 대상으로합니다 -f <file>.