Come si ottiene l'elenco di target in un makefile?


202

Ho usato un po 'di rake (un programma Ruby make) e ha un'opzione per ottenere un elenco di tutti gli obiettivi disponibili, ad es.

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

ma non sembra esserci alcuna opzione per farlo in GNU make.

Apparentemente il codice è quasi arrivato per questo, a partire dal 2007 - http://www.mail-archive.com/help-make@gnu.org/msg06434.html .

Ad ogni modo, ho fatto un piccolo trucco per estrarre gli obiettivi da un makefile, che puoi includere in un makefile.

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

Ti darà un elenco degli obiettivi definiti. È solo un inizio: non filtra le dipendenze, per esempio.

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

2
Leggo rapidamente le risposte, che sono interessanti, ma per quanto mi riguarda preferisco mantenerlo chiaro, semplice e portatile usando un alias (nel mio .bashrc): alias makefile-targets='grep "^[^#[:space:]].*:" Makefile' Molto spesso ho solo bisogno di esaminare il makefile corrente e il completamento bash si espande il mio alias.
RockyRoad,


4
E 'semplicemente troppo banale: grep : Makefile?
cibercitizen1,

Risposte:


130

Questo è un tentativo di migliorare il grande approccio di @ nobar come segue:

  • usa un comando più robusto per estrarre i nomi di destinazione, che si spera prevenga eventuali falsi positivi (e elimina anche il superfluo sh -c)
  • non indirizza invariabilmente il makefile nella directory corrente ; rispetta i makefile esplicitamente specificati con-f <file>
  • esclude obiettivi nascosti: per convenzione, si tratta di obiettivi il cui nome non inizia né con una lettera né con una cifra
  • accontenta un singolo obiettivo falso
  • antepone il comando con @per impedire che venga ripetuto prima dell'esecuzione

Curiosamente, GNU makenon ha funzionalità per elencare solo i nomi degli obiettivi definiti in un makefile. L' -popzione produce output che include tutti gli obiettivi, ma li seppellisce in molte altre informazioni.

Inserisci la seguente regola in un makefile per GNU makeper implementare un target chiamato listche elenca semplicemente tutti i nomi target in ordine alfabetico - cioè: 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 '^$@$$'

Importante : incollandolo, assicurati che l'ultima riga sia rientrata da esattamente 1 carattere di tabulazione effettivo. (gli spazi non funzionano) .

Si noti che l' ordinamento dell'elenco risultante di target è l'opzione migliore, poiché non ordinare non produce un utile ordinamento in quanto l'ordine in cui i target compaiono nel makefile non viene conservato.
Inoltre, i sotto-obiettivi di una regola che comprende più obiettivi sono invariabilmente prodotti separatamente e pertanto, a causa dell'ordinamento, di solito non compaiono uno accanto all'altro; ad esempio, una regola che inizia cona z: sarà non avere obiettivi ae zvengono riportati accanto all'altro in uscita, se ci sono ulteriori obiettivi.

Spiegazione della regola :

  • .PHONY: list
    • dichiara l'elenco target un target fasullo, ovvero uno che non fa riferimento a un file , che dovrebbe quindi essere invocato incondizionatamente alla sua ricetta
  • $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • Richiama di makenuovo per stampare e analizzare il database derivato dal makefile:
      • -p stampa il database
      • -Rr sopprime l'inclusione di regole e variabili integrate
      • -qverifica solo lo stato aggiornato di un target (senza rifare nulla), ma che da solo non impedisce l'esecuzione dei comandi di ricetta in tutti i casi; quindi:
      • -f $(lastword $(MAKEFILE_LIST))assicura che lo stesso makefile sia preso di mira come nell'invocazione originale, indipendentemente dal fatto che sia stato preso di mira in modo implicito o esplicito -f ....
        Avvertenza : questo si interromperà se il tuo makefile contiene includedirettive; per risolvere questo problema, definire la variabile THIS_FILE := $(lastword $(MAKEFILE_LIST)) prima di qualsiasi includedirettiva e utilizzare-f $(THIS_FILE) invece.
      • :è un obiettivo deliberatamente non valido che ha lo scopo di garantire che non vengano eseguiti comandi ; 2>/dev/nullsopprime il messaggio di errore risultante. Nota: ciò si basa comunque sulla -pstampa del database, come nel caso di GNU make 3.82. Purtroppo, GNU make non offre alcuna opzione diretta per stampare solo il database, senza eseguire anche l'attività predefinita (o data); se non hai bisogno di scegliere come target un Makefile specifico, puoi usare make -p -f/dev/null, come raccomandato nella manpagina.
  • -v RS=

    • Questo è un linguaggio strano che spezza l'input in blocchi di linee non vuote contigue.
  • /^# File/,/^# Finished Make data base/
    • Corrisponde all'intervallo di linee nell'output che contiene tutti i target (true a partire da GNU make 3.82) - limitando l'analisi a questo intervallo, non è necessario gestire falsi positivi da altre sezioni di output.
  • if ($$1 !~ "^[#.]")
    • Ignora selettivamente i blocchi:
      • # ... ignora i non target, i cui blocchi iniziano con # Not a target:
      • . ... ignora obiettivi speciali
    • Tutti gli altri blocchi dovrebbero iniziare con una riga contenente solo il nome di un target definito in modo esplicito seguito da :
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$' rimuove obiettivi indesiderati dall'output:
    • '^[^[:alnum:]]'... esclude obiettivi nascosti , che - per convenzione - sono obiettivi che non iniziano né con una lettera né con una cifra.
    • '^$@$$'... esclude il listbersaglio stesso

La corsa make listquindi stampa tutti i bersagli, ognuno sulla propria linea; puoi invece reindirizzare per xargscreare un elenco separato da spazi.


Questa è un'ottima risposta, tuttavia, come ottengo la descrizione per ogni attività? Attualmente, lo sto memorizzando come commento sopra la definizione dell'attività. Non sei sicuro che sia possibile includerlo nell'elenco in un modo simile come rake --tasksfa?
Piotr Kuczynski,

1
@PiotrKuczynski: domanda interessante, ma ti suggerisco di postarla come nuova domanda (indicando questa come riferimento).
mklement0

"Purtroppo, GNU make non offre alcuna opzione diretta per stampare solo il database." C'è -nun'opzione
Bulletmagnet

@Bulletmagnet: lo scopo -ndell'opzione è "Stampa i comandi che verrebbero eseguiti ..." - in altre parole: una funzione di esecuzione a secco. Inoltre non che il tuo preventivo manca l'italicization della parola solo : make -pda sola fa stampare il database, ma invariabilmente corre anche il compito di default ; il manuale raccomanda al grosso make -p -f/dev/nulldi evitarlo.
mklement0

1
Elencherà anche tutti gli obiettivi .PHONY, quindi assicurati di non averli.PHONY: *
tekumara,

189

Sotto Bash (almeno), questo può essere fatto automaticamente con il completamento della scheda:

make spacetabtab


1
Testato: bash --version = 4.2.45 (1)-release. make --version = 3.81.
nobar,

53
+1, ma nota che questa non è una funzione bash , ma dipende dalla tua piattaforma . Le piattaforme rientrano in tre categorie: quelle in cui questo completamento è installato per impostazione predefinita (ad esempio, Debian 7, Fedora 20), quelle in cui è possibile installarlo facoltativamente (ad esempio Ubuntu 14, con . /etc/bash_completion) e quelle che non lo supportano affatto (ad es. OSX 10.9)
mklement0

8
funziona su OS X 10.10 (non con bash ma con zsh).
Florian Oswald,

4
Ottimo consiglio ma necessita anche di bash-completionpacchetto. Trovato in Fedora, RHEL, Gentoo, ect.
NoelProf,

4
Questo non funziona con gli obiettivi di creazione programmati AFAICT, ad es$(RUN_TARGETS): run-%: ...
Matthias,

32

Questo ovviamente non funzionerà in molti casi, ma se il tuo è Makefilestato creato da CMake potresti essere in grado di eseguire 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

Hai qualche opzione da attivare nella tua CMakeList per ottenerlo? Ho ottenuto un makefile generato da CMake e non ho a disposizione lo pseudo aiuto target
Xavier T.

No. Su OSX almeno con un CMake recente (in realtà sto usando i nightly ma credo che quando ho scritto questo stavo usando 3.3), basta eseguire touch CMakeLists.txt && cmake . && make helpe dovrebbe funzionare. Posso solo supporre che tu stia usando un vecchio cmake o non usi il generatore di Unix Makefiles?
Timmmm

Sto usando CMake 3.6.2 con generatore unix su Windows. Scorrerò per cercare una spiegazione perché mi sembra utile.
Xavier T.

26

Ho combinato queste due risposte: https://stackoverflow.com/a/9524878/86967 e https://stackoverflow.com/a/7390874/86967 e sono riuscito a scappare in modo da poterlo utilizzare dall'interno di un 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

10
Ho anche (di recente) scoperto che il completamento della scheda in Bash elencherà gli obiettivi disponibili.
nobar

1
+1 per un ottimo approccio, ma potrebbero essere apportati alcuni miglioramenti: (a) specificare esplicitamente sh -c "…"non è necessario, perché è quello che makeper impostazione predefinita utilizza per richiamare i comandi di ricetta; (b) il comando che usi è troppo semplicistico, risultando in falsi positivi (come noti); (c) se si antepone il comando con @, non verrà ripetuto lo stdout prima dell'esecuzione, ovviando alla necessità di usare -ssu invocazione.
mklement0

1
c'è un target di make molto più semplice che potresti aggiungere: list: cat Makefile | grep "^ [Az]" | awk '{print $$ 1}' | sed "s /: // g | sort"
Thamster

2
L'approccio cat / sed fallisce su più livelli. Non espande le variabili e non è in grado di elencare le destinazioni risultanti dall'inclusione di altri file.
Troy Daniels,

1
@ mklement0: preferisco usare make -s(tramite un alias Bash) piuttosto che prefissare i comandi nel makefile con @. Ci sono alcuni casi in cui @può essere utile, in particolare come prefisso perecho comandi (in cui la visualizzazione del comando sarebbe ridondante), ma in generale non mi piace usarlo. In questo modo, posso vedere le "ricette" quando ne ho bisogno ( non usando -s), ma non in genere. Ecco la relativa documentazione: GNU Make Manual, 5.2 Echoing della ricetta .
nobar,

14

Se hai il completamento bash per makeinstallato, lo script di completamento definirà una funzione _make_target_extract_script. Questa funzione ha lo scopo di creare unsed script che può essere utilizzato per ottenere le destinazioni come un elenco.

Usalo in questo modo:

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

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

3
Utile, ma nota che non tutte le piattaforme hanno script /etc/bash_completione / o funzioni _make_target_extract_script: sembra che tu sia su Ubuntu> 12. Se /usr/share/bash-completion/completions/makeinvece scegli come target , il tuo approccio funzionerà su piattaforme aggiuntive, come Fedora 20. Ci sono piattaforme (più vecchie) che hanno questo file, ma non la funzione (es. Debian 7 e Ubuntu 12); altre piattaforme, come OSX, non prevedono affatto il completamento della scheda make. Forse pubblicare la definizione della funzione effettiva sarebbe utile.
mklement0

1
Grazie per il tuo commento. Questo è molto apprezzato Sì, l'ho provato su Ubuntu 14.04
hek2mgl,

11

Come sottolinea mklement0 , GNU-make manca una funzionalità per elencare tutti i target di Makefile, e la sua risposta e altri forniscono modi per farlo.

Tuttavia, il post originale menziona anche rake , il cui cambio di attività fa qualcosa di leggermente diverso rispetto al semplice elenco di tutte le attività nel rakefile. Rake ti fornirà solo un elenco di attività a cui sono associate descrizioni. Le attività senza descrizioni non verranno elencate . Ciò dà all'autore la possibilità sia di fornire descrizioni di aiuto personalizzate sia di omettere l'aiuto per determinati target.

Se vuoi emulare il comportamento di rake, dove fornisci descrizioni per ciascun obiettivo , esiste una tecnica semplice per farlo: incorporare le descrizioni nei commenti per ciascun obiettivo che si desidera elencare.

Puoi mettere la descrizione vicino al bersaglio o, come faccio spesso, accanto a una specifica PHONY sopra il bersaglio, in questo modo:

.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

Che produrrà

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

...
help                Generate list of targets with descriptions

Puoi anche trovare un esempio di codice breve in questa sintesi e qui anche .

Ancora una volta, questo non risolve il problema di elencare tutti gli obiettivi in ​​un Makefile. Ad esempio, se hai un grande Makefile che è stato forse generato o che qualcun altro ha scritto e vuoi un modo rapido per elencare i suoi obiettivi senza scavare attraverso di esso, questo non sarà di aiuto.

Tuttavia, se stai scrivendo un Makefile e desideri un modo per generare un testo di aiuto in modo coerente e autocompattante, questa tecnica può essere utile.


Questa è un'ottima tecnica, carina e semplice, ma fornisce anche descrizioni!
Brian Burns,

Grande tecnica. L'ho modificato un po 'per usare il echocomando come descrizione del comando ( stackoverflow.com/a/52059487/814145 ).
Penghe Geng,

@PengheGeng Grazie per il post. Voglio chiarire che @echo "Target 1"è solo un segnaposto e non un "comando di descrizione dell'eco". Il testo di aiuto generato non proviene da @echo"s". In un vero Makefile, questi echoverrebbero sostituiti da un comando build o qualcosa del genere. Modificherò il post per renderlo più chiaro.
jsp

5

La mia risposta preferita è stata pubblicata da Chris Down su Unix & Linux Stack Exchange. Citerò.

Ecco come il modulo di completamento bash makeottiene il suo elenco:

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

Stampa un elenco di destinazioni delimitato da nuova riga, senza paginazione.

L'utente Brainstone suggerisce di eseguire il piping sort -uper rimuovere voci duplicate:

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

Fonte: come elencare tutti i target in make? (Unix e Linux SE)


4

La risposta di @ nobar mostra come utilizzare il completamento della scheda per elencare gli obiettivi di un makefile .

  • Funziona benissimo per le piattaforme che forniscono questa funzionalità di default (es. Debian, Fedora ).

  • Su altre piattaforme (ad esempio Ubuntu ) è necessario caricare esplicitamente questa funzionalità, come implica la risposta di @ hek2mgl :

    • . /etc/bash_completion installa diverse funzioni di completamento delle schede, inclusa quella per make
    • In alternativa, per installare solo il completamento della scheda per make:
      • . /usr/share/bash-completion/completions/make
  • Per le piattaforme che non offrono affatto questa funzionalità , come OSX , è possibile eseguire i seguenti comandi (adattati da qui ) per implementarlo:
_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
  • Nota: non è sofisticato come la funzionalità di completamento della scheda fornita con le distribuzioni Linux: in particolare, indirizza invariabilmente il makefile nella directory corrente , anche se la riga di comando ha come target un makefile diverso -f <file>.

4

Concentrandomi su una sintassi semplice per descrivere un obiettivo di creazione e avendo un output pulito, ho scelto questo approccio:

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:

Quindi trattare quanto sopra come un Makefile ed eseguirlo ti dà qualcosa di simile

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

Spiegazione per la catena di comandi:


Soluzione molto bella. L'ho usato da alcuni anni: awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort con ##il commento precedente sulla stessa riga dell'obiettivo. Ma penso che la tua soluzione consenta una prima lettura.
giovedì

Un makefile composto dalle prime due righe riporta grep: parentheses not balancedsulla mia macchina OSX 10.15.
Malcolm Crum

@Crummy scusa, errore mio. Grazie per segnalarlo. Aggiustato. make richiede di sfuggire ai segni del dollaro che non dovrebbero iniziare nomi di variabili.
Richard Kiefer,

Attenzione, StackOverflow converte le schede in spazi quando si visualizzano le sezioni di codice sopra, ma i Makefile richiedono schede. È possibile modificare il post e quindi copiare le sezioni, in modo da mantenere le schede.
Richard Kiefer,

2

Molte soluzioni praticabili qui, ma come mi piace dire "se vale la pena farlo una volta, vale la pena farlo di nuovo". Ho votato a favore della richiesta (tab) (tab), ma come alcuni hanno notato, potresti non avere il supporto per il completamento o, se hai molti file include, potresti voler un modo più semplice per sapere dove è definito un target.

Non ho testato il sotto con sub-make ... Penso che non funzionerebbe. Come sappiamo, ricorsivo viene considerato dannoso.

.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 := \)

Che mi piace perché:

  • elenca i target in base al file include.
  • output definizioni target dinamiche non elaborate (sostituisce i delimitatori variabili con modulo)
  • output di ciascun target su una nuova riga
  • sembra più chiaro (opinione soggettiva)

Spiegazione:

  • foreach file in MAKEFILE_LIST
  • output il nome del file
  • linee grep contenenti due punti, che non sono rientrati, non commenti e non iniziano con un punto
  • escludi espressioni di assegnazione immediate (: =)
  • tagliare, ordinare, rientrare e tagliare le dipendenze delle regole (dopo i due punti)
  • delimitatori di variabili munge per impedire l'espansione

Uscita campione:

 = 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

1

Questo mi è stato utile perché volevo vedere gli obiettivi di costruzione richiesti (e le loro dipendenze) dall'obiettivo di creazione. So che fare obiettivi non può iniziare con un "." carattere. Non so quali lingue sono supportate, quindi sono andato con le espressioni di parentesi di egrep.

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

1

Questo è tutt'altro che pulito, ma ha fatto il lavoro, per me.

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

Uso make -pquel dump del database interno, ditch stderr, uso un veloce e sporco grep -A 100000per mantenere il fondo dell'output. Quindi pulisco l'output con un paio di grep -v, e infine usocut per ottenere ciò che precede i due punti, vale a dire, gli obiettivi.

Questo è abbastanza per i miei script di supporto sulla maggior parte dei miei Makefile.

EDIT: aggiunta grep -v Makefileche è una regola interna


1

Questa è una modifica alla risposta molto utile di jsp ( https://stackoverflow.com/a/45843594/814145 ). Mi piace l'idea di ottenere non solo un elenco di obiettivi, ma anche le loro descrizioni. Makefile di jsp inserisce la descrizione come commento, che ho trovato spesso verrà ripetuta nel comando echo della descrizione del target. Quindi, invece, estraggo la descrizione dal comando echo per ogni destinazione.

Makefile di esempio:

.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

Uscita di 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

Appunti:

  • Come nella risposta di jsp , possono essere elencati solo i target PHONY, che possono o meno funzionare nel tuo caso
  • Inoltre, elenca solo quei target PHONY che hanno un echoo: comando come primo comando della ricetta. :significa "non fare nulla". Lo uso qui per quegli obiettivi che non sono necessari echi, come l' allobiettivo sopra.
  • C'è un ulteriore trucco per il helptarget di aggiungere ":" make helpnell'output.

0

Ancora un'altra risposta sopra a sopra.

testato su MacOSX usando solo cat e awk sul terminale

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

produrrà il file make come di seguito:

target1

TARGET2

target3

nel Makefile, dovrebbe essere la stessa istruzione, assicurati di sfuggire alle variabili usando la variabile $$ anziché $.

Spiegazione

cat - sputa il contenuto

| - pipe analizza l'output al prossimo awk

awk - esegue regex escludendo "shell" e accettando solo le righe "Az", quindi stampa la prima colonna da $ 1

awk : rimuove di nuovo l'ultimo carattere ":" dall'elenco

questo è un risultato approssimativo e puoi fare cose più funky solo con AWK. Cerca di evitare sed perché non è così coerente nelle varianti di BSD, ad esempio alcuni funzionano su * nix ma falliscono su BSD come MacOSX.

Di Più

Dovresti essere in grado di aggiungere questo (con modifiche) a un file per make , nella cartella di completamento bash predefinita /usr/local/etc/bash-completion.d/ che significa quando "fai la scheda " ... completerà il obiettivi basati sulla sceneggiatura di una riga.


puoi anche usare make -qp piuttosto che cat. così diventerà make -qp | awk '/: / &&! /: = / && / ^ [Az] / &&! / PATH / &&! / DISPLAY / &&! / TERM_SESSION / &&! / USER_TEXT_ENCODING / &&! / Makefile / {stampa substr ($ 0, 1 , lunghezza ($ 0) -1) | "sort -u"} '
Jimmy MG Lim

0

Di solito faccio:

grep install_targets Makefile

Sarebbe tornato con qualcosa di simile:

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

Spero che aiuti


0

Per uno script Bash

Ecco un modo molto semplice per farlo in bash- basato sul commento di @ cibercitizen1 sopra :

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

Vedi anche la risposta più autorevole di @ Marc.2377, che spiega come lo fa il modulo di completamento Bash make.


-4

non so perché la risposta precedente fosse così complicata:

list:
    cat Makefile | grep "^[A-z]" | awk '{print $$1}' | sed "s/://g" 

8
La risposta precedente è così complicata, perché copre tutti gli scenari che la tua risposta NON copre: (a) inclusione di obiettivi definiti tramite variabili (ad esempio, $(SHELLS): ...), (b) inclusione di obiettivi che iniziano con una cifra, (c) non- inclusione di definizioni variabili , (d) indirizzare il makefile corretto se è makestato specificato con un percorso di makefile esplicito. (a) è il difetto cruciale: anche se hai mirato in modo affidabile il giusto makefile, l'analisi del file raw non funzionerà nel caso generale, a causa della mancanza di espansione variabile.
mklement0

6
Per inciso, re complicato: il vostro comando può essere semplificata al seguente - ma il punto principale è che non è abbastanza robusto : awk -F: '/^[A-z]/ {print $$1}' Makefile. Infine, un punto in gran parte accademico: usare [A-z]piuttosto che [:alpha:]significa che ti mancheranno obiettivi che iniziano con un personaggio straniero come á.
mklement0

@ mklement0 il tuo primo comando awk funziona bene, ed è il più semplice finora, sebbene l'uso di [: alpha:] sembra infrangerlo per qualche motivo - manca alcuni target in un file di test.
Brian Burns,

@ bburns.km: Il mio male: avrei dovuto dire [[:alpha:]]piuttosto che [:alpha:]( [:alpha:]rappresenta l'insieme di lettere consapevoli del locale all'interno di una classe di caratteri ( [...]), quindi l'effettiva necessità di double [[ / ]].
mklement0

4
Perché questa risposta è così complicata? Riesci a raccogliere molti dei peccati inutili in questo breve frammento. awk -F: '/^[A-Za-z]/ { print $$1 }' Makefileusa un singolo processo e, si spera, un'espressione regolare più corretta (anche se ovviamente potresti avere obiettivi con caratteri di sottolineatura, numeri ecc., come notato nei commenti precedenti).
Tripleee,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.