V tejto časti seriálu si predstavíme make. Na niekoľkých ukážkach si predvedieme ako funguju závislosti v Makefile. Na konci článku nás čaká ľahký úvod do cmake.
Mnohí z vás určite poznajú trojicu príkazov configure
, make
a make install
. V tejto časti sa pokúsim vysvetliť čo sa za týmito príkazmi skrýva a ako to využiť pri vlastných projektoch.
Make
Make je nástroj, ktorý dokáže automaticky zistiť poradie v ktorom majú byť časti programu skompilované. Na to aby vedel určiť v akom poradí sa majú súbory kompilovať musíme vytvoriť súbor Makefile ktorý obsahuje závislosti a príkazy. Veľmi dôležitou vlastnosťou make je rekompilácia iba tých častí, ktoré sa musia znovu skompilovať. Tieto vlastnosti robia z GNU Make veľmi silný nástroj.
Závislosti
Pri kompilácii programu musíme zaistiť aby jednotlivé časti kompilácie prebehli v správnom poradí. Ak chceme napríklad vytvoriť súbor objekt.o budeme na kompiláciu potrebovať súbory objekt.h a objekt.cpp (za predpokladu, že tieto súbory nepotrebujú žiadne ďalšie závislosti). Akonáhle máme všetky objektové súbory (súbory s príponou *.o) skompilované môžeme celý program zlinkovať. Toto správanie sa dá veľmi ľahko popísať grafom závislostí.
Graf závislostí
Tento graf znázorňuje program "Ahoj svet" z minulej časti. Na začiatku máme súbory hello_lib.cpp, hello_lib.h a hello_main.cpp. Potrebujeme skompilovať výsledný program (hello). Na úspešné zlinkovanie tohto programu potrebujeme hello_lib.o a hello_main.o. Preto musíme najskôr skompilovať tieto 2 objektové kódy a až potom môžeme pokračovať linkovaním.
Teraz si predstavme situáciu, že všetko je správne skompilované a pri testovaní programu sme našli chybu. Táto chyba sa nachádza v jedinom súbore - hello_lib.cpp. Jednou z výhod oddelenej kompilácie je to, že nemusíme po nájdení chyby prekompilovať celý program, ale iba časť v ktorej sa chyba nachádza a všetky ďalšie časti ktoré zmena ovplyvní.
V tomto prípade treba znovu skompilovať hello_lib.o. Tým sa nam ale zmenila jedna zo závislostí programu hello preto musí byť hello znovu zlinkovaný. Všetko za nás našťastie rieši make, stačí len správne napísať súbor Makefile.
Tvorba makefile
Graf závislostí je teraz potrebné prepísať do súboru Makefile, ktorý má nasledujúcu syntax:
cieľ: závislosti príkazy
Každý príkaz sa musí začínať tabulátorom. Ak chceme do súboru pridať komentár stačí pred začiatok komentára vložiť znak #. Cieľ je súbor ktorý bude vytvorený alebo aktualizovaný ak sa zmení akýkoľvek súbor uvedený v závislostiach. Prepis grafu závislostí do Makefile by mohol vyzerať takto:
hello: hello_lib.o hello_main.o g++ hello_lib.o hello_main.o -o hello hello_lib.o: hello_lib.cpp hello_lib.h g++ -c hello_lib.cpp hello_main.o: hello_main.cpp hello_lib.h g++ -c hello_main.cpp
Pozor pri prepise treba dávať hlavne na hlavičkové súbory. Ak by sme zabudli na uvedenie hlavičkových súborov mohlo by sa nám stať, že by sa po ich úprave program nekorektne skompiloval.
Kompilácia pomocou make
Najskôr si vytvoríme nový adresár. Všetky zdrojové kódy nášho projektu skopírujeme do nového adresára a vytvoríme tam súbor Makefile. Po úspešnom vytvorení súboru Makefile môžeme v adresári s projektom spustiť príkaz make hello
. V prípade, že sa náš Makefile súbor volá ináč než Makefile musíme príkazu make špecifikovať ktorý súbor chceme použiť - make -f NášMakefile hello
. Ak nešpecifikujeme cieľ ktorý chceme skompilovať make automaticky skompiluje prvý cieľ ktorý v súbore nájde. V našom prípade je prvý cieľ hello preto namiesto make hello
môžeme napísať make
a kompilácia prebehne úplne rovnako.
Premenné
Ak by sme teraz chceli vymeniť kompilátor g++ za icc museli by sme nahradiť vo všetkých riadkoch kde kompilujeme príkaz g++ za icc. Pri väčších projektoch by sa toto mohlo stať nočnou morou programátora. Preto je lepšie príkazy vložiť do premenných.
Syntax vytvorenia premennej vyzerá takto:
názov_premennej = hodnota
Viacriadkové premenné môžeme zapísať pomocou znaku \ (spätné lomítko).
názov premennej = 1. riadok \ 2. riadok
Takto vytvorené premenné je možné použiť v príkazoch. Prístup k premennej je možný cez $(názov_premennej).
Náš Makefile s použitím premenných bude vyzerať takto:
CXX = g++ LINK = g++ CXX_FLAGS = -Wall hello: hello_lib.o hello_main.o $(LINK) hello_lib.o hello_main.o -o hello hello_lib.o: hello_lib.cpp hello_lib.h $(CXX) $(CXX_FLAGS) -c hello_lib.cpp hello_main.o: hello_main.cpp hello_lib.h $(CXX) $(CXX_FLAGS) -c hello_main.cpp
Automatické premenné
Automatické premenné sú vytvárané samostatne pre každý cieľ.
Zoznam niektorých automatických premenných
$@ | Táto premenná obsahuje názov cieľa. Ak je cieľov viacero príkaz v ktorom sa nachádza $@ sa vykoná pre každý cieľ samostatne. |
$< | Názov prvého súboru zo závislostí. |
$? | Medzerou oddelené názvy všetkých závislostí ktoré sú potrebné na vytvorenie cieľa. |
Kompletný zoznam automatických premenných obsahuje manuál ku GNU `make'.
S využitím automatických premenných bude náš Makefile vyzerať nasledovne:
CXX = g++ LINK = g++ CXX_FLAGS = -Wall hello: hello_lib.o hello_main.o $(LINK) $? -o $@ hello_lib.o: hello_lib.cpp hello_lib.h $(CXX) $(CXX_FLAGS) -c $< -o $@ hello_main.o: hello_main.cpp hello_lib.h $(CXX) $(CXX_FLAGS) -c $< -o $@
Posledné 2 pravidlá sú takmer identické. V takýchto prípadoch môžeme použiť implicitné pravidlá. Tieto 2 pravidlá môžeme zapísať pomocou implicitných pravidiel takto:
%.o: %.cpp hello_lib.h $(CXX) $(CXX_FLAGS) -c $< -o $@
Znak % môže reprezentovať akýkoľvek reťazec. V tomto prípade make vyhľadá všetky súbory *.cpp a skompiluje ich.
Úvod do problematiky automatickej kompilácie by sme mali za sebou. Pre tých, ktorí by sa chceli viac dozvedieť o GNU Make a Auto Tools som pripravil pár odkazov.
Odkazy
Stručný popis makefile (anglicky)
Manuál k make (anglicky)
Make tutoriál (anglicky)
Seriál o Auto Tools (slovensky)
CMake
CMake alebo Cross Platform Make je určený na vytvorenie natívnych Makefile súborov. Okrem unixových Makefile vie generovať napríklad Windows MSVC projekty, "Borland Makefiles" a ďalšie. Okrem multiplatformovosti sa CMake vyznačuje aj jednoduchou syntaxou a vhodnosťou pre veľké projekty (CMake využíva napr. KDE4).
Syntax CMake je veľmi jednoduchá. Celý súbor sa skladá z CMake príkazov a parametrov. Príkazy a parametre sa zapisujú Príkaz(parametre). Príkazy nie sú citlivé na veľkosť znakov. Komentáre podobne ako v Makefile začíname znakom #.
Ako príklad použijem znova program "Ahoj svet". Adresár s projektom vytvoríme podobne ako pri GNU Make. Namiesto Makefile si vytvoríme súbor CMakeLists.txt s nasledujúcim obsahom:
PROJECT(hello) INCLUDE_DIRECTORIES ("${PROJECT_BINARY_DIR}") ADD_EXECUTABLE(hello hello_lib.cpp hello_main.cpp)
V prvom riadku nastavíme názov projektu. Príkazom INCLUDE_DIRECTORIES
pridáme adresáre v ktorých bude CMake hľadať hlavičkové súbory. Ak by sme neuviedli tento príkaz nemali by sme v závislostiach hlavičkové súbory. Posledným príkazom ADD_EXECUTABLE
špecifikujeme zdrojové súbory potrebné na vytvorenie spustiteľného súboru.
Kompilácia
Pred kompiláciou najskôr vygenerujeme Makefile príkazom:
cmake cesta k adresáru s projektom
Aj keď cmake spúšťame v adresári s projektom musíme zadať cestu k adresáru. Ako cestu zadáme aktuálny adresár (cmake .
). CMake automaticky zistí prítomnosť kompilátora a vytvorí Makefile. Na kompiláciu projektu stačí už len spustiť make
.
V budúcej časti sa budeme zaoberať ďalšími funkciami CMake. Ukážeme si ako pomocou CMake vytvoriť config.h a povieme si niečo o preprocesore a direktívach pre preprocesor kompilátora.
dik :)
I enjoyed reading your articles. This is truly a great experience for me happy wheels
I found a lot of information here to create this actually best for all newbie here. Thank you for this information. outlook entrar
Great post,Thanks for providing us this great knowledge,Keep it up. super mario bros
Thanks to author friv & Madalin Stunt Cars 2