AMIGA REVIEW online
  Uvodná stránka     Software     Hry     Obaly     Download     Kniha návštev     Amiga na PC     Amiga Forever  

ADE: GNU Make 3.75

Jan Skýpala

Utilita make je základní vývojový nástroj programátora na Unixu a mnohých dalších platformách. Ač se začátečníkovi líbí různé project managery jak chtějí, časem stejně přijde na něco, co neumí. Make umí všechno. A GNU Make ještě víc...

Tato definice je poměrně výstižná. Ale hodilo by se asi dodat „ale mocnější než všechny pohodlné.“ Pokud jste nikdy neprogramovali, tak vám musím stručně vysvětlit, co to ta správa programu je.
Čím je program delší, tím je nepraktičtější držet celý zdroják v jednom souboru. Jednak se v něm špatně hledá a ještě navíc se dlouho překládá. Takže větší programy mají většinou více zdrojových souborů a po nějaké změně (přidání nové funkce, odstranění staré chyby apod.) se překládá pouze to, co je zapotřebí.
No a to byla asi základní myšlenka při vzniku utility make (té obecné Unixové verze). Takže bylo třeba zajistit, aby prográmek make uměl poznat to, co je třeba udělat (např. právě které soubory překompilovat).
Make předpokládá, že (většinou) nějaká akce končí vytvořením nějakého souboru, a to na základě souborů jiných. Například u programu soubor xxx vznikne ze souboru xxx.o po linkování a xxx.o vznikne z xxx.c po přeložení překladačem céčka. Soubor xxx.c navíc includuje soubor xxx.h. Pokud tomu tak je, měl by být čas a datum u souboru xxx pozdější než u xxx.o a ten pozdější než u xxx.c a xxx.h. A to je přesně princip, podle kterého utilita make rozhoduje, co je třeba udělat.
Když make spustíte, tak načte soubor Makefile a tam předpokládá uložení závislostí (tedy který soubor je závislý na kterém) a co má provádět. Následující příklad řekne více:
xxx.o: xxx.c xxx.h
gcc -c xxx.c -o xxx.o
První řádek znamená, že soubor xxx.o má mít pozdější čas uložení než soubory xxx.c a xxx.h. Druhý řádek obsahuje, co se má udělat, když tomu tak není - zde spuštění GNU C překladače.
Řádků s příkazy může být za sebou pochopitelně více, celá sekvence bude ukončena buď prázdným řádkem nebo dalším řádkem se závislostmi. Co je ovšem u unixových make utilit a GNU make podmínkou, že řádek s příkazem začíná tabulátorem; pozor - mezera (32 ASCII) není tabulátor (9 ASCII). smake (z SAS/C) vystačí se dvěmi mezerami, dmake (DiceC) nepotřebuje ani jednu.
Čistě teoreticky vám výše uvedené stačí k rozumnému používání prográmku make. Pokud ale např. chcete dát někomu archiv se zdrojákem svého programu, může se stát, že bude mít úplně jiný překladač céčka, než vy, a bude ho muset úplně všude v souboru Makefile přepsat (třeba všude změnit gcc na lcc). Aby to nebylo tak obtížné, lze v Makefile zavést proměnné.
Takže změňme náš malý příkládek na:
CC = gcc xxx.o: xxx.c
xxx.h $(CC) -c xxx.c
-o xxx.o
První řádek nám zavede proměnnou CC, do které uložíme jméno překladače. A na třetím řádku ji před vyvoláním příkazu make vyhodnotí, takže volaný řádek bude vypadat úplně stejně, jako předtím. Takže až bude váš kamarád chtít překompilovat vaše programy svým (jiným) překladačem, změní jediný řádek, a to ten, kde definujete proměnnou CC.
Proměnné se samozřejmě používají na všechno možné, např. i pro zadání parametrů pro překladač. Tato proměnná má doporučené jméno CPPFLAGS a v ní by měla být např. uvedená optimalizace nebo cílový procesor. Takže řádek vyvolávající překlad by měl být:
$(CC) $(CPPFLAGS) –c
xxx.c -o xxx.o
GNU make nemusí mít tyto proměnné definovány v souboru Makefile. Pokud tam nejsou, převezme je ze shellu. Takže doporučuji přidat si do user-startup řádek „Set CC gcc“ a podobně.
Tímto místem končí kompatibilita s dmake (DiceC). Některé následující věci dmake ještě umí, ale má jinou syntaxi.
Náš řádek zajišťující překlad lze ještě zkrátit. Make umí proměnné, které jsou při spouštění příkazu nahrazovány údaji z definice závislosti. Konkrétně tedy proměnná $@ bude rozvinuta na jméno cílového souboru (xxx.o). Proměnná $? bude rozvinuta do všech zdrojových souborů (xxx.c xxx.h). A proměnná $< bude rozvinuta do prvního zdrojového souboru (xxx.c).
Takže náš řádek pěkně zkrátíme na
$(CC) $(CPPFLAGS) -C
$< -o $@.
Jak je vidět, v tomto řádku není jediné konkrétní jméno, a tak je zřejmé, že ho lze nakopírovat za každou závislost pro překlad céčkovského zdrojáku na objekt. Jen je nutné dát si pozor, aby vždy jako první zdrojový soubor byl uveden skutečný zdroják pro daný objekt (omylem by se vám tam mohl připlést třeba nějaký *.h).
Některé make utility umí i takzvaná implicitní pravidla. Ta jsou použita, pokud v Makefile neuvedete, co má make dělat. GNU make jich umí spousty a smake přinejmenším jedno: jak vytvořit *.o soubor z *.c souboru. O odstavec výše zmíněné zkrácení řádku je přesně tím příkazem, který volá GNU make, SAS/C má volání $(CC) $<. Závislost je pochopitelně *.o: *.c, GNU make nám ale navíc umožňuje definovat ještě další závislosti (někde jinde v Makefile souboru). To znamená, že pro GNU make stačí správně nastavit hodnoty $(CC) a $(CPPFLAGS) a uvést řádek „xxx.o: xxx.c xxx.h“ a bude to fungovat přesně tak, jak si přejeme.
Tak a zde končíme i s kompatibilitou s smake (SAS/C). Následující vlastnosti smake neumí (nebo jsem přinejmenším nepřišel na to jak). dmake první z nich umí, ale zápis je jiný. Ovšem co nám brání používat všemocný GNU make i s DiceC nebo SAS/C?
Jak je výše uvedeno, mohli jsme v smake vypustit pravidlo pro céčkovský překlad, pokud byl objekt závislý pouze na svém zdrojáku, a v GNU make jsme mohli takovéto pravidlo vypustit úplně. Ne pro všechny typy závislostí zná make pravidla a proto lze v GNU make udělat pravidlo obecné pro daný typ podle masek zdrojového a cílového souboru. Znaky % musí odpovídat v obou částech. Tak tedy např. GNU make pochopitelně nic netuší o programovacím jazyce AmigaE, ale pravidlo
%: %.e EC:ec $< OPTIMIZE
způsobí, že bude-li muset vytvořit nějaký soubor, k němuž na disku existuje soubor s příponou .e, bude automaticky vědět jak na to.
Ještě ale musím zmínit jeden rozdíl mezi smake + dmake a unixovskými make (včetně GNU make). smake a dmake, pokud je spustíte jen tak, bez parametru, budou za hlavní cíl považovat to, co je výsledný soubor u první závislosti v Makefile. Unixové make utility naopak budou dělat to, co je uvedené u závislosti „all:“ To, že se při kompilaci žádný soubor se jménem all nevytvoří, vůbec nevadí.
Závislosti, které nemají žádné zdrojové soubory, by se normálně nevykonávaly. Prostě vytvářený soubor (i třeba neexistující) bude vlastně vždy novější. Proto na začátek Makefile uveďte řádky, kde bude pro každou závislost, která nemá žádné zdrojové soubory, uvedeno: „.PHONY : target“ (přičemž target je ona závislost). V Makefile souborech se většinou vyskytuje takovýchto závislostí více a když spustíte make se jménem závislosti, bude provádět ji, a ne tu se jménem all. Závislost nazvaná clean většinou smaže všechny soubory vytvořené kompilací, závislost install nainstaluje program tam, kam má a podobně.
Nyní by se hodilo nějak vymyslet generování závislostí, aby to člověk nemusel psát do Makefile souboru ručně. To není zase až tak složité. Céčkovské preprocesory na unixu (včetně preprocesoru u GNU C) při direktivě -M místo normální činnosti vypíšou závislosti. GNU C preprocesor navíc s direktivou MM vypíše pouze závislosti na nesystémových header souborech.
Dobrá, teď umíme závislosti vygenerovat, ale jak je přidat do Makefile souboru? Dříve se to řešilo tak, že v Makefile byla položka depend, která způsobila vygenerování závislostí do souboru, a pak tento soubor připojila ke starému Makefile a mohlo se provést normální make. To je samozřejmě nepříjemné, musíte make volat dvakrát. V GNU make to lze vyřešit takto: Nejdříve si zaveďme pravidlo, které nám pro každý céčkovský zdroják vygeneruje soubor s příponou .d (místo .c) se závislostí:
%.d: %.c /bin/sh –ec
„$(CC) -MM $(CPPFLAGS)
$< > $@“
Mějme v proměnné SOURCES zadefinované všechny céčkovské zdrojáky, pak interpretace $(SOURCES:.c=.d) nám udělá všechny soubory s příponou .d a direktivou include tyto soubory do Makefile přidáme:
include $(SOURCES:.c=.d)
Nazvěme nějak výsledný spustitelný soubor (já preferuji main, ale vy můžete mít lepší název). Dejme ho do proměnné BUILD a nastavme pro all: závislost právě na $(BUILD). Do proměnné OBJECTS dejme všechny objekty (soubory zkompilované z céčkovských zdrojáků). Do proměnné LOADLIBES dejme jména všech linkovaných knihoven (pokud budete linkovat pomocí gcc nebo ld a používáte přitom nějaké vymoženosti C++, přilinkujte knihovnu stdc++). Do proměnné LDOPTS dejme parametry pro linkování (třeba -s) a přidejme pravidlo:
$(BUILD): $(OBJECTS)
$(CC) $(LDOPTS) $? -o
$@ $(LOADLIBES)
Nyní máme Makefile který nám pro sadu uvedených objektů, k nimž existují zdrojáky, bude pracovat až k vytvoření spustitelného souboru. A blížíme se do finiše. Poslední co nám zbývá, je zajistit, aby si make našel všechny céčkovské zdrojáky na disku sám. Tím vytvoříme potencionálně nezávislý Makefile použitelný pro jakýkoliv jednodušší program v céčku.
Bylo by chyba dát OBJECTS = *.o - v momentu, kdy bude program rozdělaný a bude se znovu a znovu kompilovat, je vše v pořádku. Ale po smazání všech souborů s příponou .o by make přestal pracovat, protože proměnná OBJECTS by byla prázdná. Takže můžeme dát SOURCES = *.c a na další řádek OBJECTS = $(SOURCES:.c=.o), ale ještě lepší bude použít přímo funkce GNU make a vytvořit si proměnnou OBJECTS takto:
OBJECTS = $(pathsubst %.c, %.o,$(wildcard *.c))
funkce wildcard nám najde všechny soubory podle dané masky a funkce pathsubst potom v nich provede změnu z .c na .o.
Tak teď už skutečně máme dosti dobrý Makefile, který vám bude, doufám, dlouho sloužit. Celý je vylistovaný vedle článku, takže vám stačí si ho jen opsat a můžete programovat a téměř se nestarat o správu programu.
Doufám, že každý pochopil, v čem je síla make. To co jsem tady vysvětloval, může vypadat jako přesně to, co umí i ty různé project managery u takzvaných integrovaných prostředí, ale make je obecný. Nemusíte spouštět jenom překladač céčka, ale cokoliv. Do Makefile si můžete dát třeba i generování dokumentace (často se používá formát TeXinfo, z něhož se pak generuje jak manuál, tak online he/p). Pokud pracujete s gramatikami, make může automaticky spouštět lex nebo yacc. A tak podobně.
GNU make toho samozřejmě umí mnohem více, např. podmíněné části souboru Makefile. Takže si například můžete přímo do Makefile zahrnout jaké pravidlo má použít při daném překladači apod. Velice oblíbené a mocné je také volat make rekurzivně, tzn. spustit z Makefile znovu make např. na některý podadresář.
Ještě pár poznámek na závěr. Pokud používáte nějaké specifické funkce nějaké make utility, místo Makefile použijte specifické jméno, které daná verze zná a preferuje, zatímco ostatní make utility ji vůbec nepoužijí. U GNU make je to GNUmakefile (pozor, záleží na velkých a malých písmenech), u smake smakefile, u dmake dmakefile. GNU make najdete na jakémkoliv serveru s ADE archivem, např. ftp.grolierfr/pub/amiga/ade/current/amiga-bin/make-3.75bin.lha
A jako vždycky si dobře pročtěte dokumentaci. Guide k GNU make má skoro 400kB a najdete v něm úplně všechno.

Univerzální GNU makefile pro jednodušší céčkovské programy
(poznámka: pro zdrojáky v C++ doporučuji používat příponu .cc, GNU make pak sám zná implicitní pravidlo):
# Universal GNUmakefile by Jan Skypala .PHONY: clean
# what to do: BUILD = main
# System configuration SHELL = /bin/sh
# System environment CC = gcc CXX = g++
CPPFLAGS = LDFLAGS = -s LOADLIBES = -lstdc++
OBJ = $(patsubst %.cc, %.o,$(wildcard *.cc))
$(patsubst %.c, %.o,$(wildcard *.c))
all: $(BUILD)
clean: rm -f $(BUILD) $(BUILD:%=%.o)
$(BUILD:%=%.d)
%.d: %.c $(SHELL) -ec „$(CC) -MM $(CPPFLAGS) $< | sed s!$*.o: *!$*.o $@: !g > $@“
%.d: %.cc $(SHELL) -ec „$(CXX) -MM $(CXXFLAGS) $(CPPFLAGS) $< | sed s!$*.o: *!$*.o $@: !g > $@“
include $(BUILD:%=%.d) #END OF FILE#

GNU Make

Hodnocení: 9,5 z 10
Autor: FSF
Typ: freeware

+

plně kompatibilní s UNIXovým maker mnohem více funkcí; zadarmo

-

není pro začínající programátory

Vytlačiť článok


© ATLANTIDA Publishing Všechna práva vyhrazena.
Žádna část nesmí být reprodukována nebo jinak šířena bez písemného svolení vydavatele.



Amiga na Vašem PC rychle, snadno a zdarma!


none

AMIGA REVIEW

57 ( 11-12 / 2000 )
56 ( 9-10 / 2000 )
55 ( 7-8 / 2000 )
54 ( 5-6 / 2000 )
53 ( 3-4 / 2000 )
52 ( 1-2 / 2000 )
 
51 ( 12 / 1999 )
50 ( 11 / 1999 )
49 ( 10 / 1999 )
48 ( 9 / 1999 )
46-47 ( 7-8 / 1999 )
45 ( 6 / 1999 )
44 ( 5 / 1999 )
43 ( 4 / 1999 )
42 ( 3 / 1999 )
41 ( 2 / 1999 )
40 ( 1 / 1999 )
 
39 ( 12 / 1998 )
38 ( 11 / 1998 )
37 ( 10 / 1998 )
36 ( 9 / 1998 )
35 ( x / 1998 )
34 ( x / 1998 )
33 ( 1-2 / 1998 )
 
32 ( 11-12 / 1997 )
31 ( 9-10 / 1997 )
30 ( 7-8 / 1997 )
29 ( 6 / 1997 )
28 ( 5 / 1997 )
27 ( 4 / 1997 )
26 ( 3 / 1997 )
25 ( 2 / 1997 )
24 ( 1 / 1997 )
 
23 ( 12 / 1996 )
22 ( 11 / 1996 )
21 ( 10 / 1996 )
20 ( 9 / 1996 )
18-19 ( 7-8 / 1996 )
17 ( 6 / 1996 )
16 ( 5 / 1996 )
15 ( 4 / 1996 )
14 ( 3 / 1996 )
13 ( 2 / 1996 )
12 ( 1 / 1996 )
 
11 ( 12 / 1995 )
10 ( 11 / 1995 )
9 ( 10 / 1995 )
8 ( 9 / 1995 )
7 ( 7 / 1995 )
6 ( 5 / 1995 )

ATLANTIDA NEWS

5 ( 3 / 1995 )
4 ( 1 / 1995 )
 
3 ( 11 / 1994 )
2 ( 9 / 1994 )
1 ( 7 / 1994 )
0 ( 5 / 1994 )