program story

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

inputbox 2020. 8. 20. 08:19
반응형

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


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

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


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


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

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


이것이 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 초였습니다.


GitHub 에서 make대한 bash 완료를 확인하십시오 .


편집 : 참고로 다른 답변의 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]}"'

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

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

여기에 sed 및 egrep 마법이있는 아주 좋은 솔루션이 있습니다 : https://gist.github.com/pvdb/777954


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

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

This mostly works, although it might still include some non-target stuff like a vpath directive. If you don't depend on make's built-in rules, you can use make -qpR as the first command in the pipeline.


Ruby solution:

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

Im working on solaris 10 anda turbo C shell. The given solution doesn´t work for my makefile project. even after altering the command line above to tcsh syntax. However, I found out you can get an easy solution using

remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´

remake version:

remake --version

is

GNU Make 3.82+dbg0.8
Built for sparc-sun-sparc2-9

and some other unimportant version data


I went looking for the same question and came up with this spin:

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

This removes all comment lines, pattern rules (lines beginning with tabs), all the intrinsics (example .c.o and %.o: %.c patterns).


Found this solution in another thread:

sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""

You can also add it to your Makefile:

list:
    sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""

And execute make list.


Sure, but when do you want it to spit them out?

To report the name of the target when it runs the rule, put a line in the rule:

foo$(VAR): $(PREREQS)
    @echo now making the foo target: $@
    do_other_stuff...

To spit them all out at once, you could make a separate PHONY target:

.PHONY: show_vars
show_vars:
    @echo foo$(VAR)
    @echo bar$(PARAM) blah$(FLAG)
    # and so on

And this can be made a prerequisite of your default target:

all: show_vars
    ...

EDIT:
You want a way to show all possible targets of an arbitrary makefile, which I suppose means non-intrusively. Well...

To do it exactly, and be able to cope with sophisticated makefiles, e.g. involving rules constructed by eval statements, you'd have to write something close to a Make emulator. Impractical.

To see the targets of the simple rules, you could write a makefile that would act as a makefile scanner, operating on an arbitrary makefile:

  1. Get all the target names from the makefile using sed.
  2. `include` the makefile in order to use it to expand variables.
  3. Use `show_%: ; echo $$*` to print all the targets

This would be an impressive piece of work. Are you sure the goal is worth the effort?


grep ^[a-z].*\:$ Makefile | sed s,:,,g

참고URL : https://stackoverflow.com/questions/3063507/list-goals-targets-in-gnu-make-that-contain-variables-in-their-definition

반응형