MakeA make egy programfordításra kifejlesztett segédprogram: a forrásprogramokból előállítja a végrehajtható programo(ka)t. Csak a szükséges műveleteket végzi el: azokat a forrásprogramokat fordítja le, melyeket még nem fordított le, vagy melyek az utolsó fordítás óta változtak. A make nemcsak programfordításra használható, hanem minden olyan feladatra, ahol fájlokból más fájlokat kell előállítani. Unix operációs rendszerre fejlesztették ki, de azóta más rendszerekben is megtalálható. A make a fájlok dátumából állapítja meg, hogy szükséges-e a fordítás. Tartalmaz beépített szabályokat az ismert programnyelvek számára, de saját szabályok is megadhatók, ill. a beépítettek helyettesíthetők saját szabályokkal. A make programot rendszerint paraméter nélkül hívjuk. A fordításhoz szükséges tennivalók az aktuális könyvtárban, a Makefile nevű fájlban vannak. Formai szabályokMakefile-ban
A make működésePélda Makefile-ra: proba : proba.c
gcc -o proba proba.c
A fenti példa egyetlen szabályt tartalmaz. A szabály első sorában a kettősponttól balra álló szó a cél, a jobbra álló az előfeltétel. Több cél és több előfeltétel adható meg helyközzel elválasztva.[1] A szabály következő sora(i) a célt előállító utasítás(ok). Fontos, hogy az utasítások tabulátorral (és nem helyközökkel) kezdődnek: a make innen tudja, mely sorok tartoznak a szabályhoz. Az utasítások elmaradhatnak, ha van olyan implicit szabály, mely a célt elő tudja állítani (pl. a kiterjesztése alapján). Az előfeltételek is elmaradhatnak: ilyenkor az utasítások mindenképpen végrehajtódnak. A make hívósorában cél(ok) adható(k) meg paraméterként. Ha nincs paraméter, az első szabály hajtódik végre, ami tipikus esetben az összes célt előállítja. A célok fájlok (hacsak mást nem adunk meg: lásd a .PHONY utasítást). Az előfeltételek más szabályok célfájljai, ill. ha nem létezik ilyen szabály, akkor normál fájlok. Az előfeltétel ellenőrzéséhez a make végrehajtja az előfeltétel-fájlt létrehozó szabályt (hogy ellenőrizze, nem kell-e újra létrehozni), ill. ha nincs ilyen szabály, de normál fájl igen, akkor összehasonlítja a célfájl és az előfeltétel-fájl dátumát. Ha a cél régebbi, mint a fájl, akkor a célt újra létre kell hozni, azaz végre kell hajtani az utasításait, ellenkező esetben nincs tennivaló: a cél az adott előfeltétel szempontjából naprakész. Ha sem szabálya, sem normál fájlja nincs az előfeltételnek, akkor a szabály befejeződik, és hibával visszatér az őt hívó szabályhoz. A make a fenti módon egymás után ellenőrzi a szabály összes előfeltételét. Egy szabálynak háromféle végeredménye lehet:
UtasításokFontos, hogy a make a szabály utasításait soronként külön-külön shellben hajtja végre. Pl. a külön sorba írt A make minden utasítássor után ellenőrzi a shelltől visszakapott értéket, és ha az nem 0, vagyis a sor végrehajtása sikertelen, félbeszakítja az utasítások végrehajtását, és hibával visszatér a hívó szabályhoz, ami ugyancsak hibával visszatér az őt hívóhoz, stb., végül a make is hibával tér vissza a shellbe. VáltozókA make-ben háromféle típusú változó van:
A változó értékére a Saját változó a Az implicit és automatikus változó az utasításokban használható, a saját változó bárhol a szabályban. Példa: MIND = proba proba.gz
all : $(MIND)
proba : proba.c proba1.c
$(CC) -o $@ $^
proba.gz : proba.1
gzip -c <$^ >$@
A MIND saját változó, mely a célok nevét (a végrehajtható programét és a tömörített manuálét) tartalmazza helyközzel elválasztva. Az all a Makefile első szabálya, ez hajtódik végre, ha paraméter nélkül hívjuk a make parancsot.[4] Miután utasítása nincs, csak az előfeltételeket ellenőrzi, de ezzel le is fordítja a programot ill. újratömöríti a manuált, ha valamelyik megváltozott. Az automatikus változók lehetővé teszik, hogy minden fájlnevet csak egyszer kelljen leírni, a CC implicit változó pedig azt, hogy Makefile-lal ne csak linuxban lehessen a programot lefordítani. Implicit szabályokA fenti példában mindkét C-program lefordul, ha bármelyik forrásfájl megváltozik. Ez nem előnyös, különösen sok forrásprogramból álló programok esetén. Az alábbi Makefile-részlet megoldja a problémát: ...
proba : proba.o proba1.o
$(CC) -o $@ $^
proba.o : proba.c
$(CC) -c $^
proba1.o : proba1.c
$(CC) -c $^
...
Ebben az a kényelmetlen, hogy kétszer kell felsorolni a forrásfájlokat, és kétszer kell leírni a .c → .o fordítás utasítását is. Ezt lehet elkerülni implicit szabállyal: ...
.c.o:
$(CC) -Wall -c $^
...
A fenti implicit szabály azt adja meg, hogyan kell .c kiterjesztésű fájlból .o-t előállítani. Ez helyettesíti a két .o kiterjesztésű cél szabályát. Amikor a proba cél előfeltételeiben a make találkozik proba.o-val, és nem talál ezt előállító szabályt, megpróbál olyan implicit szabályt keresni, mely előállít ilyen kiterjesztésű fájlt. Háromféle implicit szabály létezik:
A mintaillesztéses implicit szabály a hagyományos kiterjesztése. A make-nek vannak beépített implicit szabályai, pl. a .c → .o átalakításra is. Ezek törölhetők, de a törlés hátránya, hogy a Makefile nem lesz hordozható különböző operációs rendszerek között. .SUFFIXES:
.SUFFIXES: .c .o .1 .gz
Az első sor törli az összes beépített szabályt, de a törléssel a beépített kiterjesztések táblázata is törlődik. A második sor pótolja azt a négy kiterjesztést, melyre a példában szükség van. Hamis célokA fenti példában az all célú szabállyal probléma lehet, ha az aktuális könyvtárban véletlenül létezik all nevű fájl. Miután nem ritka az ehhez hasonló cél,[6] a probléma elkerülésére külön utasítás szolgál: .PHONY: all
A .PHONY után írt szavakat céloknak tekinti a make, és előfeltétel ellenőrzésekor végrehajtja a szabályaikat, de nem ellenőrzi, léteznek-e ilyen nevű fájlok. Példa Makefile-ra.SUFFIXES:
.SUFFIXES: .c .o .1 .gz
.PHONY: all clean
.c.o:
$(CC) -c -Wall $^
.1.gz:
gzip -c <$^ >$@
MIND = proba proba.gz
all : $(MIND)
proba : proba.o proba1.o
$(CC) -o $@ $^
clean:
rm -f $(MIND) *.o
A -Wall a C-fordító kapcsolója: bekapcsolja az összes figyelmeztetést. Az rm parancsban fontos a -f: az rm – következésképp a make is – hibát jelez, ha nem létezik valamelyik törlendő fájl. A hibajelzést szünteti meg a kapcsoló. Jegyzetek
Források
Kapcsolódó szócikkek |
Portal di Ensiklopedia Dunia