makefile esegue un altro target


123

Ho un makefile strutturato in questo modo:

all : 
    compile executable

clean :
    rm -f *.o $(EXEC)

Mi sono reso conto che stavo eseguendo costantemente "make clean" seguito da "clear" nel mio terminale prima di eseguire "make all". Mi piace avere un terminale pulito prima di provare a setacciare i cattivi errori di compilazione C ++. Quindi ho provato ad aggiungere un terzo obiettivo:

fresh :
    rm -f *.o $(EXEC)
    clear
    make all

Funziona, tuttavia esegue una seconda istanza di make (credo). Esiste un modo giusto per ottenere la stessa funzionalità senza eseguire una seconda istanza di make?

Risposte:


172

In realtà hai ragione: esegue un'altra istanza di make. Una possibile soluzione sarebbe:

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : clean clearscr all

clearscr:
    clear

Chiamando make freshottieni prima il cleantarget, poi il clearscreenquale viene eseguito cleare infine allchi fa il lavoro.

MODIFICA 4 agosto

Cosa succede nel caso di build parallele con l' -jopzione make ? C'è un modo per sistemare l'ordine. Dal manuale make, sezione 4.2:

Occasionalmente, tuttavia, si ha una situazione in cui si desidera imporre un ordine specifico alle regole da invocare senza forzare l'aggiornamento del target se viene eseguita una di queste regole. In tal caso, si desidera definire i prerequisiti di solo ordine. I prerequisiti di solo ordine possono essere specificati inserendo un simbolo pipe (|) nell'elenco dei prerequisiti: tutti i prerequisiti a sinistra del simbolo pipe sono normali; eventuali prerequisiti a destra sono di solo ordine: obiettivi: prerequisiti normali | order-only-prerequisiti

La sezione dei normali prerequisiti può ovviamente essere vuota. Inoltre, puoi comunque dichiarare più righe di prerequisiti per lo stesso target: vengono aggiunte in modo appropriato. Nota che se dichiari lo stesso file come prerequisito sia normale che di solo ordine, il prerequisito normale ha la precedenza (poiché sono un superinsieme rigoroso del comportamento di un prerequisito di solo ordine).

Quindi il makefile diventa

.PHONY : clearscr fresh clean all

all :
    compile executable

clean :
    rm -f *.o $(EXEC)

fresh : | clean clearscr all

clearscr:
    clear

MODIFICA 5 dicembre

Non è un grosso problema eseguire più di un'istanza di makefile poiché ogni comando all'interno dell'attività sarà comunque una sotto-shell . Ma puoi avere metodi riutilizzabili usando la funzione call .

log_success = (echo "\x1B[32m>> $1\x1B[39m")
log_error = (>&2 echo "\x1B[31m>> $1\x1B[39m" && exit 1)

install:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  command1  # this line will be a subshell
  command2  # this line will be another subshell
  @command3  # Use `@` to hide the command line
  $(call log_error, "It works, yey!")

uninstall:
  @[ "$(AWS_PROFILE)" ] || $(call log_error, "AWS_PROFILE not set!")
  ....
  $(call log_error, "Nuked!")

6
@ sas4740: in pratica tutto ciò che segue .PHONY : viene trattato come una parola chiave che viene sempre eseguita, mentre i target non fasulli sono intesi come file.
Dacav

i "prerequisiti di solo ordine" sono condizionali? per il target t2 voglio prima fare t0, poi solo se t0 riesce a eseguire t1, e solo se entrambi riescono a eseguire qualche attività in t3
fantastory

1
@fantastory, no, penso che siano indipendenti. t2dipenderà da t0, t1e t3. Se necessario, inserire t3come richiesto da t2, t1come richiesto da t3e t0come richiesto da t1. Ciò significa 3 regole diverse. Tuttavia, dovresti verificarlo. Non ne sono sicuro al 100%.
Dacav

3
I "prerequisiti di solo ordine" sono indipendenti
fantastico

2
Non vedo dov'è la garanzia che "pulito" funzioni prima di "tutto"? Il fatto che tu li metta proprio da | non li fa eseguire in ordine. Dipendenza solo ordine significa che l'obiettivo non è necessariamente aggiornato dopo tale operazione. Non ha nulla a che fare con l'ordinamento degli elementi dipendenti ... o?
CygnusX1

6

Se hai rimosso la make alllinea dal tuo target "fresco":

fresh :
    rm -f *.o $(EXEC)
    clear

Potresti semplicemente eseguire il comando make fresh all, che verrà eseguito come make fresh; make all.

Alcuni potrebbero considerarlo come una seconda istanza di make, ma certamente non è una sottoistanza di make (un make all'interno di un make), che è ciò in cui il tuo tentativo sembrava aver prodotto.

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.