Articles

Che cos’è un Makefile e come funziona?

Posted by admin

Se si desidera eseguire o aggiornare un’attività quando vengono aggiornati determinati file, l’utilitàmake può tornare utile. L’utilitàmake richiede un file,Makefile (omakefile), che definisce un insieme di attività da eseguire. Potresti aver usato make per compilare un programma dal codice sorgente. La maggior parte dei progetti open source utilizzamake per compilare un binario eseguibile finale, che può essere installato utilizzandomake install.,

In questo articolo, esploreremo make e Makefile utilizzando esempi di base e avanzati. Prima di iniziare, assicurarsi che make sia installato nel sistema.

Esempi di base

Iniziamo stampando il classico “Hello World” sul terminale. Creare una directory vuota myproject che contiene un file Makefile con questo contenuto:

say_hello:
echo "Hello World"

eseguire il file digitando make all’interno della directory myproject., L’output sarà:

$ make
echo "Hello World"
Hello World

Nell’esempio precedente, say_hello si comporta come un nome di funzione, come in qualsiasi linguaggio di programmazione. Questo è chiamato il bersaglio. I prerequisiti o le dipendenze seguono la destinazione. Per semplicità, non abbiamo definito alcun prerequisito in questo esempio. Il comandoecho "Hello World" è chiamato la ricetta. La ricetta utilizza i prerequisiti per creare un target. L’obiettivo, i prerequisiti e le ricette insieme fanno una regola.,

Per riassumere, di seguito è riportata la sintassi di una regola tipica:

target: prerequisites
<TAB> recipe

Ad esempio, un target potrebbe essere un file binario che dipende dai prerequisiti (file di origine). D’altra parte, un prerequisito può anche essere un target che dipende da altre dipendenze:

Non è necessario che il target sia un file; potrebbe essere solo un nome per la ricetta, come nel nostro esempio. Noi chiamiamo questi ” obiettivi fasulli.,”

Tornando all’esempio precedente, quando è stato eseguitomake, è stato visualizzato l’intero comandoecho "Hello World", seguito dall’output effettivo del comando. Spesso non lo vogliamo. Per sopprimere l’eco del comando effettivo, dobbiamo avviareecho con@:

say_hello:
@echo "Hello World"

Ora prova a eseguire nuovamentemake., L’output dovrebbe mostrare solo questo:

$ make
Hello World

Cerchiamo di aggiungere un paio di più falso obiettivi: generate e clean per il Makefile:

Se si tenta di eseguire make dopo le modifiche, solo il target say_hello verrà eseguito. Questo perché solo il primo target nel makefile è il target predefinito. Spesso chiamato l’obiettivo predefinito, questo è il motivo per cui vedrai all come primo obiettivo nella maggior parte dei progetti., È responsabilità di all chiamare altri target. Possiamo ignorare questo comportamento usando uno speciale target fasullo chiamato .DEFAULT_GOAL.

Lasciate che include che all’inizio della nostra makefile:

.DEFAULT_GOAL := generate

Questo sarà il target generate come predefinito:

$ make
Creating empty text files...
touch file-{1..10}.txt

Come suggerisce il nome, falso bersaglio .DEFAULT_GOAL possibile eseguire un solo bersaglio alla volta. Questo è il motivo per cui la maggior parte dei makefile include all come target che può chiamare tutti i target necessari.,

Includiamo il target fasulloall e rimuoviamo.DEFAULT_GOAL:

Prima di eseguiremake, includiamo un altro target speciale fasullo,.PHONY, dove definiamo tutti gli obiettivi che non sono file. make eseguirà la sua ricetta indipendentemente dall’esistenza di un file con quel nome o dall’ora dell’ultima modifica., Qui è la completa makefile:

make dovrebbe chiamare say_hello e generate:

$ make
Hello World
Creating empty text files...
touch file-{1..10}.txt

si tratta di una buona pratica di non chiamare clean nel all o metterlo come primo target., clean dovrebbe essere chiamato manualmente quando è necessaria una pulizia come primo argomento make:

$ make clean
Cleaning up...
rm *.txt

Ora che avete un’idea di come una base makefile funziona e come scrivere un semplice makefile, diamo un’occhiata ad alcuni esempi più avanzati.

Esempi avanzati

Variabili

Nell’esempio precedente, la maggior parte dei valori target e prerequisiti sono hard-coded, ma nei progetti reali, questi vengono sostituiti con variabili e pattern.,

Il modo più semplice per definire una variabile in un makefile è usare l’operatore =., Per esempio, per assegnare il comando gcc variabile CC:

CC = gcc

Questo è anche chiamata ricorsiva ampliato variabile, e viene utilizzato in una regola, come illustrato di seguito:

hello: hello.c
${CC} hello.c -o hello

Come si può immaginare, la ricetta si espande come di seguito quando è passato al terminale:

gcc hello.c -o hello

Sia ${CC} e $(CC) sono validi riferimenti per chiamare gcc. Ma se si tenta di riassegnare una variabile a se stessa, causerà un ciclo infinito., Verifichiamo questo:

CC = gcc
CC = ${CC}
all:
@echo ${CC}

L’esecuzione di make comporterà:

$ make
Makefile:8: *** Recursive variable 'CC' references itself (eventually). Stop.

Per evitare questo scenario, possiamo utilizzare l’operatore := (questo è anche chiamato la variabile semplicemente espansa). Non dovremmo avere problemi a eseguire il makefile qui sotto:

CC := gcc
CC := ${CC}
all:
@echo ${CC}

Pattern e funzioni

Il seguente makefile può compilare tutti i programmi C usando variabili, pattern e funzioni., Esploriamolo riga per riga:

Di seguito è riportata la riscrittura del makefile sopra, supponendo che sia posizionato nella directory con un singolo file foo.c:

Leave A Comment