Programkészítés a Build-del

Dr. Vermes Mátyás1

1999. július - 2003. szeptember

1.  Áttekintés
2.  Implicit fordítási szabályok
3.  Build programtípusok
4.  Alapvető üzemmódok
    4.1.  Egyetlen exe (-x) üzemmód
    4.2.  Könyvtár (-l) üzemmód
    4.3.  Osztott könyvtár (-s) üzemmód
    4.4.  Minden main-ből exe (alapértelmezett) üzemmód
5.  Paraméter referencia
    5.1.  Kapcsolók
    5.2.  Build környezeti változók
    5.3.  Könyvtár és include környezeti változók
6.  Példa

1.  Áttekintés

A CCC programok a Build projekt-generátorral készülnek. Build kielemzi a forráskönyvtárakban talált programokat, megállapítja, hogy azokból milyen lib-eket és exe-ket lehet csinálni. Összeveti a források, objectek, lib-ek, exe-k dátum/idejét, és elvégzi a szükséges fordítást, linkelést. Build ismeri és kezeli az összes olyan forrástípust, ami a CCC környezetben eddig előfordult: mnt, cls, msk, pge, asm, c, cpp, y, lex, prg, így nemcsak Clipper programok fordítására képes, hanem pl. yacc és lex programokhoz is megfelel. Valójában a Build olyankor is jó szolgálatot tesz, amikor egyáltalán nincs a projektben Clipper nyelvű program. Az egész CCC futtatórendszer, könyvtárak, utilityk (köztük maga a Build) fordítását is a Build vezérli.

Kiemelem, hogy a támogatott platformokon (DOS, Windows, Linux, Solaris) ugyanazt a makerendszert használjuk, ráadásul platformváltáskor nincs szükség a források konverziójára, hanem egyszerűen átmásoljuk a projektet tartalmazó directory struktúrát egyik gépről a másikra. A Build nem keveri össze különböző fordítókkal készített, különböző platformra szánt binárisokat.

A Build jelenleg az alábbi fordítókkal képes programot csinálni:

Microsoft C (Visual C) Windows NT/2000
Borland C (C Builder) Windows NT/2000
MinGW Windows NT/2000
GCC Linux, Solaris

Maga a Build a DOS korlátai miatt csak UNIX-on és NT-n futtatható. Lehetséges azonban DOS-os fejlesztés is, ha NT-s környezetből fordítjuk az elavult rendszerre szánt programunkat.2

2.  Implicit fordítási szabályok

Build a forrásprogramok elemzésével megállapítja, hogy azok milyen összefüggésben vannak egymással (melyikből lesz object, melyik inkludálja valamelyik másikat, stb.), és a filéidők alapján eldönti, hogy milyen fordítási műveleteket kell végrehajtani. Ha Build úgy látja, hogy egy msk filéből elő kell állítani a say-t, akkor végrehajtja az msk2say.bat scriptet. Általában is minden filétípust a filé kiterjesztése alapján azonosítunk, és minden fordítási művelethez tartozik egy batch filé, aminek a nevét az előbbi példa mintájára képezzük: prg2obj.bat, cpp2obj.bat, obj2lib.bat, stb.3 Ezáltal Build működése éppen olyan, mint ahogy a make utility alkalmazza az implicit fordítási szabályokat. A szabályokhoz tartozó tevékenységet azonban nem a makefilében adjuk meg, hanem az iménti batch scriptekben.

A Build programnak paraméterként kell megadni, hogy hol keresse az adott platform xxx2yyy.bat alakú scriptjeit. A különböző platformokhoz különböző script készleteket csinálunk, és ezzel elfedjük a platformok közti eltéréseket.

3.  Build programtípusok

A Build-et általában nem indítjuk közvetlenül, hanem olyan scripteken keresztül, amik megfelelő paraméterezéssel előkészítik Build-et egy-egy programtípus fordítására. Ezek a scriptek a $CCCDIR/usr/bin/$CCCUNAME könyvtárban találhatók. A Windowson használható scriptek:

bapp_w320.bat           Win32, CCC könyvtár nélkül
bapp_w32_.bat           Win32 konzol, képernyőkezelés nélkül
bapp_w32c.bat           Win32 konzol, fullscreen képernyő
bapp_w32c_btbtx.bat     Win32 konzol, BTBTX adatbázis
bapp_w32c_datidx.bat    Win32 konzol, DATIDX adatbázis
bapp_w32c_dbfctx.bat    Win32 konzol, DBFCTX adatbázis
bapp_w32g.bat           Win32 GUI
bapp_w32g_btbtx.bat     Win32 GUI, BTBTX adatbázis
bapp_w32g_datidx.bat    Win32 GUI, DATIDX adatbázis
bapp_w32g_dbfctx.bat    Win32 GUI, DBFCTX adatbázis

A Linux, Solaris platformon használható scriptek:

bapp_unix0.b           UNIX, CCC könyvtár nélkül
bapp_unix_.b           UNIX, képernyőkezelés nélkül
bapp_unixc.b           UNIX, karakteres (fullscreen) képernyő
bapp_unixc_btbtx.b     UNIX, karakteres képernyő, BTBTX adatbázis
bapp_unixc_datidx.b    UNIX, karakteres képernyő, DATIDX adatbázis
bapp_unixc_dbfctx.b    UNIX, karakteres képernyő, DBFCTX adatbázis
bapp_unixg.b           UNIX, Fltk (X) képernyőkezelés
bapp_unix.b            Dinamikus megjelenítő választás

A dinamikus megjelenítés választás azt jelenti, hogy a program elinduláskor felderíti (tipikusan környezeti változók alapján), hogy milyen megjelenítéssel (grafikus vagy karakteres) kell működnie.

A felsorolás közel sem teljes. A minták alapján könnyen lehet készíteni további variációkat, emellett a Build egy adott programtípuson belül, alkalmazás szinten is rugalmasan paraméterezhető, ahogy azt a következőkben látni fogjuk.

4.  Alapvető üzemmódok

Build legegyszerűbb használata esetén az aktuális directoryban található forrásprogramokból készít exe, lib és so filéket. A programnak négy üzemmódja van, amit az -x, -l és -s kapcsolókkal, illetve ezek elhagyásával lehet beállítani.

4.1.  Egyetlen exe (-x) üzemmód

Példa: bapp_unix.b -xpelda

Ez a parancs arra utasítja Build-et, hogy a pelda.prg forrásprogramból hozza létre pelda.exe-t úgy, hogy az aktuális directoryban lévő többi forrást szintén fordítsa le, és az objecteket linkelje az exe-hez. Részletesebben a következők történnek.

Mint látjuk Build az aktuális directory minden szóbajövő programját felhasználja pelda.exe elkészítéséhez.

4.2.  Könyvtár (-l) üzemmód

Példa: bapp_unix.b -lpelda

Ez a parancs arra utasítja Build-et, hogy készítse el pelda.lib-et, amibe be kell venni az aktuális directory minden olyan forrásprogramját, ami nem tartalmaz function main-t, ezenkívül az összes olyan prg-ből, ami main-t tartalmaz készítsen exe programot az előbbi lib hozzálinkelésével. A prg-k #include-jait most is vizsgálja Build, és lehetőség szerint beveszi őket a projekt függőségi listáiba. A -l üzemmód még az -x-nél is mohóbb, az összes forrást így vagy úgy felhasználja, hogy programot készítsen belőle.

4.3.  Osztott könyvtár (-s) üzemmód

Példa: bapp_unix.b -spelda

Ez az üzemmód UNIX-on alkalmazható, annyival több a -l módnál, hogy elkészül a könyvtár osztott változata (so) is.

4.4.  Minden main-ből exe (alapértelmezett) üzemmód

Példa: bapp_unix.b

Ha az előbbi -x, -l, -s kapcsolók egyikét sem alkalmazzuk, akkor Build az aktuális directory minden main-t tartalmazó programjából exe-t készít, amihez hozzálinkeli az összes többi programból készített objectet anélkül, hogy azokból könyvtárat készítene.

A projektek (könyvtárak, végrehajtható programok) tartalmát a források megfelelő csoportosításával kell szabályozni. Például, ha nem akarjuk letörölni egy forrás elavult változatát, de az sem jó, ha jelenlétével zavarja Build működését, akkor egyszerűen félre kell rakni egy alkönyvtárba. A fent ismertetett négy üzemmód az alkalmazási programok 90%-ában elegendő. A bonyolultabb esetekben segítenek az alább ismertetett kapcsolók.

5.  Paraméter referencia

5.1.  Kapcsolók

-xExeName
ExeName az elkészítendő program neve (lásd fenn).
-lLibName
LibName az elkészítendő könyvtár neve (lásd fenn).
-sLibName
LibName az elkészítendő osztott könyvtár neve (lásd fenn).
-dSrcDir
SrcDir azon directoryk listája, amikben Build a lefordítandó forrásmodulokat keresi. A lista a ,; karakterekkel lehet elválasztva. A parancssorban több -d paraméter is meg lehet adva, ekkor ezek tartalma összeadódik (additív). Ha -d meg van adva, az aktuális directoryban csak akkor keres a program, ha az explicite fel van sorolva, pl. -d.;srcprg;srccpp. Ha -d nincs megadva, akkor a program csak az aktuális directoryban keres, ami a -d. paraméterezéssel egyenértékű. A -d-ben felsorolt directorykban Build automatikusan keresi az inkludálandó filéket is, ezért ezeket nem kell a -i-ben is megadni.
-mMain
Az -m kapcsolóval lehet felsorolni a főprogramot tartalmazó forrásmodulokat. A main modulok listája a ,; karakterekkel lehet elválasztva. A kapcsoló additív. Az -m kapcsolót akkor használjuk, ha a main függvény nem prg típusú forrásban van. Ezzel Build nem Clipper nyelvű programok fordítására is használható. A ppo2cpp program pl. cpp, y és lex típusú forrásokból készül, azaz egyáltalán nincs is a projektben prg.
-iIncDir
Az include directoryk listája adható meg az -i kapcsolóval. A C fordító saját könyvtárait nem itt szoktuk megadni, hanem a fordító konfigurálásánal, ami rendszerfüggő, pl. DOS-on az include környezeti változót szokták erre használni. A lista ,; karakterekkel szeparálható, a kapcsoló additív. Nem kell olyan directoryt megadni, ami -d-ben már szerepelt.
-pLibPath
Azon directoryk listája adható meg a -p kapcsolóval, ahol a linker a CCC könyvtárakat keresi. A C fordító saját könyvtárainak helyét nem itt szoktuk megadni, hanem a lib környezeti változóban. A lista ,; karakterekkel szeparálható, a kapcsoló additív.
-bLibFile
A linkelendő könyvtárak nevét tartalmazó lista. A lista ,; karakterekkel szeparálható, a kapcsoló additív.
-hHelp
Listát ad az érvényes kapcsolókról.
name=value
A name=value paraméter hatására a Build futása alatt a name környezeti változó értéke be lesz állítva value-ra. Build-et egy sereg BUILD_XXX alakú környezeti változóval is paraméterezhetjük. A Build a fordítást végző xxx2yyy.bat scriptekkel szintén ilyen alakú környezeti változókon (és paramétereken) keresztül kommunikál. Ez a paraméter megadási forma lehetővé teszi, hogy Build környezeti változóit az operációs rendszertől független szintaktikával állítsuk be.
$(name)
Ha Build a parancssorában $(name) alakú kifejezést talál, azt helyettesíti a getenv(name) értékkel. Ez lehetővé teszi, hogy a környezeti változó értékét az operációs rendszertől független szintaktikával kapjuk meg.
@parfile
Parfile egy tetszőleges paraméterfilé, amiben a fent leírt paramétereket helyezhetjük el. A paramétereket a filében újsor karakterrel választjuk el. A parancssor és a paraméterfilé olvasása folytatólagos, pl. lehet több paraméterfilé is a parancssorban.

5.2.  Build környezeti változók

BUILD_BAT
Implicit szabályokhoz rendelt batch scriptek directoryja.
BUILD_BSN
A Bison-nak átadott kapcsolók.
BUILD_CLS
Az objccc paraméterei, pl. build_cls=-iclassdef.
BUILD_CPP
Egy directory, ahol a rendszer a C++ kódot gyűjti abból a célból, hogy letölthető installáló készletet lehessen előállítani belőle.
BUILD_DBG
Ha e változó értéke on, akkor Build kiírja a projekt függőségi listáit, és megmutatja a filék időbeli viszonyait.
BUILD_EXE
Az exe directory specifikációja, ide teszi Build az elkészült exe-ket, defaultja az aktuális directory.
BUILD_INC
A statndard include directoryk listája.
BUILD_LEX
A Flex-nek átadott kapcsolók.
BUILD_LIB
A standard libraryk listája.
BUILD_LPT
A standard library path.
BUILD_OBJ
Az aktuális object directory neve (a különböző platformú binárisokat ui. szét kell választani). Főleg könyvtár specifikációban használjuk "átnyúlkálós" linkeléskor. Például a KLTPINFO program így linkeli a KLTP projekt könyvtárát: -b../kltp/$(BUILD_OBJ)/kltp.
BUILD_OPT
A $CCCDIR/usr/options/$CCCBIN directoryban található, standard C++ fordítás opcióit tartalmazó filé neve.
BUILD_PRE
A prg2ppo preprocesszornak (vagy a Clippernek) átdott paraméterek.
BUILD_SRC
Ha ebben a változóban megadunk egy directoryt, akkor Build a forrásdirectory paramétereket (-d) erre a directoryra relatívan értelmezi.
BUILD_SYS
Subsystem azonostó. Tartalma platformfüggő, pl. MSC-vel windows/console, Watcom-mal nt_win/nt.

5.3.  Könyvtár és include környezeti változók

Külön kell szólni a BUILD_INC, BUILD_LIB, BUILD_LPT változókról.

Build összegyűjti az include és library paramétereket, és elhelyezi egy-egy környezeti változóban úgy (blank elválasztó), hogy később batch filéből shiftekkel könnyen fel lehessen dolgozni. A használt környezeti változók:

BUILD_INC
-d + -i kapcsolók tartalma + $(BUILD_INC) + $(INCLUDE)
BUILD_LPT
-p kapcsoló tartalma + $(BUILD_LPT) + $(LIB)
BUILD_LIB
-b kapcsoló tartalma + $(BUILD_LIB)
Ebből megállapítható a különböző szinten előírt paraméterek közötti összefüggés.

  1. A kapcsolók szintjén adjuk meg a projekt specifikus paramétereket. Ha pl. a KLTPINFO átnyúl a KLTP projekt OCH (include) filéiért, azt így írjuk elő: -i../kltp/classdef.

  2. A BUILD_XXX változók szintjén adjuk meg a standard paramétereket. Pl. a CCC könyvtárak, a Kontó könyvtárak is így vannak megadva. Ezeket a paramétereket projekt szinten nem tanácsos piszkálni. Ugyancsak ezen a szinten állítunk be olyan paramétereket, amiknek a használata nem gyakori, pl. BUILD_EXE, BUILD_DBG, BUILD_LEX, BUILD_BSN, BUILD_PRE.

  3. Végül az általános környezeti változók szintjén kell magadni az aktuális fordító (Clipper, Watcom C, stb.) normál működéséhez szükséges include és lib directorykat.

6.  Példa

A CCCDIR/tools/mask/m script tartalma a következő:

#!/bin/bash
bapp_unixc.b -lmask "BUILD_EXE=$CCCDIR/usr/bin/$CCCUNAME" 

  1. UNIX-os, karakteres képernyőkezelésű programok készülnek.

  2. Minden main-t nem tartalmazó program lefordul, és készül belőlük egy mask nevű könyvtár.

  3. Minden main-t tartalmazó programból lesz egy azonos nevű exe, amihez hozzálinkelődik az előbbi könyvtár. A konkrét példában öt darab exe fog készülni (ez a scriptből nem látszik, a Build fogja megkeresni őket).

  4. A BUILD_EXE változó beállításával megadjuk azt a directoryt, ahová a Build a friss exe-ket tenni fogja. Enélkül az aktuális directoryban jönnének létre az exe-k.

Ha az m script tartalma csak ennyi volna:

#!/bin/bash
bapp_unixc.b

akkor is lefordulna az összes program, létrejönne az öt exe (az aktuális directoryban), de nem készülne külön könyvtár.

Az előbbi script windowsos megfelelője m.bat:

@echo off
bapp_w32c -lmask  "BUILD_EXE=$(CCCDIR)/usr/bin/nt"

Nagyon hasonló a UNIX-os változathoz, azonban a UNIX és Windows shell eltérései miatt a paraméterekben előforduló speciális karaktereket másképp kell védeni. A $(CCCDIR) makrót a Build fogja értelmezni. A Build egyformán megérti a \ és / elválasztó karakterrel leírt útvonalakat.

Végeredményben két nagyon rövid, egymáshoz nagyon hasonló scriptet kell csak megírni, ezután bármely platformon az egybetűs m parancs hatására elkészül az adott direktoriban fellelhető összes program. Így működik a Build.

További példák sokasága található a CCC directory struktúrában, ahol minden projekt, beleértve a runtime libraryk fordítását, a prg forrást egyáltalán nem tartalmazó programok fordítását, a Build-del készül.


Jegyzetek:

1ComFirm BT.

2 A CCC 2.x-ben megszűnt a DOS-os Clipper és a Watcom fordítási környezet karbantartása, újdonság viszont a MinGW.

3 A DOS világban meghonosodott kiterjesztéseket használjuk Linuxon is (bat, obj, lib, exe), ez azonban, hála a Linux rugalmasságának, semmilyen problémát nem okoz.


Learn Hungarian in Budapest in Ulysses language school. Group and private courses on affordable prices.