Wie erhält man die Liste der Ziele in einem Makefile?

202

Ich habe ein bisschen Rake verwendet (ein Ruby-Make-Programm) und es gibt eine Option, um eine Liste aller verfügbaren Ziele zu erhalten, z

> 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...
...

aber es scheint keine Option zu geben, dies in GNU make zu tun.

Anscheinend ist der Code ab 2007 fast da - http://www.mail-archive.com/[email protected]/msg06434.html .

Wie auch immer, ich habe wenig gehackt, um die Ziele aus einem Makefile zu extrahieren, das Sie in ein Makefile aufnehmen können.

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

Sie erhalten eine Liste der definierten Ziele. Es ist nur ein Anfang - es filtert zum Beispiel nicht die Abhängigkeiten heraus.

> make list
list:
copy:
run:
plot:
turnin:
Brian Burns
quelle
2
Ich lese schnell Antworten, die interessant sind, aber bisher ziehe ich es vor, sie einfach, einfach und portabel mit einem Alias ​​(in meiner .bashrc) zu halten: alias makefile-targets='grep "^[^#[:space:]].*:" Makefile' Meistens muss ich nur das aktuelle Makefile untersuchen, und die Bash-Vervollständigung wird erweitert mein Alias.
RockyRoad
4
Ist es einfach zu trivial : grep : Makefile?
Cibercitizen1

Antworten:

130

Dies ist ein Versuch, den großartigen Ansatz von @ nobar wie folgt zu verbessern :

  • verwendet einen robusteren Befehl, um die Zielnamen zu extrahieren, was hoffentlich Fehlalarme verhindert (und auch das Unnötige beseitigt sh -c).
  • zielt nicht immer auf das Makefile im aktuellen Verzeichnis ab; respektiert Makefiles, die explizit mit angegeben wurden-f <file>
  • schließt versteckte Ziele aus - gemäß Konvention sind dies Ziele, deren Name weder mit einem Buchstaben noch mit einer Ziffer beginnt
  • kommt mit einem einzigen falschen Ziel aus
  • Präfixiert den Befehl @, um zu verhindern, dass er vor der Ausführung wiederholt wird

Seltsamerweise GNU make keine Funktion, um nur die Namen der in einem Makefile definierten Ziele aufzulisten. Die -pOption erzeugt eine Ausgabe, die alle Ziele enthält, diese jedoch in vielen anderen Informationen vergräbt.

Fügen Sie die folgende Regel in ein Makefile für GNU ein make, um ein Ziel mit dem Namen zu implementieren list, das einfach alle Zielnamen in alphabetischer Reihenfolge auflistet - dh: Aufruf alsmake 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 '^$@$$'

Wichtig : Stellen Sie beim Einfügen sicher, dass die letzte Zeile durch genau 1 aktuelles Tabulatorzeichen eingerückt ist . (Leerzeichen nicht ) .

Beachten Sie, dass das Sortieren der resultierenden Liste von Zielen die beste Option ist, da das Nicht- Sortieren keine hilfreiche Reihenfolge ergibt , da die Reihenfolge, in der die Ziele im Makefile angezeigt werden, nicht beibehalten wird.
Außerdem werden die Unterziele einer Regel, die mehrere Ziele umfasst, immer separat ausgegeben und erscheinen daher aufgrund der Sortierung normalerweise nicht nebeneinander. Beispielsweise hat eine Regel, die mit beginnt a z:, keine Ziele aund wird zaufgelistet in der Ausgabe nebeneinander , wenn zusätzliche Ziele vorhanden sind.

Erklärung der Regel :

  • .PHONY: list
    • deklariert die Zielliste als falsches Ziel, dh als eines, das sich nicht auf eine Datei bezieht, deren Rezept daher unbedingt aufgerufen werden sollte
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • Ruft makeerneut auf, um die aus dem Makefile abgeleitete Datenbank zu drucken und zu analysieren:
      • -p druckt die Datenbank
      • -Rr Unterdrückt die Einbeziehung integrierter Regeln und Variablen
      • -qtestet nur den aktuellen Status eines Ziels (ohne etwas neu zu erstellen), aber das allein verhindert nicht in allen Fällen die Ausführung von Rezeptbefehlen; daher:
      • -f $(lastword $(MAKEFILE_LIST))stellt sicher, dass das gleiche Makefile als Ziel des ursprünglichen Aufrufs ausgewählt wird, unabhängig davon, ob es implizit oder explizit mit ausgewählt wurde -f ....
        Vorsichtsmaßnahme : Dies wird unterbrochen, wenn Ihr Makefile includeAnweisungen enthält . diese Adresse definieren variable THIS_FILE := $(lastword $(MAKEFILE_LIST)) bevor irgendwelche includeDirektiven und verwenden -f $(THIS_FILE)statt.
      • :ist ein absichtlich ungültiges Ziel , das sicherstellen soll, dass keine Befehle ausgeführt werden ; 2>/dev/nullunterdrückt die resultierende Fehlermeldung. Hinweis: Dies -phängt jedoch vom Drucken der Datenbank ab, was ab GNU make 3.82 der Fall ist. Leider bietet GNU make keine direkte Option zum einfachen Drucken der Datenbank, ohne auch die Standardaufgabe (oder die angegebene Aufgabe) auszuführen. Wenn Sie nicht auf ein bestimmtes Makefile abzielen müssen, können Sie es verwenden make -p -f/dev/null, wie auf der manSeite empfohlen .
  • -v RS=

    • Dies ist eine awk-Redewendung, die die Eingabe in Blöcke zusammenhängender nicht leerer Zeilen aufteilt.
  • /^# File/,/^# Finished Make data base/
    • Entspricht dem Zeilenbereich in der Ausgabe, der alle Ziele enthält (wahr ab GNU make 3.82). Wenn Sie das Parsen auf diesen Bereich beschränken, müssen Sie sich nicht mit falsch positiven Ergebnissen aus anderen Ausgabeabschnitten befassen.
  • if ($$1 !~ "^[#.]")
    • Ignoriert selektiv Blöcke:
      • # ... ignoriert Nichtziele, deren Blöcke mit beginnen # Not a target:
      • . ... ignoriert spezielle Ziele
    • Alle anderen Blöcke sollten jeweils mit einer Zeile beginnen, die nur den Namen eines explizit definierten Ziels enthält, gefolgt von :
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$' Entfernt unerwünschte Ziele aus der Ausgabe:
    • '^[^[:alnum:]]'... schließt versteckte Ziele aus, bei denen es sich üblicherweise um Ziele handelt, die weder mit einem Buchstaben noch mit einer Ziffer beginnen.
    • '^$@$$'... schließt das listZiel selbst aus

Beim Ausführen werden make listdann alle Ziele in einer eigenen Zeile gedruckt. Sie können zu weiterleiten, xargsum stattdessen eine durch Leerzeichen getrennte Liste zu erstellen.

mklement0
quelle
Dies ist jedoch eine gute Antwort. Wie würde ich die Beschreibung für jede Aufgabe erhalten? Derzeit speichere ich es als Kommentar über der Aufgabendefinition. Sie sind sich nicht sicher, ob es möglich ist, es auf ähnliche Weise wie es in die Liste aufzunehmen rake --tasks?
Piotr Kuczynski
1
@PiotrKuczynski: Interessante Frage, aber ich schlage vor, dass Sie sie als neue Frage posten (auf diese als Referenz verweisen).
mklement0
"Leider bietet GNU make keine direkte Möglichkeit, nur die Datenbank zu drucken." Es gibt eine -nOption.
Bulletmagnet
@Bulletmagnet: Der Zweck der -nOption besteht darin, "die Befehle zu drucken , die ausgeführt werden sollen ..." - mit anderen Worten: eine Trockenlauffunktion. Auch nicht, dass Ihr Angebot fehlt die Kursiv des Wortes nur : make -pvon selbst tut die Datenbank drucken, aber immer läuft auch die Standardaufgabe ; Das Handbuch empfiehlt den klobigen make -p -f/dev/null, um dies zu vermeiden.
mklement0
1
Listet auch alle .PHONY-Ziele auf, stellen Sie also sicher, dass Sie keine haben.PHONY: *
tekumara
188

Unter Bash (zumindest) kann dies automatisch mit Tab-Vervollständigung erfolgen:

make spacetabtab

kein Balken
quelle
1
Getestet: bash --version = 4.2.45 (1) -Release. make --version = 3.81.
Nobar
53
+1, aber beachten Sie, dass dies keine Bash- Funktion ist, sondern von Ihrer Plattform abhängt . Plattformen lassen sich in drei Kategorien einteilen: diejenigen, bei denen diese Fertigstellung standardmäßig installiert ist (z. B. Debian 7, Fedora 20), diejenigen, bei denen Sie sie optional installieren können (z. B. Ubuntu 14 mit . /etc/bash_completion), und diejenigen, die sie überhaupt nicht unterstützen (zB OSX 10.9)
mklement0
8
Es funktioniert unter OS X 10.10 (nicht mit Bash, sondern mit Zsh).
Florian Oswald
4
Toller Tipp, braucht aber auch bash-completionPaket. Gefunden in Fedora, RHEL, Gentoo, ect.
NoelProf
4
Dies funktioniert nicht mit programmgesteuert erstellten Make-Zielen AFAICT, zB$(RUN_TARGETS): run-%: ...
Matthias
31

Dies funktioniert natürlich in vielen Fällen nicht, aber wenn Ihr Makefilevon CMake erstellt wurde, können Sie es möglicherweise ausführen 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
Timmmm
quelle
Haben Sie eine Option, die Sie in Ihrer CMakeList aktivieren können, um dies zu erreichen? Ich habe ein von CMake generiertes Makefile erhalten und habe kein Pseudo-Hilfeziel zur Verfügung
Xavier T.
Nee. Zumindest unter OSX mit einem aktuellen CMake (ich verwende tatsächlich Nightlies, aber ich glaube, als ich dies schrieb, habe ich 3.3 verwendet), laufen touch CMakeLists.txt && cmake . && make helpSie einfach und es sollte funktionieren. Ich kann nur vermuten, dass Sie einen alten cmake verwenden oder den Unix Makefiles-Generator nicht verwenden.
Timmmm
Ich verwende CMake 3.6.2 mit Unix-Generator unter Windows. Ich werde mich umsehen, um nach einer Erklärung zu suchen, weil es praktisch erscheint.
Xavier T.
26

Ich habe diese beiden Antworten kombiniert: https://stackoverflow.com/a/9524878/86967 und https://stackoverflow.com/a/7390874/86967 und einige Fluchtversuche durchgeführt, damit diese aus einem Makefile heraus verwendet werden können.

.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
kein Balken
quelle
10
Ich habe auch (kürzlich) festgestellt, dass die Tab-Vervollständigung unter Bash verfügbare Ziele auflistet.
Nobar
1
+1 für einen großartigen Ansatz, aber es könnten einige Verbesserungen vorgenommen werden: (a) Eine explizite Angabe sh -c "…"ist nicht erforderlich, da dies makestandardmäßig zum Aufrufen von Rezeptbefehlen verwendet wird. (b) der von Ihnen verwendete Befehl ist zu einfach, was zu falsch positiven Ergebnissen führt (wie Sie bemerken); (c) Wenn Sie dem Befehl ein Präfix voranstellen @, wird er vor der Ausführung nicht an stdout zurückgegeben, sodass er beim -sAufruf nicht verwendet werden muss.
mklement0
1
Es gibt ein viel einfacheres Make-Ziel, das Sie hinzufügen könnten: list: cat Makefile | grep "^ [Az]" | awk '{print $$ 1}' | sed "s /: // g | sort"
thamster
2
Der Cat / Sed-Ansatz schlägt auf mehreren Ebenen fehl. Es werden keine Variablen erweitert und es werden keine Ziele aufgelistet, die das Ergebnis des Einfügens anderer Dateien sind.
Troy Daniels
1
@ mklement0: Ich bevorzuge die Verwendung make -s(über einen Bash-Alias) anstelle des Präfixierens von Befehlen im Makefile mit @. Es gibt einige Fälle, in denen @dies nützlich sein kann, insbesondere als Präfix für echoBefehle (bei denen die Anzeige des Befehls redundant wäre), aber im Allgemeinen verwende ich ihn nicht gern. Auf diese Weise kann ich die "Rezepte" sehen, wenn ich muss (indem ich sie nicht benutze -s), aber normalerweise nicht. Hier ist die zugehörige Dokumentation: GNU Make Manual, 5.2 Recipe Echoing .
Nobar
14

Wenn Sie Bash Completion für makeinstalliert haben, definiert das Completion-Skript eine Funktion _make_target_extract_script. Diese Funktion soll ein sedSkript erstellen, mit dem die Ziele als Liste abgerufen werden können.

Verwenden Sie es so:

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

# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile
hek2mgl
quelle
3
Hilfreich, aber beachten Sie, dass nicht alle Plattformen über Skripte /etc/bash_completionund / oder Funktionen verfügen _make_target_extract_script- Sie scheinen Ubuntu> 12 zu verwenden. Wenn Sie /usr/share/bash-completion/completions/makestattdessen zielen , funktioniert Ihr Ansatz auf zusätzlichen Plattformen wie Fedora 20. Es gibt (ältere) Plattformen mit diesen Funktionen diese Datei, aber nicht die Funktion (zB Debian 7 und Ubuntu 12); Andere Plattformen wie OSX verfügen überhaupt nicht über eine Tab-Vervollständigung make. Vielleicht wäre es hilfreich, die eigentliche Funktionsdefinition zu veröffentlichen.
mklement0
1
Vielen Dank für Ihren Kommentar. Dies wird sehr geschätzt. Ja, ich habe dies auf Ubuntu 14.04 getestet
hek2mgl
11

Wie mklement0 hervorhebt , fehlt in GNU-make eine Funktion zum Auflisten aller Makefile-Ziele, und seine und andere Antworten bieten Möglichkeiten dazu.

Der ursprüngliche Beitrag erwähnt jedoch auch Rake , dessen Aufgabenwechsel etwas anderes bewirkt als nur die Auflistung aller Aufgaben in der Rake-Datei. Rake gibt Ihnen nur eine Liste von Aufgaben, denen Beschreibungen zugeordnet sind. Aufgaben ohne Beschreibung werden nicht aufgelistet . Dies gibt dem Autor die Möglichkeit, sowohl benutzerdefinierte Hilfebeschreibungen bereitzustellen als auch Hilfe für bestimmte Ziele wegzulassen.

Wenn Sie das Verhalten von Rake emulieren möchten, indem Sie Beschreibungen für jedes Ziel bereitstellen , gibt es eine einfache Technik, um dies zu tun: Betten Sie Beschreibungen in Kommentare für jedes Ziel ein, das aufgelistet werden soll.

Sie können die Beschreibung entweder neben das Ziel oder, wie so oft, neben eine PHONY-Spezifikation über dem Ziel setzen:

.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

Welches wird ergeben

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

...
help                Generate list of targets with descriptions

Ein kurzes Codebeispiel finden Sie auch in dieser Übersicht und auch hier .

Dies löst wiederum nicht das Problem, alle Ziele in einem Makefile aufzulisten. Wenn Sie beispielsweise ein großes Makefile haben, das möglicherweise generiert wurde oder von jemand anderem geschrieben wurde, und eine schnelle Möglichkeit zum Auflisten der Ziele wünschen, ohne es zu durchsuchen, hilft dies nicht.

Wenn Sie jedoch ein Makefile schreiben und eine Möglichkeit suchen, Hilfetext auf konsistente, selbstdokumentierende Weise zu generieren, kann diese Technik hilfreich sein.

jsp
quelle
Dies ist eine großartige Technik - nett und einfach, gibt aber auch Beschreibungen!
Brian Burns
Tolle Technik. Ich habe dies ein wenig geändert, um den echoBefehl als Befehlsbeschreibung zu verwenden ( stackoverflow.com/a/52059487/814145 ).
Penghe Geng
@PengheGeng Danke für den Beitrag. Ich möchte klarstellen, dass dies @echo "Target 1"nur ein Platzhalter und kein "Beschreibungsecho-Befehl" ist. Der generierte Hilfetext stammt nicht von den @echo. In einem echten Makefile echowürden diese durch einen Build-Befehl oder ähnliches ersetzt. Ich werde den Beitrag bearbeiten, um dies klarer zu machen.
jsp
4

Die Antwort von @ nobar zeigt hilfreich, wie Sie mithilfe der Tab-Vervollständigung die Ziele eines Makefiles auflisten .

  • Dies funktioniert hervorragend für Plattformen, die diese Funktionalität standardmäßig bereitstellen (z. B. Debian, Fedora ).

  • Auf anderen Plattformen (z. B. Ubuntu ) müssen Sie diese Funktionalität explizit laden , wie aus der Antwort von @ hek2mgl hervorgeht :

    • . /etc/bash_completion Installiert mehrere Funktionen zum Vervollständigen von Registerkarten, einschließlich der für make
    • Alternativ können Sie nur die Tab-Vervollständigung installieren für make:
      • . /usr/share/bash-completion/completions/make
  • Für Plattformen, die diese Funktionalität überhaupt nicht bieten , wie z. B. OSX , können Sie die folgenden Befehle (von hier angepasst ) verwenden, um sie zu implementieren:
_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
  • Hinweis: Dies ist nicht so ausgefeilt wie die mit Linux-Distributionen gelieferte Tab-Vervollständigungsfunktion: Insbesondere zielt sie immer auf das Makefile im aktuellen Verzeichnis ab , selbst wenn die Befehlszeile auf ein anderes Makefile mit abzielt -f <file>.
mklement0
quelle
4

Meine Lieblingsantwort darauf wurde von Chris Down bei Unix & Linux Stack Exchange veröffentlicht. Ich werde zitieren.

So erhält das Bash-Vervollständigungsmodul für makeseine Liste:

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

Es druckt eine durch Zeilenumbrüche getrennte Liste von Zielen ohne Paging aus.

Benutzer Brainstone schlägt Piping vor sort -u, um doppelte Einträge zu entfernen:

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

Quelle: Wie liste ich alle Ziele in make auf? (Unix & Linux SE)

März 2377
quelle
4

Ich konzentrierte mich auf eine einfache Syntax zur Beschreibung eines Make-Ziels und hatte eine saubere Ausgabe. Ich entschied mich für diesen Ansatz:

help:
    @grep -B1 -E "^[a-zA-Z0-9_-]+\:([^\=]|$$)" Makefile \
     | grep -v -- -- \
     | sed 'N;s/\n/###/' \
     | sed -n 's/^#: \(.*\)###\(.*\):.*/\2###\1/p' \
     | column -t  -s '###'


#: Starts the container stack
up: a b
  command

#: Pulls in new container images
pull: c d 
    another command

make-target-not-shown:

# this does not count as a description, so leaving
# your implementation comments alone, e.g TODOs
also-not-shown:

Wenn Sie also das Obige als Makefile behandeln und es ausführen, erhalten Sie so etwas wie

> make help
up          Starts the container stack
pull        Pulls in new container images

Erläuterung zur Befehlskette:

Richard Kiefer
quelle
Sehr schöne Lösung. Ich benutze dies seit einigen Jahren: awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort mit dem ##vor dem Kommentar in der gleichen Zeile wie das Ziel. Aber ich denke, Ihre Lösung ermöglicht vor der Lesbarkeit.
Thoroc
Ein Makefile, das aus den ersten beiden Zeilen besteht, meldet sich grep: parentheses not balancedauf meinem OSX 10.15-Computer.
Malcolm Crum
@ Crummy sorry, mein Fehler. Vielen Dank für den Hinweis. Behoben. make erfordert das Entkommen von Dollarzeichen, die keine Variablennamen starten sollen.
Richard Kiefer
Achtung, StackOverflow konvertiert Tabulatoren in Leerzeichen, wenn die obigen Codeabschnitte angezeigt werden. Für Makefiles sind jedoch Tabulatoren erforderlich. Sie können den Beitrag bearbeiten und dann die Abschnitte kopieren, sodass die Registerkarten beibehalten werden.
Richard Kiefer
2

Viele praktikable Lösungen hier, aber wie ich gerne sage: "Wenn es sich lohnt, es einmal zu tun, lohnt es sich, es noch einmal zu tun." Ich habe den zu verwendenden Vorschlag (tab) (tab) positiv bewertet, aber wie einige angemerkt haben, haben Sie möglicherweise keine Abschlussunterstützung, oder wenn Sie viele Include-Dateien haben, möchten Sie möglicherweise einen einfacheren Weg, um zu wissen, wo ein Ziel definiert ist.

Ich habe das Folgende nicht mit Untermarken getestet ... Ich denke, es würde nicht funktionieren. Wie wir wissen, wird rekursiv als schädlich angesehen.

.PHONY: list ls
ls list :
    @# search all include files for targets.
    @# ... excluding special targets, and output dynamic rule definitions unresolved.
    @for inc in $(MAKEFILE_LIST); do \
    echo ' =' $$inc '= '; \
    grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
    cut -f 1 | sort | sed 's/.*/  &/' | sed -n 's/:.*$$//p' | \
    tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done

# to get around escaping limitations:
open_paren := \(
close_paren := \)

Was ich mag, weil:

  • Listen Sie die Ziele nach Include-Datei auf.
  • Ausgabe roher dynamischer Zieldefinitionen (ersetzt variable Begrenzer durch Modulo)
  • Geben Sie jedes Ziel in einer neuen Zeile aus
  • scheint klarer (subjektive Meinung)

Erläuterung:

  • foreach-Datei in der MAKEFILE_LIST
  • Geben Sie den Namen der Datei aus
  • grep-Zeilen mit einem Doppelpunkt, die nicht eingerückt sind, keine Kommentare enthalten und nicht mit einem Punkt beginnen
  • Sofortige Zuweisungsausdrücke ausschließen (: =)
  • Ausschneiden, Sortieren, Einrücken und Zerhacken von Regelabhängigkeiten (nach Doppelpunkt)
  • Munge variable Trennzeichen, um eine Erweiterung zu verhindern

Beispielausgabe:

 = Makefile = 
  includes
  ls list
 = util/kiss/snapshots.mk = 
  rotate-db-snapshots
  rotate-file-snapshots
  snap-db
  snap-files
  snapshot
 = util/kiss/main.mk = 
  dirs
  install
   %MK_DIR_PREFIX%env-config.php
   %MK_DIR_PREFIX%../srdb
ginkgoMZD
quelle
1

Dieser war für mich hilfreich, weil ich die Build-Ziele sehen wollte, die vom make-Ziel benötigt werden (und deren Abhängigkeiten). Ich weiß, dass Make-Ziele nicht mit einem "." Beginnen können. Charakter. Ich weiß nicht, welche Sprachen unterstützt werden, deshalb habe ich mich für die Klammerausdrücke von egrep entschieden.

cat Makefile | egrep "^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$"
Seanlum
quelle
1

Das ist alles andere als sauber, hat aber den Job für mich gemacht.

make -p 2&>/dev/null | grep -A 100000 "# Files" | grep -v "^$" | grep -v "^\(\s\|#\|\.\)" | grep -v "Makefile:" | cut -d ":" -f 1

Ich benutze make -pdas Dumps die interne Datenbank, Graben stderr, benutze eine schnelle und schmutzigegrep -A 100000 , um den Boden der Ausgabe zu halten. Dann bereinige ich die Ausgabe mit ein paar grep -vund benutze schließlich, um cutzu bekommen, was vor dem Doppelpunkt ist, nämlich die Ziele.

Dies reicht für meine Hilfsskripte auf den meisten meiner Makefiles.

BEARBEITEN: hinzugefügt, grep -v Makefiledass dies eine interne Regel ist

Lisael
quelle
1

Dies ist eine Änderung der sehr hilfreichen Antwort von jsp ( https://stackoverflow.com/a/45843594/814145 ). Ich mag die Idee, nicht nur eine Liste von Zielen zu erhalten, sondern auch deren Beschreibungen. Das Makefile von jsp fügt die Beschreibung als Kommentar ein, den ich oft gefunden habe und der im Befehl description echo des Ziels wiederholt wird. Also extrahiere ich stattdessen die Beschreibung aus dem Echo-Befehl für jedes Ziel.

Beispiel Makefile:

.PHONY: all
all: build
        : "same as 'make build'"

.PHONY: build
build:
        @echo "Build the project"

.PHONY: clean
clean:
        @echo "Clean the project"

.PHONY: help
help:
        @echo -n "Common make targets"
        @echo ":"
        @cat Makefile | sed -n '/^\.PHONY: / h; /\(^\t@*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/    make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20

Ausgabe von make help:

$ make help
Common make targets:
    make all        same as 'make build'
    make build      Build the project
    make clean      Clean the project
    make help       Common make targets

Anmerkungen:

  • Wie bei der Antwort von jsp werden möglicherweise nur PHONY-Ziele aufgelistet, die für Ihren Fall möglicherweise funktionieren oder nicht
  • Außerdem werden nur die PHONY-Ziele aufgelistet, die einen echooder :-Befehl als ersten Befehl des Rezepts haben. :bedeutet "nichts tun". Ich benutze es hier für jene Ziele, für die kein Echo benötigt wird, wie zall obige Ziel.
  • Es gibt einen zusätzlichen Trick für das helpZiel, das ":" in die make helpAusgabe einzufügen.
Penghe Geng
quelle
0

Noch eine zusätzliche Antwort auf oben.

unter MacOSX nur mit cat und awk am Terminal getestet

cat Makefile | awk '!/SHELL/ && /^[A-z]/ {print $1}' | awk '{print substr($0, 1, length($0)-1)}'

wird die make-Datei wie folgt ausgeben:

Ziel1

target2

target3

Im Makefile sollte es dieselbe Anweisung sein. Stellen Sie sicher, dass Sie die Variablen mit der Variablen $$ anstelle der Variablen $ maskieren.

Erläuterung

Katze - spuckt den Inhalt aus

| - Pipe analysiert die Ausgabe auf das nächste awk

awk - führt Regex ohne "Shell" aus und akzeptiert nur "Az" -Zeilen. Anschließend wird die erste Spalte von $ 1 gedruckt

awk - entfernt erneut das letzte Zeichen ":" aus der Liste

Dies ist eine grobe Ausgabe und Sie können mit nur AWK mehr funky Sachen machen. Versuchen Sie, sed zu vermeiden, da es in BSD-Varianten nicht so konsistent ist, dh einige funktionieren unter * nix, scheitern jedoch unter BSDs wie MacOSX.

Mehr

Sie sollten diese in der Lage sein add (mit Änderungen) in eine Datei für make , auf den Standard Bash-Completion - Ordner /usr/local/etc/bash-completion.d/ Bedeutung , wenn Sie „make tab tab “ .. es wird füllen Sie bitte den Ziele basierend auf dem Einzeilenskript.

Jimmy MG Lim
quelle
Sie können auch make -qp anstelle von cat verwenden. so wird es make -qp | awk '/: / &&! /: = / && / ^ [Az] / &&! / PATH / &&! / DISPLAY / &&! / TERM_SESSION / &&! / USER_TEXT_ENCODING / &&! / Makefile / {print substr ($ 0, 1 , Länge ($ 0) -1) | "sort -u"} '
Jimmy MG Lim
0

Normalerweise mache ich:

grep install_targets Makefile

Es würde mit so etwas zurückkommen wie:

install_targets = install-xxx1 install-xxx2 ... etc

ich hoffe das hilft

Heider Sati
quelle
0

Für ein Bash-Skript

Hier ist eine sehr einfache Möglichkeit, dies zu tun bash- basierend auf dem obigen Kommentar von @ cibercitizen1 :

grep : Makefile | awk -F: '/^[^.]/ {print $1;}'

Siehe auch die maßgeblichere Antwort von @ Marc.2377, in der angegeben ist, wie das Bash-Vervollständigungsmodul dies maketut.

jvriesem
quelle
-4

Ich bin mir nicht sicher, warum die vorherige Antwort so kompliziert war:

list:
    cat Makefile | grep "^[A-z]" | awk '{print $$1}' | sed "s/://g" 
Thamster
quelle
8
Die vorherige Antwort ist so kompliziert, weil sie alle Szenarien abdeckt, die Ihre Antwort NICHT abdeckt: (a) Einbeziehung von Zielen, die über Variablen definiert sind (z. B. $(SHELLS): ...), (b) Einbeziehung von Zielen, die mit einer Ziffer beginnen, (c) Nicht- Einbeziehung von Variablendefinitionen , (d) Ausrichtung auf das richtige Makefile, wenn dies makemit einem expliziten Makefile-Pfad angegeben wurde. (a) ist das entscheidende Manko: Selbst wenn Sie das richtige Makefile zuverlässig ausgewählt haben , funktioniert das Parsen der Rohdatei im allgemeinen Fall aufgrund fehlender variabler Erweiterung nicht.
mklement0
6
Abgesehen davon ist es kompliziert: Ihr Befehl kann wie folgt vereinfacht werden - aber der Hauptpunkt ist, dass er nicht robust genug ist : awk -F: '/^[A-z]/ {print $$1}' Makefile. Schließlich ein weitgehend akademischer Punkt: Verwenden von [A-z]anstatt [:alpha:]bedeutet, dass Sie Ziele verfehlen, die mit einem fremden Charakter beginnen, wie z á.
mklement0
@ mklement0 Ihr erster awk-Befehl funktioniert gut und ist der bisher einfachste, obwohl die Verwendung von [: alpha:] ihn aus irgendeinem Grund zu beschädigen scheint - er verfehlt einige Ziele in einer Testdatei.
Brian Burns
@ bburns.km: Mein schlechtes: Ich hätte eher sagen sollen [[:alpha:]]als [:alpha:]( [:alpha:]repräsentiert den länderspezifischen Satz von Buchstaben innerhalb einer Zeichenklasse ( [...]), daher die effektive Notwendigkeit für double [[ / ]].
mklement0
4
Warum ist diese Antwort so kompliziert? Sie schaffen es, einige der nutzlosen Sünden in diesem kurzen Ausschnitt zu sammeln . awk -F: '/^[A-Za-z]/ { print $$1 }' Makefileverwendet einen einzelnen Prozess und hoffentlich einen korrekteren regulären Ausdruck (obwohl Sie natürlich auch Ziele mit Unterstrichen, Zahlen usw. haben könnten, wie in früheren Kommentaren erwähnt).
Tripleee