Cross compiling for Win32 under Linux/it

From Free Pascal wiki

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

Suggerimenti per la Cross-Compilazione - creazione di binari per Win32 in ambiente Linux

Dalla versione 0.9.10 esiste un rpm 'fpc-crosswin32', che installa i binutils necessari (p.e. cross assembler, cross linker), i file .ppu di fpc cross-compilati per win32 e modifica il file /etc/fpc.cfg.

Tuttavia non include i file cross-compilati .ppu dell'LCL. É necessario che questi siano compilati dall'utente dopo l'installazione dell'fpc-crosswin32.

Lazarus ed il Compilatore Free Pascal

La Cross-compilazione - cosa bisogna sapere

Questo è una breve introduzione per i novizi.

La sezione seguente descrive come impostare il sistema per la cross-compilazione, in modo tale che lavori sotto linux e crei eseguibili per win32 (o freebsd o dawin, o ...). Perché usare la cross-compilazione: il FreePascal è un compilatore con l'obiettivo di convertire un programma sorgente in uno binario (in linguaggio macchina). Questi file binari contengono numerose informazioni, ad esempio la descrizione di come il sistema operativo deve avviare l'eseguibile. Nella maggior parte dei casi i file binari sono specifici per una determinata piattaforma e possono essere utilizzati solo sulla piattaforma per la quale sono stati scritti.

Di per sé il FreePascal non richiede un setup complesso. Esso è in grado di creare binari per molte piattaforme. Ed in pratica può già farlo. Tuttavia il compilatore è solo una parte. Bisogna anche tener conto dell'assembler ed del linker. E purtroppo questi strumenti non sono in grado di creare direttamente codice multipiattaforma. Ecco è necessario far riferimento a linker 'ld' e assembler 'as' specifici per ciascuna piattaforma di destinazione. Fortunatamente, per risolvere tali problemi, è possibile ricorrere alle binutils. Dopo aver creato gli strumenti "cross", tutte le unit pascal di fpc saranno cross-compilate. Ad esempio, ci sarà un file system.ppu per ciascuna piattaforma di destinazione. Quindi sarà necessario settare il file di config dell'fpc, così che la compilazione multipiattaforma avvenga tanto facilmente da dimenticarsi tutti i noiosi dettagli. La stessa cosà dovrà essere fatta per l'LCL - la lazarus component library. Infine sarà possibile compilare programmi per win32 su Linux. Successivamente i programmi realizzati si potranno testare con wine, con una macchina virtuale o copiandoli direttamente su una macchina reale windows.

Percé da *nix a windows e non viceversa.

La ragione principale di ciò è che generare binari unix su una piattaforma estranea (un'altra unix o anche un'altra distribuzione Linux) è più complicato. Il linking statico è complicato di suo, maggiormente quello shared.

You would need the used libraries from the target platform's (gtk, glib,libc etc), and a lot of additional configuring for ld. (library paths, dynlinker path etc)

This has been partially done (for the static case), but it is hard since it needs manual postediting of linker files and linker commandline, and a deep understanding about what makes Unix binaries tick.

Download del codice sorgente del FPC

Per realizzare programmi multipiattaforma purtroppo i binari non sono sufficienti, è dunque necessario scaricare i sorgenti completi del fpc. Si veda www.freepascal.org. Per ottenere i sorgenti è possibile usare SVN o una daily snapshot.

Per gli esempi che seguono si suppone che i sorgenti siano stati scaricati nella cartella ~/sources/fpc.

Scaricare le gnu binutils.

É possibile scaricare l'ultima versione delle binutils da http://ftp.gnu.org/gnu/binutils/
Supponiamo di scaricare le binutils-2.xx.tar.gz nella cartella ~/download/.

Cross build binutils

Nel repository di fpcbuild c'é uno script per creare le binutils per tutte le piattaforme: install/cross/buildcrossbinutils Prima di procedere visitate http://svn.freepascal.org/svn/fpcbuild/branches/ e individuate la versione di vostro interesse.

Per scaricare la cartella install da fpcbuild:

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

(nota: verrà creata una nuova cartella install nella vostra home - la cartella NON deve esistere!)

Creare una copia dello script:

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

Modificare le variabili all'inizio dello script.

La variabile BASE punta ad una directori di lavoro ed installazione. Essa dovrebbe essere vuota. Per esempio:

 BASE=~/cross_fpc

Ora il file binutils scaricato. se per esempio è stato scaricato in ~/download/binutils-2.18.tar.gz allora impostare le variabili come segue

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

Lo script aggancerà questo automaticamente a ~/download/binutils-2.18.tar.gz. Le variabili restanti da modificare definizcono la piattaforma di destinazione desiderata. Per default verranno considerate tutti i sistemi operativi supportati, ma cò richiede molto tempo (anche alcune ore su macchine lente). Per compilazioni per Windows, è necessario solo

 TARGETS_WIN="mingw32"
 

e possono essere commentate le altre righe:

 #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=


Quindi lanciare lo script:

 []$ sh buildcrossbinutils.sh
 

Lo script crea una sottocartella 'logs' contenente una serie di file di log. nel caso in cui ci dovessero essere errori partire osservando il contenuto di questi log.

Si noti che per molte piattaforme (Linux,FreeBSD, win32) queste sono disponibili già in forma compilata. Si veda: ftp://freepascal.stack.nl/pub/fpc/contrib/cross/

Cross build FPC

Nel repositorio scaricato è presente uno script per costruire l'fpc snapshot per tutte le piattaforme: install/cross/buildcrosssnapshot Creare una copia dello script:

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

Modificare le variabili all'inizio del nuovo script.

Normalmente è sufficiente modificare almeno le seguenti: CROSSTOOLSROOT, FPCCVS, DESTDIR, TARGETS_OS e TARGETS_CPU. Ad esempio:

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

Lanciare lo script:

 []$ sh buildcrosssnapshot.sh

Fatto ciò le unit compilate si troveranno in ~/cross_fpc/

Configure your fpc.cfg

Aprire come root il file /etc/fpc.cfg o creare una copia di /etc/fpc.cfg in ~/fpc.cfg ed editare questo file. Cercare nel config le stringhe seguenti:

Nota: Su versioni obsolete di $version e $target sono ustae al posto di $fpcversion e $fpctarget

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

Rimpiazzarle con il seguente codice (l'esempio è riferito ad una piattaforma linux per compilazioni win32):

#IFDEF win32
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/*
-Fu~/cross_fpc/lib/fpc/$fpcversion/cross/units/i386-win32/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

Infine: Testare e risolvere gli eventuali problemi

Compilazione multipiattaforma dell'LCL e dei componenti lazarus

Sulla linea di comando:

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

Questo compilerà tutti i file per win32 (incluso l'IDE, che non è necessario, ma questo semplifica il tutto)

O nell'IDE: impostare LCL, Synedit, Codetools, Package Registration e IDE Interface a Clean+Build, impostare LCL interface a win32/win64 ed impostare 'Target OS' a win32. Quindi 'build lazarus'.

These four parts have splitted output directories, so your linux .ppu/.o files are *not* overwritten and you don't need to recompile them.

Cross compiling a project

Set in Project->Compiler Options->Code the Target OS to 'win32' and in Paths the 'LCL Widget Type' to win32. That's all. The next time you build, you will create a win32 executable. The IDE will rescan for win32 units, so that 'Find declaration' and code completion features will now work with the win32 rtl instead of the linux rtl. When you open another project or reopen this project the IDE will automatically switch.

Hints for Cross compiling and Lazarus

If you create an application/package for multiple targets, you will often do the following: Fix a bug, compile and test it under linux, then compile and test it under win32, .. . Because normally you overwrite your .ppu files, you have to recompile everything, everytime you switch. This is not necessary. The Lazarus IDE supports macros.

Example 1: Cross compiling a project for linux and win32.

Set Project -> Compiler Options -> Paths -> Unit Output directory to $(TargetOS). This macro will be replaced by the value in Code -> TargetOS in lowercase (i.e. "linux" for Linux and "win32" for Win32). The output directory is relative to your project directory (the directory where your .lpi is). Create a linux and win32 directory in your project directory. When you click on the "Show Options" button at the bottom of the compiler options, you will see a -FElinux/ or -FEwin32/. This option tells the compiler where to write the output (e.g. .ppu/.o files).


Example 2: Cross compiling a project for various platforms and widget sets.

Set the Unit output directory to $(TargetCPU)/$(TargetOS)/$(LCLWidgetType) and create the sub directories for all targets. This path construction is also used by the LCL.


The same can be done for packages.

Cross compiling and Lazarus Packages

Lazarus packages are not limited to libraries. They can be used to compile nearly everything. And the IDE automatically recompiles them if needed. Packages can inherit compiler options. For example: A project that uses a package inherits the output directory of the package. In other words: the output directory of the package is added to unit search path of the project. See in the IDE: Project -> Compiler options -> Inherited. Inheritance normally works only one way. But there are exceptions: The target platform (OS and CPU) of the project overrides the target for all used packages. That means, if you set the Target OS of the project to "win32" and compile the project, the IDE will check if the used packages need to be recompiled for this Target OS.

For example:

Package A has as output directory: lib/$(TargetOS) Project uses A.

  1. The project is built for linux. The IDE compiles A for linux in <PackageDirOfA>/lib/linux/, then it compiles the project for linux.
  2. The project is built for win32. The IDE compiles A for win32 in <PackageDirOfA>/lib/win32/, then it compiles the project for win32.
  3. The project is built again for linux. The IDE checks A for linux and does not recompile it. Then it compiles the project for linux.

So, using the macros saves a lot of time.

For Unix (general)

Option -XLA is used to rename library dependencies specified in pascal units. Format is -XLAold=new, to modify ld link option -l<old> to -l<new>.

Option -XR<sysroot> (recent trunk) that can be used to specify the target system root. It's used for:

  • adding a prefix to the default added library paths; in the past you used to specify -Xd and these paths manually. E.g. for i386-linux instead of passing /lib, /usr/lib, and /usr/X11R6/lib to ld, it will pass <sysroot>/lib, <sysroot>/usr/lib, and <sysroot>/usr/X11R6/lib to ld.
  • detecting the C library (linux specific): glibc or uclibc. E.g. for uclibc detection '<sysroot>/lib/ld-uClibc.so.0' is tried.

Per Linux sotto Win32

É possibile reperire su tale argomento (meno importante del precedente) alcune informazioni nelle buildfaq

FreeBSD to sparc

I managed to crosscompile from x86 to Sparc Solaris 9. However the result doesn't work very well, but here is my cmdline:

in compiler/ execute:

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

~/src/sollib is a directory that contains:

  • a set of .o's from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
  • libgcc.a from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
  • a set of lib*.so from /usr/lib: libaio.so libmd5.so libc.so libelf.so librt.so libdl.so libm.so

Problem is illustrated by the following binary.

 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

I suspect wrong .o's are taken.

Per Mac OS X

Si veda forum post.

Contributi Originali

Questa pagina è una traduzione dall'inglese di Cross compiling for Win32 under Linux.