Ever been frustrated about spending a lot (certainly too much) time on compiling your apps for all the platforms you seek to support? Don’t want to repeatedly reboot your machine to start one for one the operating systems to compile your program there? Well, if you use to write your applications in (Free) Pascal, your happy ;-)

What is cross compiling? Cross compiling means, that you compile a program for a platform from another one. For example: If you work on Linux, you can compile your project also for Windows operating system. Sounds interesting? It is! However, it does not work “out of the box”. First we have to work a little bit and set up our cross compile environment.

Windows users: Watch out! If you think, that you can provide your apps now also for Linux and other systems I have to warn you. It is possible to compile Linux and other UNIX-oide apps using windows. But you will need a lot of stuff for this way round! As static linking is hard enough, dynamic linking will certainly drive you mad, if you don’t are ready to spend a lot of time - especially for learning the backgrounds. Same thing for Linux users who want to compile e.g. for OpenSolaris, FreeBSD, … Instead of providing binaries for each UNIXoid operating system, consider writing good Makefiles. That will probably make your users more happy.

Lets begin! So, what will this tutorial tell you? First of all: I will assume that we are on a 64bit Linux operating system. You probably can substitute “Linux” by any other UNIX-like operating system, as long as it is supported by Free Pascal. Second: I will also assume, that you want to compile your apps for Linux (64bit, 32bit) and Windows (64bit, 32bit). Again be warned: It is complicated to cross compile e.g. from Linux to FreeBSD. I will not cover this here - however you can try it yourself.

Step 1: “Building” cross linker and assembler As we are on a 64bit Linux, we need linker and assembler to be able to generate their stuff for 32bit. This is possible. And it is easy to realize for us. First, check whether you already have these binaries:

which i386-linux-ld
which i386-linux-as

If you do not have them (which will tell you, that there is no program XXX in PATH) we have to create them now. Simply create the following two files:

/usr/bin/i386-linux-ld

#!/bin/bash
ld -melf_i386 "$@"

/usr/bin/i386-linux-as

#!/bin/bash
as --32 "$@"

This should do fine. Don’t forget to make them executable!

chmod +x /usr/bin/i386-linux-ld
chmod +x /usr/bin/i386-linux-as

Step 2: Downloading Free Pascal Now you’ll need to download the Free Pascal source tarball of your choice. It doesn’t matter whether you use stable versions or checkout from SVN repos. You will also need a 64bit and a 32bit version of the Free Pascal compiler (if you don’t already have them). Let’s assume your machine is a Pascal-free zone and you also downloaded the pre-compiled Free Pascal binaries for Linux 32bit and 64bit additional to the latest stable source tarball.

Step 3: Installing Free Pascal in your home folder Now we’ll install the two binary packages at home. Why? Well: I don’t like to mess up my system more than needed. We will be able to compile our own compilers later, and let “make” do the job of installing. So, un-tar the two packages and run the contained install script:

tar -xf fpc-$FPVER.i386-linux.tar
sh install.sh
#install script guides you now through the installation
tar -xf fpc-$FPVER.x86_64-linux.tar
sh install.sh
#and again

When the install scripts ask you for a installation target, give a location in your home, e.g. “/home/tux/bin/fpc/i386” and… “/home/tux/bin/fpc/x86_64”. The two compilers will then reside in /home/tux/bin/fpc/i386/bin and /home/tux/bin/fpc/x86_64/bin. You also have to make sure that the compilers can be found by make later, so add these two locations to your PATH (e.g. by editing your local .bashrc file. Simply add:

export PATH=$PATH:/home/tux/bin/fpc/i386/bin:/home/tux/bin/fpc/x86_64/bin

This should do file. If you are in a terminal window, don’t forget to restart that window (or instead of editing the file modify PATH at “runtime”).

Step 4: Compiling Free Pascal for Linux 64bit and 32bit Now we can compile our own compilers for 32 and 64 bit. Simply unpack the source tarball and fire up make:

tar -xf fpcbuild-$FPVER.tar.gz
cd fpcbuild-$FPVER/fpcsrc
make build OS_TARGET=linux CPU_TARGET=x86_64 FPC=ppcx64
su -c "make install OS_TARGET=linux CPU_TARGET=x86_64 FPC=ppcx64"
make clean all OS_TARGET=linux CPU_TARGET=i386 FPC=ppc386
su -c "make install OS_TARGET=linux CPU_TARGET=i386 FPC=ppc386"

This will compile the Free Pascal compiler for each 64 and 32 bit Linux and install it in /usr/local/lib/fpc/$FPCVERSION. Also, the runtime library library and the default packages are installed as compiled units.

Step 5: Compiling the compiler, RTL and packages for Win32 Next step we will create a Win32 compiler and - what is much more important - the RTL and packages for Windows 32bit operating systems. This is as easy the the above step, as we just need to adjust the parameters for make:

make clean all OS_TARGET=win32 CPU_TARGET=i386 FPC=ppc386
su -c "make crossinstall OS_TARGET=win32 CPU_TARGET=i386 FPC=ppc386"

Ready! This compiles the compiler, rtl and packages and installs them into /usr/local/lib/fpc/$FPCVERSION

Step 6: Compiling Win64 RTL and packages OK, now we nearly have it done. The last step is to add support to compile to Windows 64bit systems. This is also easy to solve, despite it differs slightly from the steps we did for Win32:

cd ./rtl
make clean all OS_TARGET=win64 CPU_TARGET=x86_64 FPC=ppcx64
su -c "make install OS_TARGET=win64 CPU_TARGET=x86_64 FPC=ppcx64"
cd ../packages
make clean all OS_TARGET=win64 CPU_TARGET=x86_64 FPC=ppcx64
su -c "make install OS_TARGET=win64 CPU_TARGET=x86_64 FPC=ppcx64"

Step 7: Cleaning up Before starting to use your cross compilation environment, you should clean up. Remove the local installation of Free Pascal in your home folder and also don’t forget do edit your .bashrc file: Remove the path references to the removed installations in your home directory and add the path where FPC is installed (“/usr/local/lib/fpc/$FPCVERSION”).

Step 8: Creating a configuration file The last step is to create a configuration file for Free Pascal. To ease this, there is a script in the compiler’s directory:

cd /usr/local/lib/fpc/$FPCVERSION/
su -c "sh samplecfg /usr/local/lib/fpc/$FPCVERSION /etc"

This will create a default FPC configuration file in /etc that points to the location of the compiler. You can examine it and maybe change it to fit your needs.

Conclusion Well, done! You now have a fully working cross compile environment which allows you to compile for Linux and Windows (each 32 and 64bit). You don’t believe it? Then try it out! Create a pascal source file “hello.pas”:

program hello;

begin
  WriteLn('Hello World!');
end.

And now compile it:

mkdir linux32 linux64 win32 win64
ppcx64 -FUlinux64 -FElinux64 hello.pas
ppcx64 -FUwin64 -FEwin64 -Twin64 hello.pas
ppc386 -FUlinux32 -FElinux32 hello.pas
ppc386 -FUwin32 -FEwin32 -Twin32 hello.pas

You will end up with 4 folders containing four executeables for four different operating systems.

At last, a few notes: When upgrading to a newer version of Free Pascal, you don’t need to download the pre-compiled packages, again, as you then already have a compiler for each 32 and 64 bit. You should also note, that the compiled units and object files (.ppu, *.o) are not compatible among compilers and target platforms. That means: If you have a collection of Pascal source files and want to pre-compile them, you have to put them into different locations. If you have a closer look at the Free Pascal configuration file, you’ll notice, that there two place holders are used: *$fpcversion and $fpctarget. The second will be replaced by the target platform you compile to, and is of the form ARCHITECTURE-OPERATINGSYSTEM. So, if compiling e.g. to Win32 fpctarget will be replaced with “i386-win32”. The first - fpcversion - will be replaced by the version number of the Free Pascal compiler that is used.

That was it! Your system is now fully set up (at least for the basics). Working on only one platform and compiling to all the platforms you want to support has a lot of advantages: You only need to set up one system as a development system (in dual-boot environments), don’t need to use “tricks” (as installing Free Pascal inside a Wine environment) and you are able to write scripts to automate the compilation and packaging process.