Compilarea Proiectelor in UNIX.
Utilizarea Makefile.
 

De la Codul-Sursa la Programul Executabil

Exemple de Compilare cu gcc/g++

Compilatorul gcc este la origine unul dintre cele mai bune compilatoare de C existente. El a fost extins pentru a putea compila si programe C++,  si aceasta varianta a sa a fost denumita g++ . modul sau de utilizarea fiind insa consistent gcc-ul.  Nu ne propunem in acest paragraf sa discutam in detaliu utilizarea compilatorului gcc/g++ , ci doar sa oferim cateva exemple care sa ilustreze modul uzual de utilizare a sa. Pentru detalii consultati pagina de manual (man gcc).
 

Necesitate Compilarii Separate. Dependente.

Dezvoltarea unor programe de dimensiuni mai mari intr-un limbaj de programare presupune o metodologie de lucru diferita de cazul programelor mici. La programele simple este suficienta crearea unui fisier care contine codul si apoi, printr-o singura comanda la nivelul procesorului de comenzi sau in cadrul unui mediu integrat, se obtine fisierul executabil.

La programele mai mari lucrurile nu sunt atat de simple: daca am avea un singur fisier programul ar fi foarte greu de inteles si in plus trecerea la programul executabil ar necesita un timp mare, intrucat modificarea celui mai mic detaliu ar impune recompilare intregului cod. nefolosindu-se facilitatea de compilare separata. In plus, proiectele mari sunt intotdeauna rezultatul muncii unei intregi echipe, ceea ce face imperios necesara impartirea intr-un numar mare de fisiere (numite module) codul-sursa si de a compila independent aceste fisiere. Aceasta facilitate se numeste compilare separata.

Desi distincte si compilabile separat, diferitele module apartin aceluiasi proiect si in mod normal nu sunt total independente intre ele. Numim aceste relatii intre diferitele module, dependente. Procesul de modularizare are  ca scop tocmai detectarea si minimizarea acestor dependente intre module. Aceste dependente au un impact evident asupra procesului de compilarea si anume: atunci cand a fost modificat un modul, recompilarea sa implica si recompilarea tuturor modulelor care depind de el.
 

Utilitarul make.Fisierele Makefile

Utilitarul  make determina automat care sunt bucatile unui proiect care trebuie recompilate ca urmare a operarii unor modificari si declanseaza comenzile necesare pentru recompilarea lor.

Pentru a putea utiliza make, trebuie sa scrieti un fisier numit Makefile (sau makefile) care descrie relatiile de de dependenta intre diferitele fisiere din care se compune programul, si specifica regulile de actualizare pentru fiecare fisier in parte. In mod normal, intr-un program fisierul executabil este actualizat (recompilat) pe baza fisierelor-obiect, care la randul lor sunt obtinute prin compilarea fisierelor sursa.

Odata creat acest fisier Makefile, de fiecare data cand operati vreo modificare in fisierele sursa, este suficient sa tastati in linia de comanda:
make pentru ca toate recompilarile necesare sa fie efectuate.  Programul make utilizeaza fisierul Makefile ca baza de date si pe baza timpilor ultimei modificari a fisierelor din Makefile decide care sunt fisierele care trebuie actualizate. Pentru fiecare din aceste fisiere, declanseaza comenzile precizate in Makefile.
 

Un Exemplu de Makefile

Vom prezenta in continuare ca un exemplu de Makefile scris pentru compilarea programului prezentat ca exemplu in lucrarea 2,:
 

# Declaratiile de variabile  

CC = g++ 

CCFLAGS = -Wall 

SRC = stack.cc \ 
      main.cc 

OBJ = stack.o \ 
      main.o 

PROGRAM = stack 
 

# Regulile de compilare 

$(PROGRAM) : $(OBJ) 
 $(CC) $(OBJ) -o $(PROGRAM) 
 

stack.o : stack.cc stack.h 
 $(CC) stack.cc -c $(CCFLAGS) 

main.o : main.cc stack.h 
 $(CC) main.cc -c $(CCFLAGS) 
 

# Regulile de ... curatenie  

.PHONY : clean 
clean : 
 rm -f $(PROGRAM) $(OBJ) core *~

 
 

Structura unui Makefile

Un Makefile se poate compune din urmatoarele elemente:

 Observatie: Intr-un Makefile o linie tine pana la intalnirea caracterului CR ('\n'). Totusi o linie poate fi "continuata" si dupa caracterul CR ('\n') prin utilizarea caracterului backslash (\) ca in exemplul de mai sus.

Structure unei Reguli
Un Makefile simpul se compune din reguli de urmatoarea forma:
 

Un obiectiv (taget)  este in mod normal numele unui fisier generat de catre un program, de exemplu fisiere-obiect sau fisiere executabile. Un obiectiv poate fi si numele unei actiuni care trebuie executata, cum este obiectivul clean din exemplul nostru. (vezi Obiective Phony)
O dependenta este un fisier utilizat ca intrarea pentru a crea un obiectiv. De obieci un obiectiv depinde de mai multe fisiere.
O comanda este o actiune pe care o executa make pentru o anumita regula. Pentru o regula se pot executa mai multe comenzi.
Atentie:  Fiecare comanda trebuie plasata pe o alta linie in fisierul Makefile.
              Este obligatoriu ca fiecare linie ce contine o comanda sa inceapa cu un tab.

De obicei o comanda apare intr-o regula cu dependente si serveste la crearea unui fisier-obiectiv daca vreunul din fisierele dependenta sunt modificate. Cu toate acestea, regula care specifica comenzi pentru un obiectiv nu trebuie sa aiba neaparat dependente, cum este cazul regula clean in care se sterg anumite fisiere nu are nici o dependenta, comezile executandu-se intotdeauna cand acesta regula este invocata.

Obiective Phony
Spre deosebire de celelate obiective, un  obiectiv phony nu reprezinta numele unui fisier. Este mai degraba un nume pentru un set de comenzi care trebuie executate cand regula este apelata explicit. Exista doua motive pentru care declaram un obiectiv ca fiind phony:

Daca scrieti o regula a carei comenzi nu vor crea fisierul-obiectiv comenzile vor fi executate de fiecare data cand regula este invocata. Regulile phony vor inceta insa sa functioneze corect daca se creaza in acel director un fisier cu acelasi nume cu cel al obiectuvului phony
(in exemplul nostru, daca s-ar crea un fisier cu numele clean). Intrucat regula nu are dependente, "fisierul" clean va fi considerat in permanenta actualizat, iar comenzile sale nu se vor executa. Pentru a evita aceasta problema, puteti declara explicit un obiectiv ca fiind phony, utilizand regula speciala ".PHONY"  (vezi exemplul). Prin aceasta, comanda "make clean" va executa comenzile indiferent daca exista sau nu un fisier numit "clean". 

 
Executia unui Makefile

Intrucat un Makefile contine mai multe reguli, intrebarea care se ridica este: care dintre reguli se va executa la apelul lui make fara nici un parametru? In acest caz se va executa intotdeauna prima regula intalnita in Makefile. Din acet motiv la compilarea unui proiect se obisnuieste declararea prima data a regulii prin care se obtine executabilul. Daca se doreste executarea unei anumite reguli se apeleaza make sub forma:  make numele_regulii ;

 
Bibliografie
Probabil cea mai cuprinzatoare si bine structurata documentatie on-line pentru utilizarea Makefile-urilor este cea disponibila prin comanda info in aproape toate sisteme UNIX. Aceasta se poate apela fie sub forma: info -f /usr/info/make , dar se recomanda utilizarea utilitarului info din Emacs (ESC-x info) .
 

Hosted by www.Geocities.ws

1