Obsah
Novinky
Zverejnili sme seriál článkov Auto Tools, ktorý vychádzal na stránkach PC Revue v číslach 01/2002 - 04/2003.
Auto Tools
Seriál článkov o sade nástrojov pre vývojárov na platforme Unix (Linux) je uvoľnený pod Open Source licenciou. Ak začínate s vývojom aplikácií na spomínaných platformách, iste sa vám tieto články zídu.
6. časť: Podmienky, vetvenie Makefile
V tejto časti si povieme niečo o podmienkach, podobných tým, ktoré poznáte zo svojho obľúbeného jazyka (nech už je to C/C++, Bash, PHP alebo čokoľvek iné). V princípe ide o zistenie nejakého faktu (podmienky), na základe ktorého sa rozhodneme, ako budeme pokračovať ďalej. V praxi pri tvorbe Makefile to môže vyzerať napríklad takto: zistíme, či na danom systéme existuje požadované knižnica. Ak áno, program zlinkujeme s ňou. Ak nie, môžeme sa pokúsiť nájsť nejakú alternatívu. Ak ani potom neuspejeme, program neskompilujeme a/alebo o tomto probléme informujeme používateľa. Ide teda o akúsi analógiu k príkazom if a else z jazyka C. Podmienky ovládajú to, čo make "uvidí", nemožno ich teda použiť v shell príkazoch v čase behu.
Nasledujúci príklad je praktickou ukážkou použitia podmienok. V závislosti od toho, či je premenná CC nastavená na "gcc", použije jeden z dvoch príkazov na zlinkovanie objektov:
program: $(OBJECTS)
ifeq ($(CC),gcc)
$(CC) -o program $(OBJECTS) -lgnu
else
$(CC) -o program $(OBJECTS)
endif
Teraz si ukážku vysvetlíme. Kompiláciu spustíme príkazom
make CC=gnu
alebo
make CC=iny_prkladac
Musíme teda zadať názov nášho prekladača. Príklad samozrejme nie je kompletný, chýbajú mu minimálne pravidlá na vytvorenie objektov, definovanie mien týchto objektov, definícia pravidla all a pár iných vecí, ktoré by ste však mali byť schopní napísať už sami. Pravidlo program má ako príkazy na vytvorenie samotného programu (teda v našom prípade ide o zlinkovani objektov). Príkaz ifeq je však nový. Na čo asi môže byť? Pomôže "rozklad" tejto skratky do angličtiny - if equal, teda "ak sú zhodné". Zhodné by mali byť, samozrejme, parametre uvedené v zátvorkách. Prvým je premenná CC, ktorú musíme uviesť ako parameter pri spúštaní programu make. Je zrejmé, že ju rovnako môžeme určiť aj vnútri súboru ako každú inú prmennú. Druhý parameter je konštanta - reťazec. Ako parametre príkazu ifeq môžeme uvádzať iba tieto dva typy (konštanty a premenné).
Na nasledujúcom riadku je príkaz, ktorý zlikuje objekty použitím kompilátora gcc, pričom použije fiktívnu knižnicu libgnu (parameter -lgnu). Nasleduje ďalšie kľúčové slovo else (po slovensky "inak"). Príkazy medzi ním a slovíčkom endif sa vykonajú, ak podmienka nebola splnená. V tomto druhom príkaze už nepoužívame knižnicu libgnu, prtože (napríklad) ju iné kompilátory nepoužívajú. Kľúčové slovo endif nám uzatvára celú časť s podmienkou.
Ako vidno z našej ukážky, podmienky pracujú na textovej úrovni porovnania dvoch reťazcov, ktoré sú najprv podrobené substitúcii (o tom sme si už písali). Rovnako na textovej úrovni prebieha aj spracovanie podmienených (teda vnorených) príkazov - príkazy v časti, ktoré vyhovuje podmienke, jednoducho ostanú tam, kde boli, ale tá časť, ktorá nevyhovuje, sa zmaže. Takto môže jedno pravidlo prechádzať cez viacero podmienok a naopak, jedna podmienka cez viacero pravidiel.
Program by sme mohli aj mierne obmeniť a dostali by sme taký istý výsledok:
ifeq ($(CC),gcc)
libs=-lgnu
else
libs=
endif
program: $(OBJECTS)
$(CC) -o program $(OBJECTS) $(libs)
Teraz bude premenná libs obsahovať názov používanej knižnice v závislosti od použitého prekladača. Príkaz, ktorým program zlinkujeme, však napíšeme iba raz s tým, že použijeme spomenutú premennú.
Podmienka môže byť napísaná viacerými spôsobmi:
ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
Pomerne často môže nastať situácia, keď potrebujete zistiť, či je daná premenná prázdna alebo nie. Problém by mohol nastať v prípade, že vy považujete reťazec, ktorý obsahuje iba pár medzier za prázdny, zatiaľ čo make má na to iný názor. Tu si pomôžeme funkciou strip, ktorá odstráni prebytočné medzery (viac o funkciách na prácu s textom nabudúce). Malý príklad:
ifeq ($(strip $(premenná)),)
príkazy
endif
Príkazy sa vykonajú, ak je premenná prázdna alebo ak obsahuje tzv. "biele znaky" (znaky, ktoré sa na tlačiarni nevytlačia a na papieri ostane iba biele miesto - teda medzera, tabelátor, prechod na nový riadok, atď.).
ifneq (arg1, arg2)
Podmienka je splnená, ak reťazce nie sú zhodné. Ide teda o akýsi obrátený príkaz k príkazu ifeq.
ifdef premenná
Podmienka je splnená, ak premenná bola definovaná. Nedefinované premenné majú prázdnu hodnotu. Pozor - substitúcia nenastáva pri definícii ihneď. Ak jednej premennej priradíme hodnotu druhej, ktorá je prázdna, tá prvá premenná sa za prázdnu rátať nebude! Znova malý príklad:
premenná1 =
premenná2 = $(premenná1)
ifdef premenná2
príkazy1
else
príkazy2
endif
V tomto príklade sa vykonajú príkazy 1 a nie príkazy 2! Ak by sme chceli dosiahnuť opačný výsledok, mohli by sme použiť funkciu ifeq:
premenná1 =
premenná2 = $(premenná1)
ifeq ($(strip $(premenná)),)
príkazy1
else
príkazy2
endif
Teraz by malo prebehnúť všetko podľa našich očakávaní.
ifndef premenná
Podmienka je splnená, ak premenná nebola definovaná.
V týchto direktívach sú povolené nadbytočné medzery - budú ingorované. Avšak tabelátor sa na začiatku riadka vyskytovať nesmie! To je výsadou shell príkazov vo vnútri pravidiel. V samotnej podmienke sa tieto biele znaky vyskytovať môžu. Na konci riadka sa môže vyskytovať komentár (začínajúci znakom #). Podobne je to aj s dirktívami else a endif. Na začiatku je povolené neobmedzené množstvo medzier, na konci môžete pokojne pridať aj tabelátor a komentár. Ešte si dovolím jednu dosť dôležitú poznámku - v podminkach nesmiete použiť automatické premenné! O nich sme si už čo-to napísali v minulých číslach. Aby sa predišlo zmätkom, je zakázané začať podmienku v jednom súbore a ukončiť ju v inom (vloženom). Vkladať súbory pomocou "include" uprostred podminky je povolené za predpokladu, že vložený súbor neukončí danú podmienku.
Na konci nášho výkladu o podmienkach si ešte povieme pár slov o testovaní prítomnosti parametrov, s ktorými bol make spustený. Použijeme pritom premennú MAKEFLAGS. Ďalej použijeme funkciu findstring, ktorá zistí prítomnosť jednej premennej v druhej. Ako príklad si uvedieme detekciu parametra -t, ktorý spôsobí, že súbory, ktoré by sa mali generovať, budú mať iba upravenú časovú známku (timestamp).
all: program
program: 1.c 2.c
ifneq (,$(findstring t,$(MAKEFLAGS)))
+echo "nič sa nedeje..."
else
$(CC) -o program 1.c 2.c
endif
Príklad je naozaj veľmi jednoduchý a asi nie veľmi použiteľný, ale na ukážku stačí. Ak spustíme make s parametrom -t, vykoná sa prvý príkaz, inak sa program skompiluje a zlinkuje.
Oto Komiňák
Článok bol uverejnený v magazíne PC Revue 06/2002.
