nástroj make
, konfiguračný súbor Makefile
V prvom zadaní, do ktorého sa tento týždeň pustíte, budete mať okrem iného za úlohu vytvoriť dva samostatné moduly. Aby ste ich zvládli vytvoriť a správne manažovať, naučíte sa na tomto cvičení konfigurovať nástroj make
pomocou jeho konfiguračného súboru Makefile
. Táto znalosť vám v budúcnosti pomôže pri práci na rozsiahlejších projektoch, ktoré sa budú skladať z viacerých samostatných modulov.
Makefile
Makefile
V prvom kroku si vytvoríte nový projekt na GitLab-e, do ktorého budú postupne pribúdať vaše zadania.
Prihláste sa na GitLab a vytvorte si nový projekt s názvom prog-2018
.
Poznámka
Nezabúdajte, že záleží na veľkosti písmen! Ak sa názov vášho projektu nebude volať presne prog-2018
, Aréna ho nebude vedieť identifikovať a tým pádom ani vyhodnotiť.
Súčasťou projektu je aj súbor README
, ktorý obsahuje len jeden riadok s informáciou o skupine, ktorú navštevujete na cvičeniach v tvare:
GROUP : A1
Pokiaľ len skopírujete a vložíte postupnosť príkazov priamo z GitLab-u, nezabudnite súbor README.md
premenovať na súbor README
.
Zo stránky so zadaním projektu K si stiahnite jeho kostru.
Pokiaľ poznáte adresu súboru na stiahnutie, môžete si ho stiahnuť pomocou príkazu wget
v tvare:
kde URL
je adresa súboru na stiahnutie. Súbor sa následne stiahne do priečinka, v ktorom ste tento príkaz zadali.
Pre rozbalenie zip
balíku môžete s výhodou použiť konzolový nástroj unzip
v tvare:
kde FILE
je názov, resp. cesta k zip
balíku na rozbalenie.
Vytvorte si vo svojom projekte priečinok ps1/
a prekopírujte do neho všetky potrebné súbory z kostry zadania K.
Presná podoba štruktúry projektu tohto zadania sa nachádza na stránke požiadaviek. Ak následne sputíte príkaz tree
nad priečinkom projektu prog-2018
, jeho výstup by mal vyzerať nasledovne:
$ tree prog-2018
prog-2018/
├── ps1
│ ├── hof.h
│ ├── k.c
│ ├── k.h
│ ├── main.c
│ ├── Makefile
│ └── score
└── README
1 directory, 8 files
V priečinku projektu ps1/
vytvorte kostru súboru main.c
.
Súbor main.c
bude obsahovať hlavnú funkciu programu main()
. V tejto funkcii si vytvorte premennú hracieho poľa typu struct game
a priraďte úvodné hodnoty jednotlivým prvkom záznamu. Tento typ je zadefinovaný v súbore k.h
.
V hlavnej funkcii programu zavolajte funkciu add_random_tile()
, ktorej deklarácia sa nachádza v súbore k.h
a definícia sa nachádza v súbore k.c
. Funkcia pridá do hracieho poľa písmeno na náhodnom mieste.
Výsledná podoba súboru main.c
môže teda vyzerať nasledovne:
#include "k.h"
#include "hof.h"
int main(){
struct game game = {
.board = {
{'A', ' ', 'A', ' '},
{'A', ' ', 'A', ' '},
{'A', ' ', 'A', ' '},
{'A', ' ', 'A', ' '}
},
.score = 0
};
add_random_tile(&game);
}
Poznámka
Ak pridáte do svojho projektu nový súbor, je dobrým zvykom ho pridať rovno aj do git projektu pomocou príkazu
git add FILE
Preložte a spustite projekt.
Program sa pokúste preložiť pomocou prekladača gcc
spolu so zoznamom všetkých prepínačov, ktoré sú uvedené na stránke zadania. Výsledný spustiteľný súbor nech sa volá jednoducho game
.
Aktualizujte svoj projekt na git-e.
Okrem pridania súborov do lokálneho repozitára nezabudnite váš aktualizovaný projekt odoslať aj do vzdialeného repozitára. Obsah priečinka ps1/
vášho projektu by sa momentálne mal zhodovať s požadovanou podobou projektu, ako je uvedená na stránke zadania.
V tomto kroku si vytvoríte svoj vlastný súbor Makefile
, ktorý bude predstavovať konfiguráciu pre nástroj make
. Skladá sa zo zoznamu cieľov (z angl. target) a premenných. Tento súbor sa používa hlavne vtedy, ak pracujete na programe, ktorého kód je uložený vo viacerých súboroch, ako len v jednom.
Vytvorte v súbore Makefile
cieľ all
, pomocou ktorého bude možné preložiť celý program. Súbor Makefile
sa skladá z niekoľkých cieľov, pomocou ktorých je možné zadefinovať príslušné správanie.
Všeobecná štruktúra cieľa vyzerá nasledovne:
pričom:
TARGET
je názov cieľa,DEPENDENCIES
je zoznam závislostí pre zostavenie daného cieľa, aSYSTEM_COMMAND1
až SYSTEM_COMMANDn
je zoznam príkazov, ktoré sa majú v rámci daného cieľa vykonať.Upozornenie
Je veľmi dôležité, aby prvý znak pred každým príkazom bol znak tabulátor. Ak sa tam bude nachádzať znak medzera, súbor Makefile
nebude valídny a nástroj make
skončí s chybou.
Vašou úlohou je vytvoriť cieľ s názvom all
. V rámci príkazov, ktoré tvoria telo tohto cieľa zabezpečte preloženie programu podobne, ako ste to vykonali v predchádzajúcom kroku.
Poznámka
V tejto úlohe nemusíte použiť žiadnu závislosť a nechajte tak zoznam závislostí prázdny.
Overte funkčnosť vytvoreného cieľa.
Funkčnosť overíte spustením príkazu make
nasledovne:
kde TARGET
je názov cieľa, ktorý chcete spustiť.
Ak ste postupovali správne, po spustení príkazu make
dôjde k preloženiu programu a vytvoreniu spustiteľného súboru game
.
Poznámka
Ak pri spúšťaní príkazu make
neuvediete žiadny cieľ, použije sa prvý cieľ v poradí, ktorý sa v súbore Makefile
nachádza.
Vytvorte v súbore Makefile
tri ďalšie ciele main.o
, k.o
a hof.o
, pomocou ktorých sa program čiastočne preloží, čím vziknú tri rovnomenné objektové súbory. Upravte cieľ all
tak, aby vzniknuté objektové súbory spojil (zlinkoval) do spustiteľného súboru game
.
Aktuálne nám cieľ all
umožňuje preložiť celý program naraz. Na základe troch súborov .c
si však môžete všimnúť, že program pozostáva z troch modulov: main
, k
a hof
.
Každý z týchto modulov je možné preložiť samostatne, čím sa vytvorí tzv. objektový súbor. Spojením objektových súborov je možné vytvoriť spustiteľný súbor.
Vytvorte tri nové ciele main.o
, k.o
a hof.o
, pomocou ktorých bude možné preložiť daný modul programu. Výsledkom bude objektový súbor .o
. K prekladu použite prepínač -c
.
Poznámka
Prepínač -c
umožňuje preložiť program bez spojenia (prelinkovania) zdrojových súborov. Výstupom takého prekladu je objektový súbor.
Upravte cieľ all
tak, aby k prekladu použil objektové súbory. Spojením týchto súborov vznikne spustiteľný súbor game
.
Overte funkčnosť všetkých cieľov.
Poznámka
Všimnite si, že k prekladu dôjde zakaždým, keď príkaz make
spustíte.
Aktualizujte cieľ all
tak, aby k prekladu došlo len vtedy, ak sa niektorý zo súborov obsahujúcich zdrojové kódy aktualizuje.
V predchádzajúcej úlohe pri zostavovaní cieľa neboli použité žiadne závislosti. Závislosti je vo všeobecnosti možné charakterizovať ako súbory, ktoré sú potrebné pre zostavenie daného cieľa. V prípade, ak sa niektorá zo závislostí aktualizuje, nástroj make
daný cieľ zostaví (preloží program). Ak pri jeho použití nedošlo k aktualizácii žiadnej závislosti (všetky súbory sú aktuálne), výsledný cieľ nebude zostavený.
Poznámka
Závislosti sa s výhodou používajú v prípadoch, ak zostavujete viacero cieľov. Ak následne urobíte zmenu v jednom súbore, nepotrebujete znovu prekladať všetky súbory, ale preložené budú len tie ciele, ktorých sa táto zmena dotkne.
Ako závislosti v tomto prípade použite všetky súbory, ktoré sa podieľajú na zostavení výsledného spustiteľného programu.
Overte funkčnosť aktualizovaných cieľov a pridajte cieľ game
.
Ak spustíte príkaz make
s cieľom hof.o
alebo k.o
tentokrát, k prekladu dôjde len vtedy, keď sa zmení niektorý zo súborov uvedených ako závislosti.
Avšak ak spustíte príkaz make
s cieľom all
, stále dôjde k prekladu, aj keď sa súbory v závislostiach nezmenili. Dôvodom je to, že nástroj make
sa snaží nájsť súbor s rovnakým názvom, aký je názov cieľa, t.j. all
.
Vytvorte preto nový cieľ s rovnakým názvom, aký má výstup celého prekladu: game
. Tento cieľ bude mať rovnaké závislosti ako cieľ all
a po jeho zavolaní sa vykoná rovnaká operácia. Pôvodný cieľ all
potom zmeňte tak, aby sa priamo odvolával na nový cieľ game
.
Overte funkčnosť aktualizovaného cieľa all
. K prekladu by malo dôjsť iba ak došlo k zmene v niektorom zo súborov.
Nahraďte v príkaze na preklad meno prekladača, zoznam jeho prepínačov a zoznam potrebných knižníc pomocou premenných.
Použitie premenných v súbore Makefile
je výhodné v situáciách, keď definujete viacero cieľov, poprípade máte zadefinovaných viacero príkazov pri jednom cieli. Jednoducho tak môžete zmeniť alebo aktualizovať napr. prekladač, zoznam jeho parametrov alebo knižníc požadovaných pri preklade.
Vytvorte preto v súbore Makefile
tieto premenné:
CC
- názov, resp. absolútna cesta k prekladačuCFLAGS
- zoznam prepínačov pre prekladačLDLIBS
- zoznam knižníc potrebných pre prekladOUTPUT
- názov výsledného spustiteľného súboruInicializácia premennej vyzerá podobne ako v jazyku C, akurát nie je potrebné uvádzať jej typ:
Na mieste, kde chcete použiť hodnotu premennej, zapíšete túto premennú v tvare:
Poznámka
V súbore Makefile
je možné rovnako používať aj komentáre. Makefile
podporuje len jednoriadkové komentáre a riadok, ktorý začína znakom '#'
bude ignorovaný. Poprípade ignorovaná bude aj časť riadku za týmto znakom.
Overte funkčnosť aktualizovaných cieľov.
Pokiaľ ste postupovali správne, funkcionalita zostane nezmenená.
Pridajte pred príkaz s prekladom statickú kontrolu kódu pomocou nástroja cppcheck
a overte funkčnosť vašej úpravy.
Ako bolo uvedené vyššie, v jednom pravidle sa môže nachádzať aj viac príkazov ako len jeden. Ak sa tak stane, tak v prípade, že dôjde pri vykonávaní niektorého príkazu ku chybe (návratový kód príkazu bude iný ako 0), žiadne ďalšie príkazy sa nebudú vykonávať. Túto vlastnosť je teda možné úspešne zahrnúť aj do procesu prekladu, kedy pred samotným prekladom použijeme nástroje napr. na statickú analýzu kódu alebo na jeho formátovanie a až potom sa vykoná samotný preklad.
Nástroj cppcheck
slúži na statickú analýzu kódu. Pri kontrole zadaní sa cppcheck
bude používať nasledovne:
V tomto poslednom kroku vytvoríte cieľ, pomocou ktorého vyčist��te projekt od nepotrebných súborov. Pri preklade totiž budú vznikať rozličné súbory ako medzivýsledky prekladu. Vytvoríte preto cieľ clean
, pomocou ktorého tieto súbory zmažete.
Vytvorte cieľ clean
, pomocou ktorého zmažete z disku spustiteľný súbor game
a všetky ostatné objektové súbory .o
.
Poznámka
Pri zostavovaní pravidla nezabudnite s výhodou použiť premennú OUTPUT
.
Upozornenie
Dajte si pozor, aby ste nesprávnym zápisom tohto cieľa nezmazali všetky súbory nachádzajúce sa vo vašom projekte!
Overte funkčnosť vytvoreného cieľa.
Ak ste postupovali správne, po spustení príkazu make
s cieľom clean
dôjde k odstráneniu spustiteľného súboru game
z disku vrátane všetkých objektových súborov.
make
(a súboru Makefile
)