Articles

Ce este un Makefile și cum funcționează?

Posted by admin

Dacă doriți să rulați sau să actualizați o sarcină atunci când anumite fișiere sunt actualizate, utilitarul make poate fi util. make utilitar necesită un fișier, Makefile (sau makefile), care definește un set de sarcini pentru a fi executat. Este posibil să fi folosit make pentru a compila un program din codul sursă. Cele mai multe proiecte open source folosi make pentru a compila un final binar executabil, care poate fi apoi instalat folosind make install.,

În acest articol, vom explora make și Makefile utilizarea de bază și avansate de exemple. Înainte de a începe, asigurați-vă că make este instalat în sistemul dvs.

Exemple de bază

să începem prin imprimarea clasicului „Hello World” pe terminal. Creați un director gol myproject conține un fișier Makefile cu acest conținut:

say_hello:
echo "Hello World"

Acum, rulați fișierul prin tastarea make în directorul myproject., Rezultatul va fi:

$ make
echo "Hello World"
Hello World

În exemplul de mai sus, say_hello se comportă ca un nume de funcție, la fel ca în orice limbaj de programare. Aceasta se numește țintă. Premisele sau dependențele urmează ținta. Din motive de simplitate, nu am definit nicio condiție prealabilă în acest exemplu. Comanda echo "Hello World" se numește rețetă. Rețeta folosește premise pentru a face o țintă. Ținta, premisele și rețetele împreună fac o regulă.,pentru a rezuma, mai jos este sintaxa unei reguli tipice:

target: prerequisites
<TAB> recipe

ca exemplu, o țintă ar putea fi un fișier binar care depinde de cerințe preliminare (fișiere sursă). Pe de altă parte, o condiție prealabilă poate fi și o țintă care depinde de alte dependențe:

nu este necesar ca ținta să fie un fișier; ar putea fi doar un nume pentru rețetă, ca în exemplul nostru. Noi numim aceste ” ținte false.,”

revenind la exemplul de mai sus, atunci când make a fost executat, întreaga comandă echo "Hello World" s-a afișat, urmată de comandă efectivă de ieșire. De multe ori nu vrem asta. Pentru a suprima un ecou comanda propriu-zisă, avem nevoie pentru a începe echo cu @:

say_hello:
@echo "Hello World"

Acum încerca pentru a rula make din nou., Producția ar trebui să afișeze numai acest lucru:

$ make
Hello World

Să adăugați câteva mai multe ținte false: generate și clean la Makefile:

Dacă vom încerca să rula make după modificări, singura țintă say_hello va fi executat. Asta pentru că doar prima țintă din makefile este ținta implicită. Adesea numit obiectivul implicit, acesta este motivul pentru care veți vedea all ca prima țintă în majoritatea proiectelor., Este responsabilitatea all să apeleze la alte ținte. Putem suprascrie acest comportament folosind o țintă falsă specială numită .DEFAULT_GOAL.

Să includă faptul că la început de makefile:

.DEFAULT_GOAL := generate

Acesta va rula țintă generate ca implicit:

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

după Cum sugerează și numele, fals țintă .DEFAULT_GOAL poate rula doar o singură țintă la un moment dat. Acesta este motivul pentru care majoritatea fișierelor Makefile includ all ca țintă care poate apela cât mai multe ținte după cum este necesar.,

Să includă fals țintă all și scoateți .DEFAULT_GOAL:

Înainte de a rula make, să includă o altă speciale fals țintă, .PHONY, unde ne-am defini toate obiectivele care nu sunt fișiere. make își va rula rețeta indiferent dacă există un fișier cu acest nume sau care este ultima sa modificare., Aici este complet makefile:

make ar trebui să apel say_hello și generate:

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

este o bună practică să nu pentru a apela clean în all sau pune-l ca prima tinta., clean ar trebui să fie numit manual, atunci când curățarea este necesar ca un prim argument pentru make:

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

Acum, că aveți o idee de cât o bază makefile funcționează și cum să scrie un simplu makefile, să ne uităm la unele mai avansate exemple.

Exemple avansate

variabile

în exemplul de mai sus, cele mai multe valori țintă și premise sunt greu codate, dar în proiecte reale, acestea sunt înlocuite cu variabile și modele.,

cel mai simplu mod de a defini o variabilă într-un makefile este de a utiliza = operator., De exemplu, pentru a atribui comanda gcc o variabila CC:

CC = gcc

Acest lucru este, de asemenea, numit un recursiv extins variabilă, și este utilizat în regulă așa cum se arată mai jos:

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

Cum poate ați ghicit, reteta se extinde ca mai jos atunci când este trecut la terminal:

gcc hello.c -o hello

Ambele ${CC} și $(CC) sunt valabile trimiteri la apel gcc. Dar dacă cineva încearcă să realoce o variabilă în sine, va provoca o buclă infinită., Să verifice acest lucru:

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

Execută make va avea ca rezultat:

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

Pentru a evita acest scenariu, putem folosi := operator (acest lucru este, de asemenea, numit pur și simplu extins variabilă). Nu ar trebui să avem nicio problemă cu rularea makefile de mai jos:

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

modele și funcții

următoarele makefile pot compila toate programele C folosind variabile, modele și funcții., Să-l exploreze linie cu linie:

mai jos este rescrierea makefile de mai sus, presupunând că este plasat în directorul având un singur fișier foo.c:

Leave A Comment