From: xf0r3m
- + Na podstawie dwóch plików z poprzedniego podrozdziaÅu utworzyÅem + przykÅadowy plik Makefile. Plik ten tworzy znany nam + rownież plik myprog, który nie robi nic wiÄcej poza + wyÅwietleniem napisu Hello, World!. +
++xf0r3m@laptop-7bf2993:~/prog/C$ cat Makefile + +OBJS=aux.o main.o +all: myprog +myprog: $(OBJS) + $(CC) -o myprog $(OBJS) ++
+ W pierwszej linii znajduje siÄ definicja makra, która w tym
+ przypadku wskazuje na dwie nazwy plików obiektowych
+ (OBJS=aux.o main.o). W nastÄpnej
+ linii znajduje siÄ bowiem reguÅa
+ (all:) reguÅy jak już wczeÅniej
+ wspomniano okreÅlajÄ
sposób w jaki ma zostaÄ zbudowany cel. W tym
+ przypadku reguÅa all: wskazuje
+ mogÅoby siÄ wydawaÄ, że na nasz plik koÅcowy. Jest to poczÄÅci
+ prawda, ale zwróÄmy uwagÄ na to, że poza
+ myprog nie znajduje siÄ nic innego.
+ W jaki sposób narzÄdzie make ma wiedzieÄ jak zbudowaÄ ten
+ ten program. Odpowiedź kryje siÄ w linii niżej, bowiem
+ myprog jest celem,
+ a co za tym idzie zależnoÅciÄ
dla
+ all:. W przypadku celu
+ myprog: widzimy już jakieŠkonkrety:
+ pierwszym jest odwoÅanie siÄ do makra, jest ono rozwiÄ
zywane do
+ nazw zapisanych na poczÄ
tku pliku Makefile, w pliku nie
+ znajduje siÄ Å¼adne inne elementy systemu Make tak wiÄc
+ ten cel jest o tych plików uzależniony. Warto dodaÄ, że
+ Make zakÅada, że plki źródÅowe znajdujÄ
siÄ w tym samym
+ katalogu co pliki Makefile. Uruchomienie polecenia
+ make w tym katalogu prezentuje siÄ nastÄpujÄ
co.
+
+xf0r3m@laptop-7bf2993:~/prog/C$ make +cc -c -o aux.o aux.c +cc -c -o main.o main.c +cc -o myprog aux.o main.o ++
+ Poza tym co sami zapisaliÅmy w pliku Makefile to nie + wszystkie czynnoÅci jakie sÄ wykonywane przez system Make. + W Makefile użyliÅmy plików obiektowych, zatem skÄ d narzÄdzie + ma wiedzieÄ o tym, że ma wykorzystaÄ pliki kodu źródÅowego + (.c), aby utworzyÄ pliki obiektowe (.o). Za tego + typu czynnoÅci odpowiadajÄ reguÅy wbudowane. Przez + co osoby zajmujÄ ce siÄ utworzeniem plików Makefile mogÄ + od razu operowaÄ na wÅaÅciwych plikach. +
+
+ Ostatnia linia pliku Makefile jest odpowiedzialna za
+ zbudowanie wÅaÅciwego pliku wykonywalnego naszego programu.
+ Po wczeÅniejszym przygotowaniu plików obiektowych z plików
+ źródÅowych odwoÅanie siÄ do makra
+ $(OBJS) staje siÄ zwykÅym
+ podstawieniem argumentów do polecenia. Ta linia jest zwykÅym
+ poleceniem utworzonym na podstawie makr pliku Makefile.
+ Każde polecenie w pliku Makefile musi zostaÄ
+ wprowadzone w nowej linii i poprzedzone
+ znakiem tabulacji równym czterem znakom spacji.
+ Makro $(CC) jest zmiennÄ
, która
+ przechowywuje nazwÄ programu kompilatora C, w wiekszoÅci przypadku
+ jej wartoÅÄ bÄdzie ustawiona na cc.
+
+ Jednym z najczÄstszych bÅÄdów, jakie możemy doÅwiadczyÄ na poczÄ tku + tworzenia plików Makefile jest: +
++xf0r3m@laptop-7bf2993:~/prog/C$ make +Makefile:5: *** brakujÄ cy separator. Stop. ++
+ Wynika to najczÄÅciej ze zÅego ustawienia szerokoÅci tabulacji w + naszym edytorze. Ja korzystam z 2 spacji na 1 tab, ze wzglÄdu na + wytyczne Makefile musiaÅem zmieniÄ swoje ustawienia. +
++ Program make zostaÅ zaprojektowany w taki sposób aby do realizacji + okreÅlonego celu byÅa wymagana jak najmniejsza iloÅÄ kroków. Tak + wiÄc nie uÅwiadczymy ponownego budowania programu w momencie + ponownego wydania polecenia make. Aczkolwiek jednÄ z zasad + systemu Make jest to, że cele zawsze powinny byÄ budowane + wraz ze swoimi zależnoÅciami. Taki komunikat otrzymamy gdy + wydamy polecenie make jeszcze raz. +
++xf0r3m@laptop-7bf2993:~/prog/C$ make +make: Nie ma nic do zrobienia w 'all'. ++
+ Natomiast jeÅli chociażby zmienimy datÄ, któregoÅ z plików kodu + źródÅowego za pomocÄ prostego polecenia touch. Wówczas plik + obiektowy bÄdzie starszy niż plik źródÅowy i Make dokona + budowy naszego programu ponownie. +
++xf0r3m@laptop-7bf2993:~/prog/C$ touch aux.c +xf0r3m@laptop-7bf2993:~/prog/C$ make +cc -c -o aux.o aux.c +cc -o myprog aux.o main.o ++
+ Z tÄ róźnicÄ , że zaktualizowany zostanie wyÅÄ cznie ten plik, który + zostaÅ zmieniony oraz ponownie zostanie zbudowany koÅcowy plik + wykonywalny. +
++ UzupeÅniajÄ c wywoÅanie programu make o różne opcje oraz + argumenty możemy zmusiÄ go do wykonani kilku przydatnych czynnoÅci. + Najprostrzym przykÅadem może byÄ zmiana wartoÅci makra CC, + wskazujÄ c inny niż domyÅlny kompilator. +
++$ make CC=clang ++
+ Tak utworzone makra mogÄ byÄ przydatne w trakcie testów. Szczególnie + takie jak CFLAGS oraz LDFLAGS. Innym przypadkiem + może byÄ użycie programu make dla najprostrzych programów + wówczas podajemy nazwe pliku bez rozszerzenia jako argument, + a program zbuduje nam koÅcowy plik wynikowy o podanej nazwe. ZwróÄmy + uwagÄ, że nie ma potrzeby przygotowania pliku Makefile. +
++$ make foo +cc foo.o -o foo ++
+ Tego typu uruchmianie narzÄdzia make bedzie sprawdzaÄ siÄ + w przypadku programów zapisanych w jednym pliku lub programów, w + których jezykiem nie jest C. Jest to drobre rozwiÄ zanie gdy dopiero + rozpoczynamy pracÄ z danym jÄzykiem i nie wiem jeszcze jak dziaÅa + kompilator czy inne narzÄdzia z nim zwiÄ zane. JeÅli nawet zbudowanie + celu siÄ niepowiedzie to i tak otrzymamy informacjÄ zwrotnÄ co jest + nie tak. +
++ Po za zmianami makr, możemy wykorzystaÄ kilka przydatnych opcji + takich jak: +
++ System make posiada wiele predefiniowanych zmiennych oraz + makr. Sama różnica miÄdzy makrami i zmiennymi jest trudna do + okreÅlenia. Dlatego też przyjÄÅo siÄ, że makra sÄ niezmienne przez + caÅy okres trwania jakiegoÅ procesu. W tym przypadku nazwiemy tak + wszystko co nie zmieni siÄ od momemntu rozpoczÄcia procesu + budowania celów zawartych w pliku Makefile. +
++ NajczÄsciej wykorzystywane makra to miÄdzy innymi: +
++ Poza makrami w narzÄdziu make możemy korzystaÄ ze zmiennych. + Zmienne mogÄ zmieniÄ siÄ podczas budowania zdefiowanych celów w + Makefile. NajczÄÅciej jednak bÄdziemy siÄ spotykaÄ ze + zmiennymi zdefiniowanymi automatycznie w obrÄbie reguÅ celów. Oto + trzy z nich: +
++ W plikach makefile odpowiedzialnych za pokierowanie systemu + make faktycznych programów użytkowych możemy spotkaÄ wiele + innych celów realizujÄ cych zadania niekoniecznie zwiÄ zane z + kompilacjÄ . SÄ one predefiniowane przez make i oto kilka z + nich: +
++ Istnieje wiele róznych stylów tworzenia plików Makefile, + mimo tego stosowanych jest kilka ogólnych zasad. W pierwszej + czÄsci pliku, najczeÅciej spotykane sÄ (jako definiecje makr) + opcje bibliotek oraz plików nagÅówkowych po grupowanych wg. + okreÅlonych pakietów. +
++MYPACKAGE_INCLUDES=-I/usr/local/include/mypackage +MYPACKAGE_LIB=-L/usr/local/lib/mypackage -lmypackage +PNG_INCLUDES=-I/usr/local/include +PNG_LIB=-L/usr/local/lib -lpng ++
+ NastÄpnie zapisywane sÄ makra z opcjami kompilatora oraz opcje + konsolidatora każde z opcji zapisywane jest w osobnym makrze. +
++CFLAGS=$(CFLAGS) $(X_INCLUDES) $(PNG_INCLUDES) +LDFLAGS=$(LDFLAGS) $(X_LIB) $(PNG_LIB) ++
+ Po tych opcjach zapisywana jest hierarchia makr opisujÄ cych pliki + obiektowe. Hierarchia ze wzglÄdu na zależnoÅci. +
++UTIL_OBJS=util.o +BORING_OBJS=$(UTIL_OBJS) boring.o +TRITE_OBJS=$(UTIL_OBJS) trite.o +PROGS=boring trite ++
+ W pozostaÅej czÄsci plików wystÄpujÄ już cele, które skÅadajÄ gÅówne + pliki wykonywalne. JeÅli trzeb przygowaÄ reguÅÄ dla pliku obiektowego + należy jÄ umieÅciÄ zaraz nad reguÅÄ programu pliku wykonywalnego. + JeÅli z tego pliku obiektowego korzysta wiÄcej plików wykonywalnych + niż ten jednen to trzeba je przenieÅÄ nad nie wszystkie.