Lista celów / targets w GNU make, które zawierają zmienne w swojej definicji

Mam dość duży plik makefile, który tworzy wiele celów w locie, obliczając nazwy ze zmiennych. (np. foo$(VAR): $(PREREQS)). Czy jest jakiś sposób, aby gnu make mógł być przekonany do wyplucia listy celów po rozszerzeniu tych zmiennych?

Chciałbym być w stanie zdobyć cele dla aribitrary makefile. Próbuję napisać funkcję dopełnienia dla mojej powłoki.

16 answers

Czy możesz przeanalizować wyjście z make -pn (tj. make --print-data-base --dry-run)? Wypisuje wszystkie zmienne, reguły, reguły ukryte i które polecenia będą uruchamiane w żmudnych szczegółach.

 77
Author: Jack Kelly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-03 02:02:12
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

Wzięte z make arg, który działa jak urok.

 111
Author: todd hodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-02 18:55:54

Nie jestem pewien czy to jest tylko gnu make, ale to działa dobrze:

make help

 13
Author: Zdenik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-11 21:23:28

Kilku respondentów zasugerowało użycie make -pn, które wydrukuje bazę reguł, ale niczego nie wykona-mniej więcej. Problem z tym podejściem polega na tym, że -n nadal wywołuje wszystkie rekurencyjne Make, i nadal wykonuje o wiele więcej pracy niż to konieczne, ponieważ wypisuje wszystkie polecenia, które wywołałby w zwykłej kompilacji. Bardziej efektywnym rozwiązaniem byłoby stworzenie banalnego makefile, dummy.mk, o treści:

__all_targets__: ; #no-op

Teraz wywołaj make jako make -p -f Makefile -f dummy.mk __all_targets__. W przypadku każdej istotnej budowy różnica w ilości produkcji generowanej przez make jest znacząca. Na przykład:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985

Czas wykonania był znacznie lepszy, jak również -- 2.063 s dla pierwszej wersji, 0.059 s dla drugiej.

 10
Author: Eric Melski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-12 16:14:51

Sprawdź Ukończenie bash dla make na Githubie.

 9
Author: js.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-01 08:25:11

Edit: dla twojej wiadomości repozytorium Debian bash completion git w innej odpowiedzi zawiera teraz ulepszoną wersję tego skryptu dostosowaną do przypadków użycia bash completion.

#!/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

Jest to o wiele bardziej kompletny skrypt niż skrypt zakończenia bash Debiana, ponieważ zapewnia wyniki dla wygenerowanych reguł, o co prosi pytanie, a najczęściej głosowana odpowiedź (skrypt zakończenia bash Debiana na debian Git server) nie idzie wystarczająco daleko.

To nie jest oryginalny skrypt, który Połączyłem się, ale to jest znacznie prostsze i jest to dotyk szybciej.

 7
Author: codeshot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 21:37:45

To jest kod aliasu oparty na rozwiązaniu Todda Hodesa

alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
 4
Author: Nguyễn Minh Vũ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-20 06:40:23

To da ładny wynik:

make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort
 3
Author: Andor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-08 13:22:19

Jest tu bardzo ładne rozwiązanie z jakąś magią sed i egrep: https://gist.github.com/pvdb/777954

 3
Author: Atilla Filiz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-06 08:42:19

Chyba trochę się spóźniłem na tę imprezę, ale jeśli szukasz konkretnego polecenia, możesz spróbować

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

To w większości działa, chociaż nadal może zawierać pewne rzeczy niecelowe, takie jak dyrektywa vpath. Jeśli nie zależy ci na wbudowanych regułach make, możesz użyć make -qpR jako pierwszego polecenia w potoku.

 2
Author: DGrady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-06 17:31:04

Ruby rozwiązanie:

`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
 1
Author: gdub,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-09 08:39:55

Pracuję na Solaris 10 i turbo C shell. Podane rozwiązanie nie działa dla mojego projektu makefile. nawet po zmianie powyższej linii poleceń na składnię tcsh. Jednak okazało się, że można uzyskać łatwe rozwiązanie za pomocą

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

Wersja Remake:

remake --version

Jest

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

I inne nieistotne dane wersji

 1
Author: Aviv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-20 05:14:41

Szukałem tego samego pytania i wpadłem na ten spin:

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

Usuwa wszystkie linie komentarza, reguły wzorca (linie rozpoczynające się tabulatorami), wszystkie wewnętrzne (przykładowe wzorce .c.o i %.o: %.c).

 0
Author: Jamie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-03 21:41:12

Znalazłem to rozwiązanie w innym wątku:

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

Możesz też dodać go do swojego Makefile:

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

I wykonać make list.

 0
Author: thisismydesign,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-03 16:26:45

Jasne, ale kiedy chcesz je wypluć?

Aby zgłosić nazwę celu podczas uruchamiania reguły, umieść wiersz w regule:

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

Aby wypluć je wszystkie na raz, można zrobić osobny fałszywy Cel:

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

I to może być warunkiem wstępnym domyślnego celu:

all: show_vars
    ...

EDIT:
Chcesz pokazać wszystkie możliwe cele dowolnego pliku makefile, co chyba oznacza nieinwazyjnie. Cóż...

To do it dokładnie, i być w stanie poradzić sobie z wyrafinowanymi plikami Makefile, np. zawierającymi reguły skonstruowane przez eval, musiałbyś napisać coś podobnego do emulatora Make. Niepraktyczne.

Aby zobaczyć cele prostych zasad, możesz napisać plik makefile, który będzie działał jak skaner makefile, działający na dowolnym pliku makefile:

  1. pobranie wszystkich nazw docelowych z pliku makefile przy użyciu sed.
  2. `include ' plik makefile, aby użyć go do rozszerzenia zmienne.
  3. użyj ' show_%:; echo$$*', aby wydrukować wszystkie cele
To byłoby imponujące dzieło. Czy jesteś pewien, że cel jest wart wysiłku?
 -1
Author: Beta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-22 19:08:48
grep ^[a-z].*\:$ Makefile | sed s,:,,g
 -4
Author: Willian Braga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 19:22:54