Ce face make și Makefile
Într-un proiect cu multe fișiere .c, a recompila totul după fiecare modificare durează. make citește un fișier numit Makefile cu reguli de forma țintă: dependențe urmate de comenzi. O țintă este refăcută doar dacă lipsește sau dacă una dintre dependențe este mai nouă decât ea (după data modificării fișierelor).
Fiecare comandă dintr-o regulă începe cu un caracter TAB, nu cu spații. Variabilele (CC, CFLAGS) se folosesc cu $(NUME). Variabile automate: $@ (ținta), $< (prima dependență), $^ (toate dependențele). O regulă cu tipar (%.o: %.c) descrie cum se face orice fișier .o din .c-ul cu același nume.
make fără argumente construiește prima țintă din fișier. make clean rulează ținta clean, care șterge de obicei fișierele generate. .PHONY: clean spune că clean nu este un fișier. make -n afișează comenzile fără să le execute.
Parametri
| Parametru | Descriere |
|---|---|
$@ |
Numele țintei regulii. |
$< |
Prima dependență (de exemplu fișierul .c). |
$^ |
Toate dependențele, fără dubluri. |
make -n |
Afișează comenzile care s-ar executa, fără să le ruleze. |
make -j4 |
Rulează până la 4 comenzi în paralel. |
Exemple
Exemplul 1: Un Makefile pentru un catalog cu două fișiere
La prima rulare, make compilează ambele fișiere și le leagă. A doua oară nu are nimic de făcut. Dacă modifici doar note.c, se recompilează doar el și se refac legăturile.
# Makefile (rândurile cu comenzi încep cu TAB)
CC = clang
CFLAGS = -std=c23 -Wall -Wextra -O2
catalog: main.o note.o
$(CC) $(CFLAGS) main.o note.o -o catalog
main.o: main.c note.h
$(CC) $(CFLAGS) -c main.c
note.o: note.c note.h
$(CC) $(CFLAGS) -c note.c
clean:
rm -f *.o catalog
.PHONY: clean
# în terminal:
# make
# make
# (după o modificare în note.c)
# make
Ieșire în terminal
clang -std=c23 -Wall -Wextra -O2 -c main.c
clang -std=c23 -Wall -Wextra -O2 -c note.c
clang -std=c23 -Wall -Wextra -O2 main.o note.o -o catalog
make: `catalog' is up to date.
clang -std=c23 -Wall -Wextra -O2 -c note.c
clang -std=c23 -Wall -Wextra -O2 main.o note.o -o catalog
Exemplul 2: Regulă cu tipar și variabile automate
%.o: %.c note.h se aplică tuturor fișierelor obiect. $< devine main.c sau note.c, $@ fișierul .o, iar $^ toată lista de obiecte. make -n arată comenzile fără să le ruleze.
# Makefile
CC = clang
CFLAGS = -std=c23 -Wall -Wextra -O2
OBIECTE = main.o note.o
catalog: $(OBIECTE)
$(CC) $(CFLAGS) $^ -o $@
%.o: %.c note.h
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBIECTE) catalog
.PHONY: clean
# în terminal:
# make -n
Ieșire în terminal
clang -std=c23 -Wall -Wextra -O2 -c main.c -o main.o
clang -std=c23 -Wall -Wextra -O2 -c note.c -o note.o
clang -std=c23 -Wall -Wextra -O2 main.o note.o -o catalog
Exemplul 3: Curățarea fișierelor generate
make clean afișează și execută comanda din ținta clean. Pentru că clean este declarată .PHONY, regula rulează chiar dacă în director ar exista un fișier numit clean.
# în terminal, în directorul cu Makefile-ul din primul exemplu:
make clean
ls -1
Ieșire în terminal
rm -f *.o catalog
Makefile
main.c
note.c
note.h
Greșeli frecvente
- Indentezi comenzile cu spații.
makecere TAB și răspunde cu „Makefile:5: *** missing separator. Stop.”. - Uiți antetul în lista de dependențe (
main.o: main.cfărănote.h). Când modifici antetul,makenu recompilează nimic și programul folosește declarații vechi. - Numești o țintă ca un fișier existent (
clean,test) fără.PHONY. Dacă fișierul există,makecrede că ținta este deja făcută.
Comenzi înrudite
Compilarea cu gcc și clang: Cum transformi codul C într-un program executabil cu gcc sau clang și ce fac opțiunile folosite cel mai des.Programe din mai multe fișiere (.c și .h): Cum împarți un program C în fișiere sursă (.c) și antete (.h), cum le compilezi separat și cum le legi într-un executabil.#include: Copiază conținutul unui fișier antet (.h) în locul liniei, ca funcțiile și tipurile declarate acolo să poată fi folosite.extern: Declară o variabilă globală definită în alt fișier (sau mai jos), ca să o poți folosi fără să creezi o copie nouă.