Mi risulta errato il modo in cui i prerequisiti di ordine-ordine funzionano?
Sì, questo è quello che sembra.
Il nome "solo ordine" in un po 'di confusione. I prerequisiti dietro lo |
sono chiamati "prerequisiti di solo ordine" non perché modificano l'ordine dell'esecuzione della ricetta all'interno dell'elenco di prerequisiti per un singolo target, ma perché il loro unico scopo è avere determinati obiettivi creati prima di altri, come un bootstrap. Come spiegato correttamente dall'utente bobbogo di seguito (- grazie per la correzione): se make
decide di ricostruire un prerequisito di un obiettivo, eseguirà la ricetta per tale prerequisito. Ora, per un normale prerequisito questo aggiornamento implica che il target non è aggiornato e che make
dovrà eseguire la ricetta del target. Per un prerequisito di solo ordine, d'altra parte, make
non contrassegna il target come se avesse bisogno di un aggiornamento.
Ad esempio, vedere la sezione Types of Prerequisites per un caso di utilizzo in cui è necessario creare una directory prima che vengano creati gli oggetti in tale directory.
Prendete questo esempio makefile
:
a: b
touch a
b: c
touch b
c:
touch c
x: | y
touch x
y: | z
touch y
z:
touch z
Come si può vedere, b
e c
sono normali requisiti di a
e b
, mentre y
e z
sono dell'ordine di sola prerequisiti di x
e y
. A partire da una tabula rasa, hanno lo stesso aspetto:
:~$ make a
touch c
touch b
touch a
:~$ make x
touch z
touch y
touch x
:~$ make a
make: `a' is up to date.
:~$ make x
make: `x' is up to date.
Tuttavia, se ora manualmente "aggiornamento" i presupposti alla fine della catena (c
e z
), vediamo la differenza:
:~$ touch c
:~$ make a
touch b
touch a
:~$ touch z
:~$ make x
make: `x' is up to date.
Questo mostra come i prerequisiti di solo ordine esistenti non invalidano alcun target, indipendentemente dalla data e ora. Eliminare il target ordine solo si traduca nella ricostruzione però (ma solo la ricostruzione di quel file mancante):
:~$ rm c
:~$ make a
touch c
touch b
touch a
:~$ rm z
:~$ make x
touch z
Dopo aver detto questo, il modo corretto per modificare l'ordine in cui vengono eseguite le vostre ricette è correggendo le dipendenze tra gli obiettivi.Ad esempio, se si desidera mefirst
da costruire prima di a
, allora avete bisogno di fare mefirst
un prerequisito per a
, come in
a: mefirst
@echo a
Non è possibile dare l'intera soluzione alla tua domanda in quanto non è stato descrivere in dettaglio in quale ordine ti aspetti che le ricette vengano eseguite.
c'è una scorciatoia per la tua risposta, che non è la soluzione, ma ancora interessante sapere. Sebbene non documentato, sembra che i prerequisiti di un singolo target vengano elaborati nell'ordine in cui appaiono. Il segno |
non lo cambia. Nel tuo caso semplice, è possibile usufruire di quella di raggiungere l'uscita che si sta cercando:
normaltarget: mefirst2 normaltarget2
@echo "normaltarget done"
e
helloworld: mefirst normaltarget
@echo "helloworld done"
Tuttavia, come sottolineato da soli, questa "soluzione" si rompe come appena il flag -j
viene utilizzato per eseguire ricette in parallelo. Inoltre, come sottolineato dall'utente bobbogo, affidarsi a questo meccanismo di ordinamento è una cattiva pratica. L'introduzione di nuove dipendenze può interferire con l'ordine. Quindi non fatelo :-)
Grazie per il chiarimento Reinier. L'ho provato prima, tuttavia non funziona quando si usa -j flag con un pesante parallelismo. Il prerequisito "myfirst" verrà eseguito allo stesso tempo di quanto segue, poiché è tutto parallelo e tenta di fare tutti i prerequisiti. –
In tal caso, se davvero hai bisogno che x sia (ri) fatto prima di y anche nel caso parallelo, allora devi rendere x un prerequisito di y stesso, invece di metterli entrambi sulla stessa linea. Questo è esattamente ciò a cui si riferisce la lista dei prerequisiti: indicare quale target dipende da quale (e quindi quale target deve essere (ri) fatto per primo). Tuttavia, la tua domanda non è sufficientemente dettagliata da fornire una soluzione esatta per il tuo caso, dal momento che non è chiaro quali siano esattamente le dipendenze dei diversi target. Ci sono molti modi per raggiungere il tuo risultato. –
Siamo spiacenti, ma questa risposta è ** sbagliata ** in una serie di aspetti importanti. Come sottolinea @George, l'ordine di costruzione è _non_ da sinistra a destra. Se il tuo makefile si basa mai su questo, allora è rotto. La correzione suggerita sopra è errata. Inoltre, i prerequisiti dopo '|' sono costruiti nel modo completamente normale. Se non sono aggiornati, verrà eseguita la loro ricetta. La differenza cruciale è che dopo tale aggiornamento, _make_ non proseguirà per eseguire la ricetta per il target originale. Questo è in netto contrasto con i prequisiti ordinari, se questi dovessero essere aggiornati, il che implica che l'obiettivo non è aggiornato. – bobbogo