UPUTSTVO ZA KORISCENJE MAKE ALATA:
----------------------------------

Alat "make" se na UNIX-olikim sistemima koristi za odrzavanje projekta. Naime,
u toku procesa razvoja projekta cesto je potrebno pokretati komandu za
prevodjenje veliki broj puta, sto moze biti naporno. U slucaju vecih projekata
koji ukljucuju veliki broj fajlova, spisak komandi koje je potrebno pokrenuti
da bi se projekat ponovo izgradio moze biti podugacak. Takodje, postavlja se
i pitanja koje je fajlove potrebno ponovo prevoditi, a koje ne (u principu
se moraju prevoditi samo oni fajlovi koji su u medjuvremenu menjani). Ovo
prilicno otezava posao programeru i cini posao prevodjenja podloznim greskama
(npr. zaboravite da rekompajlirate neki od fajlova). Takodje, ponovno 
prevodjenje svih fajlova u projektu moze zahtevati mnogo vremena, sto je 
potpuno neekonomicno kada ste samo jedan ili dva fajlova menjali nakon 
poslednjeg prevodjenja projekta. 

Zbog svega ovoga, pozeljno je projekat podeliti na adekvatan nacin na veci
broj manjih fajlova, a zatim ih kompilirati odvojeno, nakon cega se u 
procesu povezivanja dobijeni objektni fajlovi spoje u izvrsni fajl. Ono
sto nam nedostaje je alat koji ce biti dovoljno pametan da zna koje komande
je neophodno pokrenuti, a koje ne, kako bi prevodjenje bilo konzistentno i
efikasno. Alati koji se koriste u ovo svrhe se obicno zovu alati za automatsko
prevodjenje projekta. Alat make je verovatno najpoznatiji ovakav alat.

Ideja make alata je da u direktorijumu sa izvornim kodom postoji poseban
fajl koji se zove Makefile (bas tako kako pise). Ovaj fajl sadrzi "recept"
za prevodjenje -- za svaki fajl koji treba da bude generisan sadrzi listu
fajlova od kojih je zavisan (tj. cija modifikacija zahteva azuriranje tog
fajla), kao i komandu (ili komande) koju je potrebno pokrenuti da bi se
fajl azurirao. Sve ovo zajedno cini PRAVILO u Makefile-u. Npr, jednostavno
pravilo izgleda ovako:

program: program.c
	 gcc -o program program.c

Dakle, najpre ide ime fajla koji se kreira tim pravilom (kod nas je to 
program). Nakon dvotacke ide lista fajlova (razdvojenih razmacima) od kojih
ovaj fajl zavisi (kod nas je to samo izvorni fajl program.c). U sledecem
redu (redovima) sledi komanda koja se pokrece da bi se fajl azurirao. Bitno
je da svaki od ovih redova sa komandama mora poceti JEDNIM TABULATOROM (bitno
je da to bude jedan tabulator, a ne nekoliko razmaka). U ovom primeru,
prosto se pokrece gcc prevodilac da azurira program. 

Svaki Makefile moze sadrzati vise pravila. Kada se u direktorijumu u kome
se nalazi Makefile pokrene komanda:

make

tada se pronalazi prvo pravilo u Makefile-u i ono se izvrsava. Izvrsavanje
pravila se obavlja na sledeci nacin:
   1) Pogleda se lista zavisnosti (iza dvotacke). Ako za bilo koji od tih
   fajlova postoje pravila u nastavku, ova pravila se rekurzivno izvrsavaju.
   Ako za neku od zavisnosti ne postoji pravilo u Makefile-u, taj fajl bi
   trebalo da postoji u istom direktorijumu. Ako ne, make ce prijaviti gresku.
   2) Nakon toga se gleda da li postoji ciljni fajl (sa leve strane dvotacke).
   Ako ne postoji, tada se komande iz tog pravila svakako izvrsavaju. Ako
   fajl postoji, onda se komenda izvrsavaju ako i samo ako postoji bar jedan
   od fajlova iz liste zavisnosti cije je poslednje vreme modifikacije
   "skorije" od poslednjeg vremena modifikacije ciljnog fajla (tj. ako je 
   neki od fajlova iz liste zavisnosti "noviji" od naseg fajla -- tada nas
   fajl nije azuran i treba ga azurirati). 

U nasem primeru, fajl od koga zavisi program je program.c, za koji ne postoji
pravilo koje bi bilo rekurzivno pozvano. Zbog toga se komanda gcc poziva ako
i samo ako ili fajl "program" ne postoji ili postoji ali je vreme azuriranja
fajla program.c novije od vremena azuriranja fajla "program"(tj. fajl program.c
je u medjuvremenu menjan). 

Ukoliko zelite da make alat ne pokrece prvo pravilo u Makefile-u, mozete
eksplicitno zadati ime cilja u pravilu prilikom pozivanja:

make program

ce traziti pravilo ciji je ciljni fajl 'program' i pokretace to pravilo.

Napomenimo jos da pravilo moze da ne sadrzi ni jednu liniju sa komandama. U 
tom slucaju, to pravilo ima jedinu svrhu da rekurzivno pokrece pravila za 
"podciljeve", npr:

all: program1 program2

Ovo pravilo ce (pod uslovom da fajl 'all' ne postoji) pozivati rekurzivno
pravila za program1 i program2, cime ce se, po potrebi, azurirati ova dva
programa. Ovakvo pravilo treba da bude oznaceno kao "lazno", jer se fajl
'all' nikada ne kreira (vidi dole LAZNA PRAVILA). 

Evo slozenijeg primera: imamo fajlove biblioteka.h (gde se nalaze deklaracije
funkcija i definicije tipova), biblioteka.c (gde se nalaze definicije funkcija
deklarisanih u prethodnom zaglavlju) i program.c gde se nalazi main() funkcija
koja koristi funkcije iz biblioteke. Ideja je da se prevodjenjem fajla
program.c dobije objektni fajl program.o, i slicno za biblioteka.c
(biblioteka.o), a da se zatim ova dva fajla povezu u izvrsni fajl 'program'.
Fajl program.o zavisice od fajla program.c, ali i od fajla biblioteka.h
(koji se ukljucuje u fajl program.c #include direktivom). Fajl biblioteka.o
zavisice od fajla biblioteka.c, ali i od zaglavlja biblioteka.h (koje se
ukljucuje u fajl biblioteka.c #include direktivom). Najzad, izvrsni fajl bi
zavisio samo od objektnih fajlova program.o i biblioteka.o. Sadrzaj Makefile-a
bi bio ovakav:

program: program.o biblioteka.o
	 gcc -o program program.o biblioteka.o
program.o: program.c biblioteka.h
	 gcc -c -o program.o program.c
biblioteka.o: biblioteka.c biblioteka.h
	 gcc -c -o biblioteka.o biblioteka.c

Ako pozovemo komandu:

make

on pronalazi prvo pravilo (program). S obzirom da fajlovi od kojih on zavisi
imaju svoja pravila u Makefile-u, ona se rekurzivno izvrsavaju. Najpre se
izvsava pravilo za program.o. Njegova komanda ce se pokrenuti ili ako ovog
fajla nema, ili ako on postoji ali je "stariji" od bar jednog od njegovih
zavisnosti (program.c ili biblioteka.h). Nakon toga se pokrece pravilo
za biblioteka.o (slicno). Na kraju se vracamo u glavno pravilo: sada su
fajlovi biblioteka.o i program.o eventualno azurirani (ako je za tim bilo
potrebe), pa se njihova vremena modifikacije uporedjuju sa fajlom program.
Ako fajl program ne postoji, ili je stariji od fajlova program.o ili 
biblioteka.o, odgovarajuca komanda za povezivanje ce se pokrenuti. 

"LAZNA" PRAVILA
----------------

Ponekad postoje tzv. "lazna" pravila, tj. pravila koja ne treba da kreiraju
ni jedan fajl, vec treba da obave neke dopunske poslove. Npr, cesto u 
Makefile-ovima postoji pravilo:

clean:
	rm -f *~
	rm -f *.o
	rm -f program

Kada se pokrene ovo pravilo, s obzirom da nema liste zavisnosti, njegove
komande ce se izvrsavati ako i samo ako fajl 'clean' ne postoji. Ovim 
komandama se ne kreira fajl 'clean' vec se brisu automatski generisani
i privremeni fajlovi ("cisti" se direktorijum). Samim tim, ako pretpostavimo
da u direktorijumu od ranije ne postoji fajl koji se zove 'clean' komande iz
ovog pravila ce se uvek izvrsavati, kad god pokrenemo komandu:

make clean

Jedini problem moze da nastane ako neko (slucajno ili namerno) kreira
fajl koji se zove 'clean' u tom direktorijumu. Tada se komanda nikada nece
izvrsavati, zato sto make smatra da je fajl 'clean' azuran. Da bi se to
sprecilo, obicno se na pocetku Makefile-a navede linija:

.PHONY: clean

cime se naglasava da je 'clean' lazno pravilo i da ne treba gledati da li
fajl postoji ili ne, vec pravilo treba uvek izvrsavati. 

KOMENTARI:
----------

U Makefile-u su dozvoljeni komentari. Sve pocev od znaka # do kraja linije
se smatra komentarom i ignorise se od strane make alata.

Za detaljnije upoznavanje sa make alatom pogledati sledecu literaturu:

http://www.gnu.org/software/make/
http://mrbook.org/tutorials/make/
http://poincare.matf.bg.ac.rs/~asamardzic//gnu.pdf


Za sva dodatna pitanja i nejasnoce, pisati na mejl: milan@matf.bg.ac.rs
