makefile Tutorial
Iniziare con makefile
Ricerca…
Osservazioni
Un makefile è un file di testo che controlla il funzionamento del programma make
. Il programma make
viene in genere utilizzato per gestire la creazione di programmi dai relativi file di origine, ma può essere generalmente utilizzato per gestire qualsiasi processo in cui i file (o le destinazioni ) devono essere rigenerati dopo che altri file (o prerequisiti ) sono stati modificati. Il makefile descrive la relazione tra obiettivi e prerequisiti e specifica anche i comandi necessari per aggiornare il target quando uno o più dei prerequisiti sono stati modificati. L'unico modo che make
determina "fuori data-ness" è confrontando il tempo di modifica dei file di destinazione e dei loro presupposti.
I makefile sono in qualche modo unici in alcuni modi che inizialmente possono confondere.
Innanzitutto, un makefile consiste in due linguaggi di programmazione completamente diversi nello stesso file. La maggior parte del file è scritto in un linguaggio che make
in grado di capire: questo offre assegnamento di variabile e di espansione, alcune funzionalità del preprocessore (inclusi altri file, l'analisi condizionale sezioni del file, ecc), così come la definizione di obiettivi e la loro prerequisiti. Inoltre, a ciascun target può essere associata una ricetta che specifica quali comandi devono essere invocati per far sì che l'obiettivo venga aggiornato. La ricetta è scritta come script di shell (POSIX sh di default). Il programma make
non analizza questo script: esegue una shell e passa lo script alla shell da eseguire. Il fatto che le ricette non vengano analizzate da make
, ma gestite da un processo shell separato, è fondamentale per comprendere i makefile.
In secondo luogo, un makefile non è un linguaggio procedurale come uno script: poiché make
pars del makefile costruisce internamente un grafo diretto dove gli obiettivi sono i nodi del grafico e le relazioni dei prerequisiti sono i bordi. Solo dopo che tutti i makefile sono stati completamente analizzati e il grafico è completo sarà make
scegliere un nodo (target) e tentare di portarlo fino ad oggi. Al fine di garantire che un obiettivo sia aggiornato, deve prima assicurarsi che tutti i prerequisiti di quel target siano aggiornati e così via in modo ricorsivo.
Versioni
Nome | Conosciuto anche come | Versione iniziale | Versione | Data di rilascio |
---|---|---|---|---|
Fare POSIX | 1992 | IEEE Std 1003.1-2008, edizione 2016 | 2016/09/30 | |
NetBSD | bmake | 1988 | 20160926 | 2016/09/26 |
Fare GNU | gmake | 1988 | 4.2.1 | 2016/06/10 |
Marca SunPro | dmake | 2006 | 2015/07/13 | |
MSVS nmake | 2003 | 2015p3 | 2016/06/27 |
Makefile di base
Prendi in considerazione la possibilità di scrivere un "Ciao mondo!" programma in c. Diciamo che il nostro codice sorgente è in un file chiamato source.c, ora per eseguire il nostro programma è necessario compilarlo, tipicamente su Linux (usando gcc) avremmo bisogno di digitare $> gcc source.c -o output
dove output è il nome dell'eseguibile da generare. Per un programma di base questo funziona bene ma, man mano che i programmi diventano più complessi, il nostro comando di compilazione può anche diventare più complesso. È qui che entra in gioco un Makefile , i makefile ci permettono di scrivere un insieme piuttosto complesso di regole su come compilare un programma e poi semplicemente compilarlo digitando make sulla riga di comando. Ad esempio, ecco un possibile esempio di Makefile per l'esempio Hello hold qui sopra.
Makefile di base
Consente di creare un Makefile di base e salvarlo nel nostro sistema nella stessa directory del nostro codice sorgente denominato Makefile . Nota che questo file deve essere chiamato Makefile, tuttavia il capitol M è opzionale. Detto questo, è relativamente normale usare un capitol M.
output: source.c
gcc source.c -o output
Si noti che esiste esattamente una scheda prima del comando gcc sulla seconda riga (questo è importante nei makefile). Una volta che questo Makefile viene scritto ogni volta che l'utente digita (nella stessa directory del Makefile) make controllerà se source.c è stato modificato (controlla il timestamp) se è stato modificato più recentemente dell'output che verrà eseguito la regola di compilazione nella riga seguente.
Variabili nei Makefile
A seconda del progetto, potresti voler introdurre alcune variabili nel tuo file make. Ecco un esempio di Makefile con variabili presenti.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Ora esploriamo cosa è successo qui. Nella prima riga abbiamo dichiarato una variabile denominata CFLAGS che contiene diversi flag comuni che potreste voler passare al compilatore, notate che è possibile memorizzare tutti i flag che volete in questa variabile. Quindi abbiamo la stessa linea di prima di fare make per controllare source.c per vedere se è stata modificata più recentemente dell'output, in tal caso esegue la regola di compilazione. La nostra regola di compilazione è per lo più la stessa di prima, ma è stata abbreviata usando le variabili, la variabile $<
è incorporata nel make (indicata come variabile automatica vedi https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ) e rappresenta sempre la fonte, quindi in questo caso source.c . $(CFLAGS)
è la nostra variabile che abbiamo definito prima, ma notiamo che dovevamo mettere la variabile tra parentesi con $ davanti come $(someVariable)
. Questa è la sintassi per dire a Make di espandere la variabile a ciò che hai digitato prima. Infine abbiamo il simbolo $ @, ancora una volta questa è una variabile incorporata nel make, e rappresenta semplicemente l'obiettivo del passo della compilazione, quindi in questo caso sta per output .
Pulito
Make clean è un altro concetto utile per imparare a creare file. Consente di modificare il Makefile dall'alto
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Come puoi vedere, abbiamo aggiunto semplicemente un'altra regola al nostro Makefile e una variabile aggiuntiva che contiene tutti i nostri obiettivi. Questa è una regola piuttosto comune da avere nei makefile in quanto ti permette di rimuovere rapidamente tutti i binari che hai prodotto semplicemente digitando $> make clean
. Digitando make clean si dice al programma make di eseguire la regola clean e quindi make eseguirà il comando rm per eliminare tutti i target.
Spero che questa breve panoramica sull'uso di make ti aiuti a velocizzare il tuo flusso di lavoro, i Makefile possono diventare molto complessi, ma con queste idee dovresti essere in grado di iniziare a usare make e avere una migliore comprensione di ciò che accade in altri Makefile dei programmatori. Per ulteriori informazioni sull'utilizzo di fare una risorsa eccellente è https://www.gnu.org/software/make/manual/ .
Definizione delle regole
Avvio veloce
Una regola descrive quando e come vengono creati determinati file ( obiettivi della regola). Può anche servire per aggiornare un file di destinazione se uno qualsiasi dei file richiesti per la sua creazione (i prerequisiti della destinazione) sono più recenti della destinazione.
Le regole seguono la seguente sintassi: (nota che i comandi che seguono una regola sono rientrati da una scheda )
targets: prerequisites
<commands>
dove obiettivi e prerequisiti sono nomi di file o nomi riservati speciali e i comandi (se presenti) vengono eseguiti da una shell per creare / ricostruire obiettivi non aggiornati.
Per eseguire una regola si può semplicemente eseguire il comando make
nel terminale dalla stessa directory in cui risiede il Makefile . Eseguendo make
senza specificare il target, verrà eseguita la prima regola definita nel Makefile . Per convenzione, la prima regola nel Makefile viene spesso chiamata all o default , elencando comunemente tutti i target di build validi come prerequisiti.
make
esegue solo la regola se il target non è aggiornato, ovvero non esiste o il suo tempo di modifica è precedente a uno dei suoi prerequisiti. Se l'elenco dei prerequisiti è vuoto, la regola verrà eseguita solo quando viene invocato per la prima volta per creare i target. Tuttavia, quando la regola non crea un file e la destinazione è una variabile fittizia, la regola verrà sempre eseguita.
Regole del modello
Le regole del modello vengono utilizzate per specificare più destinazioni e costruire nomi di prerequisiti dai nomi di destinazione. Sono più generali e più potenti rispetto alle regole ordinarie in quanto ogni obiettivo può avere i suoi prerequisiti. Nelle regole del modello, una relazione tra un obiettivo e un prerequisito è costruita in base a prefissi che includono nomi di percorso e suffissi o entrambi.
Immaginate che vogliamo costruire il target foo.o
e bar.o
, mediante la compilazione di script C, foo.c
e bar.c
, rispettivamente. Questo potrebbe essere fatto usando le regole ordinarie qui sotto:
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
dove la variabile automatica $<
è il nome del primo prerequisito e $@
il nome del target ( qui è possibile trovare un elenco completo di variabili automatiche).
Tuttavia, poiché gli obiettivi condividono lo stesso suffisso, le due regole precedenti possono ora essere sostituite dalla seguente regola del modello:
%.o: %.c
cc -c $< -o $@
Regole implicite
Regole implicite dicono make
come utilizzare i metodi usuali per costruire alcuni tipi di file di destinazione, che vengono utilizzati molto spesso. make
usa il nome del file di destinazione per determinare quale regola implicita da richiamare.
L'esempio di regola del modello che abbiamo visto nella sezione precedente, in realtà non ha bisogno di essere dichiarato in un Makefile in quanto make
ha una regola implicita per la compilazione C. Quindi, nella seguente regola, i prerequisiti foo.o
e bar.o
saranno costruiti usando la regola implicita per la compilazione C, prima di costruire foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Un catalogo di regole implicite e le variabili utilizzate da loro può essere trovato qui .
regola generica per gzip un file
se una directory contiene 2 file:
$ ls
makefile
example.txt
e makefile
contengono il seguente testo
%.gz: %
gzip $<
quindi puoi ottenere example.txt.gz
digitando la shell
$ make -f makefile example.txt.gz
il makefile sono costituiti da una sola regola che istruire rendono come creare un file il cui nome fine con .gz se esiste un file con lo stesso nome, ma il suffisso .gz.
makefile Hello World
C: \ Makefile:
helloWorld :
[TAB]echo hello world
eseguire i risultati:
C:\>make
echo hello world
hello world
Nota: [TAB] deve essere sostituito da una scheda effettiva, lo stackoverflow sostituisce le schede con spazi e gli spazi non vengono utilizzati come le schede di un makefile.