Cross compiling for Win32 under Linux/hu

From Lazarus wiki

English (en) français (fr) magyar (hu) italiano (it) русский (ru)

Keresztfordítás Windows-ra Linux rendszeren


Tippek Win32 binárisok keresztfordításához Linux rendszeren

A 0.9.10 óta létezik egy rpm 'fpc-crosswin32' néven, ami telepíti szükséges binutils eszközöket (assembler, linker), az FPC .ppu fájljait win32-re keresztfordítva és a módosított /etc/fpc.cfg.

A csomag nem tartalmazza a keresztfordított LCL .ppu fájlokat. Neked kell lefordítanod őket az fpc-crosswin32 telepítése után.

A Lazarus és a Free Pascal Compiler

A keresztfordításról - Hogy tudd mit csinálsz

Ez egy rövid bevezetés kezdőknek. A következőkben leírjuk hogyan állítsd be a rendszert keresztfordításhoz, ami azt jelenti, hogy Linux rendszeren dolgozva készíthetsz Win32 alkalmazásokat (és ugyanígy FreeBSD, Darwin, stb.). Amiért jó a keresztfordítás: A FreePascal egy fordító és forráskódból gépi kódú bináris állományokat készít. Ez a bináris tartalmaz információkat arról is hogy az operációs rendszer milyen módon kezelje az állományt. Mindezek miatt a készített bináris állományok rendszerfüggők. Maga a FreePascal nem igényel sok beállítást. Képes binárisokat készíteni sok rendszerhez, csak kérd meg rá. A fordító azonban csak egy rész. Szükségünk van még assemblerre és a linkerre is. Az FPC rendelkezik beépített assemblerrel és/vagy linkerrel néhány rendszerhez, más rendszereken külső eszközökre van szüksége. Ezek az eszközök általában nem képesek binárisokat létrehozni eltérő rendszerek számára. Ezért van, hogy speciális linkert 'ld' és assemblert 'as' használunk minden célrendszeren. Ezeket nevezzük binutils-nak. Miután létrehoztuk (vagy megszereztük/telepítettük) a keresztfordító eszközöket, szükség lesz még az FPC RTL és további unitokra a választott célrendszerre lefordítva. Például minden célrendszerhez eltérő system.ppu (System unit) fájlra van szükség, stb. Miután az fpc config fájl beállítása megtörtént, a keresztfordítás könnyűvé válik, elfeledkezhetsz az unalmas részletekről. Ugyanezt kell tenni az LCL (lazarus component library) esetén is (ha Lazarus-t használsz). Ezután már fordíthatod is a pascal programokat a win32 rendszerre. Az elkészült binárisok futtathatók a Wine segítségével vagy átmásolhatók egy olyan gépre amin win32 fut és ott kipróbálhatók.

Miért *nix rendszerről windows rendszerre és nem a másik irányba?

A legfőbb ok az, hogy Unix binárisok létrehozása más rendszereken (másik Unix vagy akár Linux is) jóval bonyolultabb.

Szükséged lehet függvénytárakra (library) a célrendszerről (gtk, glib,libc etc), és rengetek finomhangolás elvégzésére van szükség az ld számára (függvénytárak helyei, dynlinker helye, stb.).

Ezek részlegesen megoldottak (a statikus linkelés esetén), de nehéz feladat mert utólagos kézi szerkesztést igényel a linker fájlokban és a parancssorban, és széles ismereteket arról ahogy a Unix binárisok működnek.

Töltsd le az FPC forráskódját

A binárisok letöltése nem elég, szükséged van a teljes FPC forráskódra. Megtalálod az www.freepascal.org címen. Használhatod a CVS-t vagy a napi kódot (snapshot). A következő példák esetében az FPC forráskódja a ~/sources/fpc könvtárba lettek letöltve.

Töltsd le a GNU binutils programokat.

Például a binutils-2.18.tar.gz fájlt töltsd le ide: ~/download/binutils-2.18.tar.gz.

A binutils programok keresztfordítása

Az fpcbuild tárhelyén megtalálható egy szkript amivel létre lehet hozni a binutils programokat minden rendszerre: install/cross/buildcrossbinutils

Töltsd le és telepítsd az fpcbuild csomagot:

 []$ cd ~
 []$ svn co http://svn.freepascal.org/svn/fpcbuild/branches/fixes_2_2/install install

Készíts másolatot a szkriptről:

 []$ cd ~/install/cross/
 []$ cp buildcrossbinutils buildcrossbinutils.sh

Szerkesztd a változókat az új szkript elején.

A BASE változó mutatja meg a fordítás és telepítés könyvtárát. Ezért ez lehetőleg egy üres könyvtár legyen. Például:

 BASE=~/cross_fpc

Most következnek a letöltött binutils programok. Ha a csomagot a ~/download/binutils-2.18.tar.gz néven mentetted akkor a beállítások a következőképpen nézzenek ki:

 BINUTILSPATH=~/download/
 BINUTILSBASE=binutils
 BINUTILSVERSION=2.18
 BINUTILS_GZIP=yes

A szkript automatikusan összeállítja belőlük az eredeti nevet: ~/download/binutils-2.18.tar.gz. A további változók a célrendszert határozzák meg. Alapértelmezés szerint szép csendben több rendszerre is lefordítja a kódot, ezért a fordítás sok időt (lassú gépeken órákat) vehet igénybe. Ha csak windows-ra akarsz keresztfordítani akkor csak ennyi kell:

 TARGETS_WIN="mingw32"
 

a többit pedig megjegyzésbe kell áttenni:

 #BSD="freebsd netbsd openbsd"
 #TARGETS_WIN="cygwin mingw32 msdosdjgpp"
 #TARGETS_I386="${BSD} linux solaris darwin"
 #TARGETS_POWERPC="${BSD} linux darwin"
 #TARGETS_SPARC="${BSD} linux solaris"
 #TARGETS_M68k=


Ezután futtasd a szkriptet:

 []$ sh buildcrossbinutils.sh
 

A szkript létrehozz a 'logs' nevű alkönyvtárat tele naplófájlokkal. Ha valami rosszul megy akkor itt kezdj nyomozni.

Ne felejtsd el, hogy több rendszerhez (Linux, FreeBSD, win32) ezek az eszközök már elérhetők lefordítva is. Lásd: ftp://freepascal.stack.nl/pub/fpc/contrib/cross/

Az FPC keresztfordítása

Az fpcbuld tárhelyén megtalálható egy szkript az FPC napi kód (snapshot) keresztfordításához több rendszerhez: install/cross/buildcrosssnapshot Készíts másolatot a szkriptről:

 []$ cd ~/install/cross/
 []$ cp buildcrosssnapshot buildcrosssnapshot.sh

Szerkesztd a változókat az új szkript elején.

Általában csak a CROSSTOOLSROOT, FPCCVS, DESTDIR, TARGETS_OS és TARGETS_CPU értékeit kell beállítanod. Például:

 CROSSTOOLSROOT=~/cross_fpc/cross
 FPCCVS=~/sources/fpc
 TARGETS_OS="win32"
 TARGETS_CPU="i386"
 DESTDIR=~/cross_fpc/
 

Ezután futtasd a szkriptet:

 []$ sh buildcrosssnapshot.sh

Ezután a megtalálod a keresztfordított unit fájlokat a ~/cross_fpc/ könyvtárban.

Az fpc.cfg beállításai

Rendszergazdaként nyisd meg az /etc/fpc.cfg fájlt vagy készíts másolatot az /etc/fpc.cfg fájlról ~/fpc.cfg néven, majd szerkesztd ezt a fájlt. Keresd meg benne a unit-ok útvonalait meghatározó részt.

Ne felejtsd el, hogy a régebbi FPC változatok a $version és $target változókat használják az $fpcversion és $fpctarget helyett.

-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl

Cseréld le őket az egyes rendszereknek megfelelő útvonalakra. Pélául normál Linux és keresztfordított win32 esetében így:

#IFDEF win32
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/i386-win32/units/
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/i386-win32/units/*
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/i386-win32/units/rtl
-XPi686-mingw32-
-FD~/cross_fpc/cross/bin
#ELSE linux
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/*
-Fu/usr/lib/fpc/$fpcversion/units/$fpctarget/rtl
#-Fu~/fpc/packages/*;~/fpc/rtl/linux
#ENDIF

Tennivaló: Tesztelés és hibaelhárítás

Az LCL és a Lazarus komponensek keresztfordítása

Parancssorban:

cd lazarus; make clean all OS_TARGET=win32
cd lazarus/lcl; make clean all 

Ez először lefordít mindent win32 rendszerre (beleértve az IDE-t is, ami nem szükséges).

Vagy az IDE-ben: Állítsd be az LCL, Synedit, Codetools, Package Registration és IDE Interface fordítását Clean+Build-re, az LCL interface-t win32/win64-re és a 'Target OS' (célrendszer) pedig win32 legyen. Ezután fordítsd újra a Lazarus-t ('build lazarus'). Ez a négy rész külön könyvtárba kerül, ezért a linux .ppu/.o fájlok *nem* lesznek felülírva és nem kell újrafordítanod őket.

Egy projekt keresztfordítása

Kattints a Project->Compiler Options menüpontra és a Code fülön állítsd be a célrendszert (Target OS) 'win32'-re, a Paths fülön pedig az 'LCL Widget Type'-t szintén 'win32'-re. Ennyi. A következő fordításnál win32 binárist fogsz létrehozni. Az IDE újraellenörzi a win32 unit-okat, így a 'Find declaration' és a 'code completion' lehetőségek a win32 és nem a linux rtl adataival működnek majd. Amikor új projectet nyitsz meg vagy újra megnyitod ezt, az IDE automatikusan váltani fog.

Tippek a Keresztfordításhoz Lazarus-ban

Ha több célrendszerre készítesz alkalmazást/csomagot, a következő műveleteket kell sokszor elvégezned: Hibajavítás, fordítás és tesztelés linux-on, aztán fordítás és tesztelés win32 rendszeren, ... Mivel normál esetben felülírod a .ppu fájlokat, újra kell fordítanod mindent, minden alkalommal amikor váltasz. De erre már nincs szükség. A Lazarus IDE támogatja a makrókat.

1. példa: Egy projekt keresztfordítása linux és win32 rendszerekre.

Állítsd be a Project->Compiler Options->Paths->Unit Output directory értékét $(TargetOS)-ra. Ez a makró le lesz cserélve a Code->TargetOS sorban található értékre csak kisbetűkkel (pl. "linux"-ra a Linux és "win32"-re a Win32 esetében). A kimeneti könyvtár egy relatív útvonal lesz a projekt könyvtárához iszonyítva (ahol az .lpi fájl található). Létre lesz hozva egy-egy könyvtár linux és win32 néven a projekt könyvtárában. Amikor a "Show Options" gombra kattintasz a 'Compiler options' alján, egyebek mellett látni fogod a -FElinux/ vagy -FEwin32/ paramétereket. Ezek határozzák meg, hogy hová kerüljön kimenet (a .ppu/.o fájlok).

2. Példa: Projekt keresztfordítása különböző rendszerekre és eszközkészletekre (widget set).

Állítsd be a 'Unit output directory' értékét így: $(TargetCPU)/$(TargetOS)/$(LCLWidgetType) és hozd létre a könyvtárakat minden célrendszerhez. Ezt a könyvtárszerkezetet használja az LCL is.

Ugyanezeket kell elvégezni a csomagok esetében is.

Lazarus csomagok keresztfordítása

A Lazarus csomagok nincsenek függvénytárakra korlátozva. Szinte mindenre lehet használni. Az IDE pedig szükség esetén újrafordítja őket. A csomagok örökölhetik a fordítási paramétereket. Például: A projekt amelyik a csomagot használja örökli a csomag kimeneti könyvtárát. Más szavakkal: a csomag kimeneti könyvtára hozzá lesz adva a projekt unit-ok könyvtárainak listájához (unit search path). Az IDE-ben itt találod: Project -> Compiler options -> Inherited. Az öröklés általában csak egy irányba működik. De vannak kivételek: A projekt célrendszerének beállítása (OS és CPU) felülbírálja az összes csomag célrendszerbeállítását. Ez azt jelenti, hogy ha a projekt célrendszerét win32-re állítod és fordítod a projektet, az IDE elenörzi, hogy a használt csomagokat újra kell-e fordítani erre a célrendszerre.

Például:

Az A csomag kimeneti könyvtára: lib/$(TargetOS) A projekt használja az A csomagot.

  1. A projekt linux rendszerre készül. Az IDE lefordítja az A csomagot linux rendszerre a <PackageDirOfA>/lib/linux/ könyvtárba, ezután lefordítja a csomagot linux rendszerre.
  2. A csomag win32 rendszerre készül. Az IDE lefordítja az A csomagot win32 rendszerre a <PackageDirOfA>/lib/win32/ könyvtárba, ezután lefordítja a csomagot win32 rendszerre.
  3. A projekt ismét linux rendszerre lesz fordítva. Az IDE ellenörzi, hogy az A csomag le lett-e már fordítva linux rendszerre és nem fordítja újra. Ezután lefordítja a projektet linux rendszerre.

A makrók hazsnálatával sok időt lehet megtakarítani.

Unix rendszerre (általános)

Az -XLA paraméterrel tudod a pascal unit-ban megadott függőségeket átnevezni. Formátuma -XLAold=new, az ld paramétere pedig -l<régi> helyett -l<új> legyen.

Az -XR<sysroot> paraméterrel megadhatod a célrendszerhez használt gyökérkönyvtárat. Amire a következők miatt lehet szükség:

  • előtag illesztése a függvénytárak útvonala elé; a múltban a -Xd használatával és az útvonalak kézi megadásával lehetett elérni ugyanezt. Például i386-linux esetén az ld számára a /lib, /usr/lib, és /usr/X11R6/lib átadása helyett a <sysroot>/lib, <sysroot>/usr/lib, és <sysroot>/usr/X11R6/lib kerül átadásra.
  • felismerni a C függvénytárat (linux függő): glibc vagy uclibc. Például uclibc keresése esetén a '<sysroot>/lib/ld-uClibc.so.0' lesz használva.

Linux rendszerre Win32 alatt

Információkat a buildfaq részben találsz erről.

FreeBSD-ről sparc-ra

Végigcsináltam egy keresztfordítást x86-ról Sparc Solaris 9 rendszerre. Azonban az eredmény nem volt megfelelő. Itt a parancsror amit futtattam:

 gmake cycle CPU_TARGET=sparc OS_TARGET=solaris CROSSBINUTILPREFIX=solaris-sparc- CROSSOPT='-Xd -Fl~/src/sollib'

Az ~/src/sollib egy könyvtár ami a következőket tartalmazta:

  • több .o fájlt a /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3 könytvtárból
  • a libgcc.a fájlt a /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3 könytvtárból
  • több lib*.so fájlt a /usr/lib könyvtárból: libaio.so libmd5.so libc.so libelf.so librt.so libdl.so libm.so

A problémát a következő példa mutatja meg.

 Free Pascal Compiler version 2.1.1 [2006/03/17] for sparc
 Copyright (c) 1993-2005 by Florian Klaempfl
 Target OS: Solaris for SPARC
 Compiling system.pp
 system.pp(15,1) Fatal: Syntax error, "BEGIN" expected but "identifier UNIT" found

Azt gyanítom, hogy rossz .o fájlokat kapott.

Mac OS X

Nézd meg ezt a fórum bejegyzést (angol).

Eredeti közreműködők

Ez az oldal az epikwiki változat átalakításával készült.