Sign in Join
Wiki copytemporary

Cross compiling: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Cross compiling

OldNewLine
1+## Introduction
2+
3+> **Note:** Before going any further, consider [[Cross compiling|Why not to cross compile?]] below
4+
5+This is a short introduction for users new to cross compiling. The following sections describe how to setup a system to cross compile, that means creating binaries (executables) for a platform different from the one used for compilation - e.g. working under Linux and creating Win32 executables (or those for FreeBSD or Darwin, etc.). In this case, the platform used for compilation is usually referred to as "host" (Linux in the example above) and the platform where you want to run your created binaries is your "target".
6+
7+Free Pascal is a compiler and basically converts source into binaries (machine language). These binaries also contain information on how the operating system starts the executables. Moreover, the binaries refer to the APIs provided by the particular operating system, that's why a different implementation of our Run-Time Library is necessary for different operating systems. Therefore these binaries are platform specific. Free Pascal itself does not need much setup. It can create binaries for many platforms. Just tell it to do so.
8+
9+### Host and target on the same CPU
10+
11+FPC is designed so that the distributed compiler can create machine code for a certain CPU (because different CPUs need different machine code) and it knows specific requirements for all supported platforms (operating systems) available on that particular CPU. This means that you can perform cross-compilation with the same compiler used for native compilation as long as you stick to the same CPU.
12+
13+### Host and target on different CPUs
14+
15+If you need to create binaries for a different CPU, you need a special cross-compiler, i.e. compiler running on the host platform, but able to create machine code for a different CPU (in the case of FPC, such a cross-compiler would be again able to target all supported platforms available on the _target_ CPU). This cross-compiler is then usually stored in the same directory as the native compiler. Such a cross-compiler may be either compiled by yourself, or you can use a ready made distributed cross-compiler provided for some platforms directly by the FPC team (usually platforms mostly used in portable devices like arm-linux or arm-wince, because these are usually not used as host platforms). FPC binary can then select the right compiler (either the native compiler or the cross-compiler) for the target CPU selected using the -P parameter.
16+
17+### Supported targets
18+
19+See the [[Free Pascal supported targets|Supported target operating systems]] article for the full list.
20+
21+### Assembler and linker
22+
23+The compiler is only one part. We also need the assembler and the linker. FPC provides an internal assembler and/or linker for some platforms, but other platforms need external tools. Usually these tools are not able to create binaries for different platforms. That's why we have to use different special linker 'ld' and assembler 'as' for every target platform. These are the binutils.
24+
25+See [[Binutils]].
26+
27+### Units for target
28+
29+After creating (or having/installing) the cross tools, one needs FPC RTL and other units compiled for the chosen target platform. For example, every target platform needs a different file system.ppu (System unit), etc. These units may be either compiled using your compiler set up for compilation to the target platform, or you may potentially use officially distributed units compiled (and distributed) with exactly the same FPC version (if available in format usable under the particular host platform).
30+
31+Its worth noting that you don't necessarily need a new cross compiler for every CPU-OS combination, but you do need the FPC Units. For example, on a Linux host setup to cross compile to Windows and Raspberry Pi, the /usr/lib/fpc/3.2.2/units directory may contain the following directories-
32+
33+`arm-linux`\
34+`i386-linux`\
35+`i386-win32`\
36+`x86_64-linux`\
37+`x86_64-win64`
38+
39+Each of those directories will contain a directory for each of the FPC units, each one with .o and .ppu files.
40+
41+### Configuration
42+
43+Then your FPC config file will be setup, so that cross compilation becomes so easy, that you can forget all the boring details. The same will be done for the LCL - the Lazarus Component Library (if using Lazarus). And after this you can cross compile Pascal programs for the (different) target platform. The resulting binaries may then be copied to a machine running the target platform, or run under an emulator (e.g. Wine for Win32 binaries under Linux, etc.).
44+
45+### Basic Steps
46+
47+There are a few common steps involved in cross compiling that you must do in every case:
48+
49+- Have already a Free Pascal compiler for the platform you wish to compile from.
50+- You need to have the Free Pascal source code (except for the special case of having everything prepared by someone else).
51+- You need to either build from source or obtain binaries of the cross-binutils (See [[Binutils]]) that run on the platform you are on and are designed to build programs for your desired target platform.
52+- Sometimes you will need some files from the target you are compiling to.
53+
54+## From Linux
55+
56+### From Linux x64 to Linux i386
57+
58+Chances are that your 64 bit Linux distribution is already capable of compiling 32 bit programs but due to the way the FPC build process is designed there are a couple of things you might have to do.
59+
60+#### Install the 32bit libraries
61+
62+On a 64bit Debian/Ubuntu you need to install a number of 32bit libraries, first enable the architecture as shown below. Note that just installing the particular :i386 packages (without enabling the architecture) is no longer reliable, see <https://wiki.debian.org/Multiarch/HOWTO> . Other distributions will require a similar install.
63+
64+``` bash
65+sudo dpkg --add-architecture i386
66+sudo apt update
67+sudo apt install libc6-dev-i386 libx11-6:i386 libx11-dev:i386 libgdk-pixbuf2.0-0:i386 libatk1.0-dev:i386 libgdk-pixbuf2.0-dev:i386 libpango1.0-dev:i386 libgtk2.0-dev:i386 libnotify-dev:i386
68+```
69+
70+Note how they have :i386 appened to the names, thats to tell apt to get the 32bit ones on a 64bit system. If you later get missing library error messages when cross compiling 32bit to 64bit, don't forget to add the :i386 to the names when installing what is needed.
71+
72+This will typically put those 32bit libraries in /usr/lib/i386-linux-gnu/. You might need to check they are there and ensure your fpc.cfg knows where they are. Further, to ensure you find the crt* libraries, you may need to add (or, more likely, edit) something like -
73+
74+``` bash
75+# path to the gcclib,
76+#ifdef cpui386
77+-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
78+#endif
79+```
80+
81+Check that location first, the '9' varies with your distribution's age. In Bullseye for example, its /usr/lib/gcc/x86_64-linux-gnu/10/32
82+
83+#### Create ld and as files
84+
85+Check if you already have the files i386-linux-ld and i386-linux-as by doing the following commands:
86+
87+``` bash
88+$ which i386-linux-ld
89+$ which i386-linux-as
90+```
91+
92+If you get nothing, it means you need to create them. If you have these files skip to the **Compile FPC** (see below).
93+
94+Those are executable files. They must be in you PATH, if you are installing the compiler in root space, then probably /usr/bin but if you are using a compiler in user space (ie you used a FPC Tarball) then put them in the same user directory your other FPC compiler tools live in. We will assume /usr/bin here. **/usr/bin/i386-linux-ld** must contain:
95+
96+``` bash
97+#!/bin/bash
98+ld -A elf32-i386 $@
99+```
100+
101+**/usr/bin/i386-linux-as** must contain:
102+
103+``` bash
104+#!/bin/bash
105+as --32 $@
106+```
107+
108+Both can be created using following commands:
109+
110+``` bash
111+# Create /usr/bin/i386-linux-ld
112+$ cat >/usr/bin/i386-linux-ld << EOF
113+#!/bin/bash
114+ld -A elf32-i386 \$@
115+EOF
116+$ chmod +x /usr/bin/i386-linux-ld
117+
118+# Create /usr/bin/i386-linux-as
119+$ cat >/usr/bin/i386-linux-as << EOF
120+#!/bin/bash
121+as --32 \$@
122+EOF
123+$ chmod +x /usr/bin/i386-linux-as
124+```
125+
126+#### Compile The Cross Compiler
127+
128+You may be installing a cross compiler to suit either a root installed existing compiler (perhaps installed with a .deb) or your existing compiler was installed using a Tarball (an excellent idea incidentally). Further, your system may like to keep such things in /usr or, perhaps /usr/local, so adjust accordingly. Firstly, if installing in root space -
129+
130+``` bash
131+
132+$ cd /usr/share/fpcsrc/<version>
133+$ sudo make all OS_TARGET=linux CPU_TARGET=i386
134+$ sudo make crossinstall OS_TARGET=linux CPU_TARGET=i386 INSTALL_PREFIX=/usr
135+$ ls -la /usr/lib/fpc/<version>/ppcross386
136+```
137+
138+If the last command there shows you a nice file called ppcross386, great, proceed to the next command
139+
140+`$ sudo ln -s /usr/lib/fpc/<version>/ppcross386  /usr/bin/ppcross386`
141+
142+If, however, **that file is not there**, its probably in /usr/share/fpcsrc/\<version\>/compiler/ppcross386, check there and if it is, use the next command -
143+
144+`$ sudo ln -s  /usr/share/fpcsrc/<version>/compiler/ppcross386  /usr/bin/ppcross386`\
145+
146+On the other hand perhaps you are installing in user space and assuming your existing compiler is in in \$HOME/bin/FPC you might do -
147+
148+``` bash
149+
150+$ cd $HOME/bin/FPC/SRC/fpc-3.2.0
151+$ make all CPU_TARGET=i386
152+$ make crossinstall CPU_TARGET=i386 INSTALL_PREFIX=$HOME/bin/FPC
153+$ ln -s $HOME/bin/FPC/lib/fpc/3.2.0/ppcross386 $HOME/bin/FPC/bin/ppcross386
154+```
155+
156+Thats it ! You may need to edit your fpc.cfg (it lives in either /etc/fpc.cfg or \$HOME/.fpc.cfg).
157+
158+Note that if you see messages about failing to find files such as crtn.o and predicted failures to link, its probably because your Linux distro likes to keep its 32bit gcc libraries in /usr/lib32. Check if the missing files are in fact, in /usr/lib32 and, if so, make a small change to your (eg) /etc/fpc.cfg file, around line \#177 there is a section that looks like this -
159+
160+``` bash
161+#ifdef cpui386
162+-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
163+#endif
164+```
165+
166+Make it look like this, one additional line -
167+
168+``` bash
169+#ifdef cpui386
170+-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
171+-Fl/usr/lib32
172+#endif
173+```
174+
175+Again, the above says /usr/lib/gcc/x86_64-linux-gnu/**9**/32, the '9' will change over time, on Bullseye its '10'.
176+
177+#### Testing
178+
179+Before you proceed any further, its a good idea to test what you have done so far.
180+
181+With a simple hello.pas file
182+
183+``` bash
184+$> fpc -Pi386 hello.pas <enter>
185+$> file hello <enter>
186+```
187+
188+### From Linux to ARM Linux
189+
190+#### Maemo 5 OS
191+
192+Information about targeting Linux running on ARM (e.g. Zaurus) may be found in [[Setup Cross Compile For ARM]].
193+
194+#### Raspberry Pi
195+
196+Information about targeting Linux running on a Raspberry Pi may be found in [[Cross Compile to RasPi from Linux]].
197+
198+### From Linux to Windows
199+
200+Information on cross-compilation with Lazarus can be found in [[Cross compiling for Windows under Linux]]
201+
202+### From Linux to macOS
203+
204+Please see [[Cross compiling OSX on Linux|Cross compiling macOS on Linux]].
205+
206+## From Windows
207+
208+### From Windows to Android
209+
210+For a tutorial on how to create Android apps with Lazarus on Windows, see [[Android tutorial]].
211+
212+### From Windows to Linux
213+
214+This is less trivial, there is some info in the [[buildfaq]]
215+
216+See also [[fpcup]] for descriptions on which binutils work and what libraries/files to copy.
217+
218+As the Build FAQ explains, you will need libs (.so files) from the target system, e.g. from /lib and /user/lib (but could be more locations). On some systems, some .so files are actually scripts; check with:
219+
220+``` bash
221+$ grep -i "ld script" *
222+```
223+
224+Remove those .so and copy over (or symlink) the .so.x files that you should have to .so in order for the linker to find them.
225+
226+### From Windows to GO32v2
227+
228+Detailed information may be found in [[Cross-compilation from Win32 to GO32v2]].
229+
230+### From Windows to winCE
231+
232+- [[arm-wince]] describes how to setup a crosscompiler for arm CPU
233+- [[i386-wince]] describes how to setup compiling for i386 CPU (no crosscompiling)
234+
235+> **Note:** Lazarus installers have an installer that adds Windows to WinCE cross compilation options automatically
236+
237+### From win32 to win64
238+
239+If you are compiling the 2.1.1 or greater branch of fpc you can just do:
240+
241+``` bash
242+$ make all OS_TARGET=win64 CPU_TARGET=x86_64
243+```
244+
245+and then
246+
247+``` bash
248+$ make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64
249+```
250+
251+### From win64 to win32
252+
253+Assuming that Lazarus 2.0.10 was previously installed, now install
254+
255+**`lazarus-2.0.10-fpc-3.2.0-cross-i386-win32-win64.exe`**` `
256+
257+in the same base directory and then setup your project options to:
258+
259+- Target OS : Win32
260+- Target CPU : i386
261+
262+Failing to set the CPU (Default) lead to incorrect win32-x86_64 platform!
263+
264+### Lazarus guide to cross-compile Win 32/64-bit
265+
266+Download the installers from sourceforge.net (click on the Files tab):
267+
268+**[<https://sourceforge.net/projects/lazarus/>](https://sourceforge.net/projects/lazarus/)**
269+
270+The installers include FPC and the Lazarus help files *(as of Oct. 20, 2019)*:
271+
272+- Lazarus 32-bit
273+ - lazarus-2.0.4-fpc-3.0.4-win32.exe
274+ - lazarus-2.0.4-fpc-3.0.4-cross-x86_64-win64-win32.exe
275+
276+- Lazarus 64-bit
277+ - lazarus-2.0.4-fpc-3.0.4-win64.exe
278+ - lazarus-2.0.4-fpc-3.0.4-cross-i386-win32-win64.exe
279+
280+To install Lazarus 32-bit, and cross-compile a Windows 64-bit exe:
281+
282+1. Install the win32.exe
283+2. Install the cross-x86_64-win64-win32.exe in the same folder
284+
285+To install Lazarus 64-bit, and cross-compile a Windows 32-bit exe:
286+
287+1. Install the win64.exe
288+2. Install the cross-i386-win32-win64.exe in the same folder
289+
290+(The following assumes Lazarus 64-bit with cross-i386-win32-win64)
291+
292+To cross-compile 32-bit or 64-bit without creating Build Modes:
293+
294+`  Project, Options, Compiler Options, Config and Target:`\
295+`     Target OS         =Default=Win64  or Win32 for 32-bit`\
296+`     Target CPU family =Default=x86_64 or i386  for 32-bit`\
297+`     Target processor  =Default`\
298+`  Press OK to exit Project Options`\
299+`  Build and run the project`\
300+`  Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit`\
301+`  `
302+
303+To Configure Build Modes:
304+
305+`  Project, Options, Compiler Options, Config and Target:`\
306+`     Check 'Build Modes', then press the [...] button`\
307+`        Press [Create Debug and Release Modes] button`\
308+`        Press OK`\
309+`        `\
310+`  Create a Debug 32-bit Build Mode:`\
311+`     Lazarus menu: Project, Options, Compiler Options, Config and Target`\
312+`     Select Build Mode = Debug`\
313+`     Press the Build Modes [...] button`\
314+`        Click to select Debug on the list`\
315+`        Press the [ + ] button to add a new build mode`\
316+`        Rename to 'Debug 32-bit', press OK`\
317+`     Set Target Platform to 32-bit:`\
318+`        Target OS         =Win32`\
319+`        Target CPU family =i386`\
320+`        Target processor  =Default`\
321+`     Press OK to exit Project Options and save Build Mode 'Debug 32-bit'`\
322+`     `\
323+`  Create a Debug 64-bit Release Mode:`\
324+`     Lazarus menu: Project, Options, Compiler Options, Config and Target`\
325+`     Select Build Mode = Release`\
326+`     Press the Build Modes [...] button`\
327+`        Click to select Release on the list`\
328+`        Press the [ + ] button to add a new build mode`\
329+`        Rename to 'Release 32-bit', press OK`\
330+`     Set Target Platform to 32-bit:`\
331+`        Target OS         =Win32`\
332+`        Target CPU family =i386`\
333+`        Target processor  =Default`\
334+`     Press OK to exit Project Options and save Build Mode 'Release 32-bit'      `\
335+`  Build and run the project`\
336+`  Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit`
337+
338+To use Build Modes:
339+
340+`  Lazarus IDE Menu: Change Build Mode dropdown (left of Run button)`\
341+`  Build and run the project`\
342+`  Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit`
343+
344+## From macOS (Darwin)
345+
346+You must have the Free Pascal Compiler (FPC) source code already installed. Recent FPC dmg downloads store the source code on macOS in the `/usr/local/share/fpcsrc` directory.
347+
348+### From macOS to Win32
349+
350+To be able to compile your Lazarus/Pascal source code on macOS for Windows 32 bit, compile and install the Windows 32 bit cross compiler. To do this you need a bootstrap i386 compiler (ppc386). A Free Pascal Compiler release can always be built by the previously released FPC version, and FPC trunk can always be built by the currently released FPC version. So, as of July 2020:
351+
352+- to build FPC v3.2.0, you need an FPC v3.0.4 ppc386 i386 bootstrap compiler;
353+- to build trunk (v3.3.1) you need an FPC v3.2.0 ppc386 i386 bootstrap compiler.
354+
355+Once you have a bootstrap i386 compiler, then to use that compiler you pass it on the command line with *FPC=*. For example, to build the trunk (v3.3.1) FPC version cross compiler for Win32:
356+
357+`# Open a Terminal and navigate to the FPC source code directory.`\
358+`$ cd /usr/local/share/fpcsrc/`
359+
360+`# Compile the FPC trunk cross compiler using the released FPC 3.2.0 compiler.`\
361+`$ sudo make clean all FPC=/usr/local/lib/fpc/3.2.0/ppc386 OS_TARGET=win32 CPU_SOURCE=i386`
362+
363+`# Install the cross compiler.`\
364+`$ sudo make crossinstall OS_TARGET=win32 CPU_TARGET=i386`
365+
366+`# Soft link the cross compiler to the bin directory with the other compiler binaries.`\
367+`$ sudo ln -s /usr/local/lib/fpc/3.3.1/ppcross386 /usr/local/bin/ppcross386`
368+
369+Now go to the Lazarus IDE and setup the Project Options and Tools Options as follows:
370+
371+- Project Options
372+ - Config and Target
373+ - Target OS Win32
374+ - Target CPU i386
375+ - Target Processor (Default)
376+ - Target specific options \[X\] Win32 gui application
377+ - Current LCL widgetset: "win32"
378+
379+- Tools
380+ - Options
381+ - Environment
382+ - Files
383+ - Compiler executable: /usr/local/bin/ppcross386
384+
385+Once you have setup the Project Options and Tools Options, Lazarus will now be able to cross compile Windows 32 bit applications on your macOS computer. The first time you compile a Windows 32 bit application, Lazarus will also recompile its component source code; so don't be alarmed, it will just take a little longer.
386+
387+To use the FPC compiler without Lazarus, I use the following shell script:
388+
389+``` bash
390+#!/bin/sh
391+/usr/local/bin/ppcross386 -FUwin32 -FEwin32 -Twin32 ${1}
392+```
393+
394+as follows:
395+
396+``` bash
397+win32 program.pas
398+```
399+
400+This will create the 32 bit Windows executable in the win32 subdirectory to keep it separate from macOS and Win64 executables. If you do not want to use subdirectories, you can omit the *-FEwin32* parameter from the script.
401+
402+### From macOS to Win64
403+
404+To be able to compile your Lazarus/Pascal source code on macOS for Windows 64 bit on either an Intel or Apple Silicon Mac, compile and install the Windows 64 bit cross compiler. To do this you need a bootstrap x86_64 compiler (ppcx64). A Free Pascal Compiler release can always be built by the previously released FPC version, and FPC trunk can always be built by the currently released FPC version. So, as at May 2022:
405+
406+- to build FPC v3.2.2, you need an FPC v3.2.0 ppcx64 x86_64 bootstrap compiler;
407+- to build trunk (v3.3.1) you need an FPC v3.2.2 ppcx64 x86_64 bootstrap compiler.
408+
409+Once you have a bootstrap x86_64 compiler, then to use that compiler you pass it on the command line with *FPC=*. For example, to build the trunk (v3.3.1) FPC version cross compiler for Win64:
410+
411+`# Open a Terminal and navigate to the FPC source code directory`\
412+`$ cd /usr/local/share/fpcsrc/`
413+
414+`# Compile the FPC trunk cross compiler using the released FPC 3.2.2 compiler.`\
415+`$ sudo make clean all OS_TARGET=win64 CPU_SOURCE=x86_64 FPC=/usr/local/lib/fpc/3.2.2/ppcx64 OPT="-XR/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"`
416+
417+`# Install the cross compiler.`\
418+`$ sudo make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64`
419+
420+`# Soft link the cross compiler to the bin directory with the other compiler binaries.`\
421+`$ sudo ln -s /usr/local/lib/fpc/3.3.1/ppcrossx64 /usr/local/bin/ppcrossx64`
422+
423+Now go to the Lazarus IDE and setup the Project Options and Tools Options as follows:
424+
425+- Project Options
426+ - Config and Target
427+ - Target OS Win64
428+ - Target CPU x86_64
429+ - Target Processor (Default)
430+ - Target specific options \[X\] Win32 gui application \[win32 is not a mistake\]
431+ - Current LCL widgetset: "win32" \[win32 is not a mistake\]
432+
433+- Tools
434+ - Options
435+ - Environment
436+ - Files
437+ - Compiler executable: /usr/local/bin/ppcrossx64
438+
439+Once you have setup the Project Options and Tools Options, Lazarus will now be able to cross compile Windows 64 bit applications on your macOS computer. The first time you compile a Windows 64 bit application, Lazarus will also recompile its component source code; so don't be alarmed, it will just take a little longer.
440+
441+To use the FPC compiler without Lazarus, I use the following shell script located in `/usr/local/bin`:
442+
443+``` bash
444+#!/bin/sh
445+/usr/local/bin/ppcrossx64 -FUwin64 -FEwin64 -Twin64 ${1}
446+```
447+
448+as follows:
449+
450+``` bash
451+win64 program.pas
452+```
453+
454+This will create the 64 bit Windows executable in the win64 subdirectory to keep it separate from macOS and Win32 executables. If you do not want to use subdirectories, you can omit the *-FEwin64* parameter from the script.
455+
456+### From macOS i386 to PowerPC
457+
458+The official FPC installer for macOS/i386 includes a PowerPC cross-compiler and all units necessary to compile PowerPC programs (use *ppcppc* instead of *ppc386* to compile your programs). The instructions below are only necessary if you want to compile and install a new version from svn.
459+
460+- Compile FPC:
461+
462+``` bash
463+$ cd fpc
464+$ make all CPU_TARGET=powerpc -j 2
465+```
466+
467+This creates the powerpc cross-compiler compiler (fpc/compiler/ppcrosspcc) and all units. You can install them using the following commands:
468+
469+``` bash
470+$ sudo make FPC=`pwd`/compiler/ppc386 install CPU_TARGET=powerpc CROSSINSTALL=1
471+$ INSTALLED_VERSION=`./compiler/ppc386 -iV`
472+$ sudo mv /usr/local/lib/fpc/$INSTALLED_VERSION/ppcrossppc /usr/local/lib/fpc/$INSTALLED_VERSION/ppcppc
473+```
474+
475+Reminder: Universal binaries are created from the individual (i386 and powerpc) binaries using lipo.
476+
477+### From macOS i386 to x86_64
478+
479+The official FPC installer for macOS/i386 includes an x86_64 compiler and all units necessary to compile x86_64 programs (use *ppcx64* instead of *ppc386* to compile your programs or use fpc -Px86_64). The instructions below are only necessary if you want to compile and install a new version from svn.
480+
481+- Compile FPC:
482+
483+``` bash
484+$ cd fpc
485+$ make all CPU_TARGET=x86_64
486+```
487+
488+This creates the x86_64 cross-compiler (fpc/compiler/ppcrossx64) and all units. You can install them using the following commands:
489+
490+``` bash
491+$ sudo make crossinstall CPU_TARGET=x86_64
492+$ sudo mv /usr/local/lib/fpc/2.7.1/ppcrossx64 /usr/local/lib/fpc/2.7.1/ppcx64
493+```
494+
495+If you want to make this newly installed compiler the default version (this is ***not*** recommended, and will break your ability to build new FPC 2.7.1 versions without explicitly specifying the path to the latest official FPC release), also execute the following command:
496+
497+``` bash
498+$ sudo ln -sf /usr/local/lib/fpc/2.7.1/ppcx64 /usr/local/bin/ppcx64
499+```
500+
501+Assuming all of the LCL components your project uses are supported by the [Cocoa widgetset](http://wiki.lazarus.freepascal.org/Roadmap#Status_of_features_on_each_LCL_Interface), you can compile a Lazarus project from the command line, using a command like this (full path to the compiler seems required):
502+
503+``` bash
504+$ lazbuild -B project1.lpr --ws=cocoa --cpu=x86_64 --os=darwin --compiler=/usr/local/bin/ppcx64
505+```
506+
507+You can check that your executable is 64-bit uses the "file" command:
508+
509+``` bash
510+$ file ./project1
511+$ ./project1: Mach-O 64-bit executable x86_64
512+```
513+
514+Alternatively, you can set your project to compile as 64-bit using the Lazarus graphical interface:
515+
516+- Choose the Project/ProjectOptions menu item
517+- For CompilerOptions/ConfigAndTarget set the "Target CPU family" to "x86_64"
518+- For CompilerOptions/AdditionsAndOverrides store the "LCLWidgetType := cocoa" in the LPI
519+
520+> **Note:** Before macOS 10.15 (Catalina), a 64-bit Mac computer could run 32-bit executables. With macOS 10.15 and higher, 32-bit executables can no longer run.
521+
522+If you want to create a universal binary that executes on a 32-bit Intel as well as in 64-bit mode on a pre-Catalina 64-bit Intel computer you can use the "lipo" command. This would allow the 64-bit computer to access more memory and in theory might perform a bit better (e.g. different compiler optimizations, more registers though with larger pointers). Assuming you have generated separate 32-bit ("project32") and 64-bit ("project64") executables with Lazarus.
523+
524+``` bash
525+$ lipo -create project32 project64 -o projectUniversal
526+```
527+
528+### From macOS x86_64 to i386
529+
530+The official Free Pascal Compiler installer for macOS includes an i386 32 bit compiler and all units necessary to compile i386 programs (use ppc386 instead of ppcx64 to compile your programs or use fpc -Pi386). **The instructions below are only necessary if you want to compile and install a new version from the git repository.**
531+
532+You need a bootstrap i386 compiler (ppc386). A Free Pascal Compiler release can always be built by the previously released FPC version, and FPC trunk can always be built by the current FPC version. So, as at May 2022:
533+
534+- to build FPC v3.2.2, you need an FPC v3.2.0 ppc386 i386 bootstrap compiler;
535+- to build trunk you need an FPC v3.2.2 ppc386 i386 bootstrap compiler.
536+
537+Once you have a bootstrap i386 compiler, then to use that compiler you pass it on the command line with FPC= as below:
538+
539+``` bash
540+$ make FPC=/usr/local/lib/fpc/3.2.2/ppc386 distclean CPU_SOURCE=i386
541+```
542+
543+And install with:
544+
545+``` bash
546+$ make install CPU_TARGET=i386
547+```
548+
549+### From macOS to any using fink
550+
551+The FPC package of the package manager [fink](http://finkproject.org/) has a 64-bit compiler for macOS and cross compilers to Windows, Linux, FreeBSD and others on various CPUs.
552+
553+Examples for installing a cross compiler are:
554+
555+``` bash
556+$ fink install fpc-cross-i386-win32
557+```
558+
559+or
560+
561+``` bash
562+$ fink install fpc-cross-arm-linux
563+```
564+
565+To compile use these commands:
566+
567+``` bash
568+fpc -Pi386 -Twin32 FILENAME
569+fpc -Parm -Tlinux FILENAME
570+```
571+
572+This command gives the list of cross compilers:
573+
574+``` bash
575+$ fink list fpc-cross
576+```
577+
578+For other platforms (processors and systems) you have to do the setup by yourself. It is basically the same scheme: First, you need the corresponding binutils (see [[Binutils]]) and second, the cross compiler and the run time library. Some more details of the building procedure can be learned from the fink package description files of the cross compilers from above.
579+
580+## From FreeBSD
581+
582+### FreeBSD to SPARC
583+
584+> **Warning:** This section appears to date from around 2005 and may not be relevant anymore. Updates are welcome.
585+
586+I managed to crosscompile from x86 to Sparc Solaris 9. However the result doesn't work very well, but here is my command-line:
587+
588+in compiler/ execute:
589+
590+``` bash
591+$ gmake cycle CPU_TARGET=sparc OS_TARGET=solaris CROSSBINUTILPREFIX=solaris-sparc- CROSSOPT='-Xd -Fl~/src/sollib'
592+```
593+
594+~/src/sollib is a directory that contains:
595+
596+- a set of .o's from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
597+- libgcc.a from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
598+- a set of lib*.so from /usr/lib: libaio.so libmd5.so libc.so libelf.so librt.so libdl.so libm.so
599+
600+Problem is illustrated by the following binary.
601+
602+` Free Pascal Compiler version 2.1.1 [2006/03/17] for sparc`\
603+` Copyright (c) 1993-2005 by Florian Klaempfl`\
604+` Target OS: Solaris for SPARC`\
605+` Compiling system.pp`\
606+` system.pp(15,1) Fatal: Syntax error, "BEGIN" expected but "identifier UNIT" found`
607+
608+I suspect wrong .o's are taken.
609+
610+## From within Docker container
611+
612+Cross compiling hello world with Docker image and Free Pascal Compiler 3.0.4
613+
614+1\. Pull docker image:
615+
616+``` bash
617+$ sudo docker pull taraworks/lazarus-cross:0.0.2 # (do not use latest)
618+```
619+
620+2\. Create container with virtual volume based on the pulled image:
621+
622+a\. Identify image ID (first 4 digits are needed):
623+
624+``` bash
625+$ sudo docker images
626+```
627+
628+b\. Use the image for the container, map virtual volume from host:
629+
630+``` bash
631+$ sudo docker create --name pascalContainer -v /home/tudi/pascal_files:/home/tudi/pascal_files -ti image ID
632+```
633+
634+3\. Start the container
635+
636+a\. Identify container ID (first 4 digits are needed):
637+
638+``` bash
639+$ sudo docker ps -a
640+```
641+
642+b\. Start container:
643+
644+``` bash
645+$ sudo docker start container ID
646+```
647+
648+4\. Compile file
649+
650+a\. Copy Pascal file hello.pas from <https://github.com/taraworks/lazarus-cross> to folder /home/tudi/pascal_files on host
651+
652+b\. Run on host:
653+
654+``` bash
655+$ cd /home/tudi/pascal_files
656+```
657+
658+``` bash
659+$ git clone https://github.com/taraworks/lazarus-cross.git
660+```
661+
662+b\. Attach to container to check the cloned repo is presented:
663+
664+c\. Run on host:
665+
666+``` bash
667+$ sudo docker attach container ID
668+```
669+
670+Press 'Enter' one more time and check hello.pas is in container folder. Do not detach with exit from container as container will stop.
671+
672+c\. Compile from container. Change directory to the folder containing hello.pas:
673+
674+For Windows:
675+
676+``` bash
677+PATH=$PATH:/opt/clang/bin:/opt/osxcross/target/bin /opt/windows/lib/fpc/3.0.4/ppcross386 -Twin32 -va hello.pas
678+```
679+
680+For macOS:
681+
682+``` bash
683+PATH=$PATH:/opt/clang/bin:/opt/osxcross/target/bin /opt/darwin/lib/fpc/3.0.4/ppcross386 -Tdarwin -XR/opt/osxcross/target/SDK/MacOSX10.11.sdk -va hello.pas
684+```
685+
686+d\. Compile from host.
687+
688+``` bash
689+$ sudo docker exec pascalContainer bash -c "cd ${CI_PROJECT_DIR} && PATH=$PATH:/opt/clang/bin:/opt/osxcross/target/bin /opt/windows/lib/fpc/3.0.4/ppcross386 -Twin32 -va /home/tudi/pascal_files/lazarus-cross/hello.pas"
690+```
691+
692+## General Unix/Linux notes
693+
694+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\>.
695+
696+Option -XR\<sysroot\> (recent trunk) that can be used to specify the target system root. It's used for:
697+
698+- 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.
699+- detecting the C library (linux specific): glibc or uclibc. E.g. for uclibc detection '\<sysroot\>/lib/ld-uClibc.so.0' is tried.
700+
701+## Cross compiling the LCL
702+
703+Since 0.9.31 the LCL is a normal Lazarus package and the IDE will automatically cross compile all needed packages, when you change the target platform of your project.
704+
705+If something goes wrong, here are some hints that might help to find out why:
706+
707+### Test cross compiler
708+
709+Test if you have installed the cross compiled FPC correctly:
710+
711+Create a hello world program test.pas:
712+
713+``` pascal
714+program test;
715+begin
716+ writeln('DATE ',{$i %DATE%});
717+ writeln('FPCTARGET ',{$i %FPCTARGET%});
718+ writeln('FPCTARGETCPU ',{$i %FPCTARGETCPU%});
719+ writeln('FPCTARGETOS ',{$i %FPCTARGETOS%});
720+ writeln('FPCVERSION ',{$i %FPCVERSION%});
721+end.
722+```
723+
724+And compile it with your source/original platform. Example for x86 Windows:
725+
726+``` bash
727+fpc -Twin32 -Pi386 test.pas
728+```
729+
730+Then test source compiler:
731+
732+``` bash
733+test
734+```
735+
736+Replace *win32* and *i386* with your targets. Example for target Windows 64 bit:
737+
738+``` bash
739+fpc -Twin64 -Px86_64 test.pas
740+```
741+
742+Then test cross compiler:
743+
744+``` bash
745+test
746+```
747+
748+The program **fpc** is a wrapper that searches the right compiler (eg ppcrossx64) for the target and executes it.
749+
750+If this does not work, your cross compiler was not installed correctly. When this works you can cross compile the LCL.
751+
752+### Cross compiling the LCL in Lazarus 0.9.30 and below
753+
754+If you are sure your cross compiler works, you can do the actual cross compile.
755+
756+Perform the following steps in the Lazarus IDE to do an LCL cross compile: In older IDEs:
757+
758+- Set in *Tools -\> Options -\> Environment -\> Files* the *Compiler path* to the path to *fpc*. Normally this is already done.
759+- Then open *Tools -\> Configure Build Lazarus*.
760+- Set *Target OS* (e.g. to *Win64*) and *Target CPU* (e.g. to *x86_64*)
761+- Click the *Build* button.
762+
763+### Command line
764+
765+Apart from the IDE, the command line also allows you to build a cross compiled LCL.
766+
767+> **Note:** Since 0.9.31 you should use lazbuild to cross compile Lazarus packages. See lazbuild -h for a list of options.
768+
769+An example: you would cross compile a Windows 64 cross compiler using:
770+
771+- First thoroughly clean any 64 bit leftovers. This does not touch your 32 bit environment:
772+
773+``` bash
774+make distclean LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64
775+```
776+
777+- Then build LCL and its required dependencies. We're using LCL_PLATFORM as that presumably corresponds to the widgetset, which is still Windows 32 even on Windows 64 (the widgetsets are the same).
778+
779+``` bash
780+make packager/registration lazutils lcl LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64
781+```
782+
783+The LCL for your normal OS is untouched.
784+
785+## Cross compiling LCL applications
786+
787+You first need to cross compile the LCL. See above.
788+
789+Cross compiling applications means: compiling plus linking. When you have cross compiled the LCL the compilation part is easy. Just set in the compiler options of the IDE the Target OS and Target CPU. The tricky part is the linking. If you cross compile a project you may see something like this:
790+
791+`/usr/local/bin/arm-linux-ld: cannot find -lX11`
792+
793+This means you have to install the graphical libraries of the target system. This has nothing to do with FPC/Lazarus, but with cross compiling a library. Some distributions provides pre compiled packages for this. For example Microsoft provides cross compiled libraries for WinCE for Windows. Under Linux you can install Wine to cross compile from Linux to Windows. Some Linux distributions provide 64bit libraries for 32bit systems.
794+
795+## Cross compile FAQ
796+
797+### Why cross compile?
798+
799+So you can develop a program for one OS/CPU and compile it for another OS/CPU without rebooting or switching computers.
800+
801+### Why not to cross compile?
802+
803+In many cases, you will want to test the application which you have cross compiled on its native platform. Compiling the application on that platform in the first place may be easier to set up, especially for new users.
804+
805+One way of being able to compile and test your application on a non-native platform is to use a Virtual Machine (VM) of that platform on your computer. For example, you could setup a Linux/FreeBSD/Windows VM running on an Apple computer running its native macOS operating system.
806+
807+There are a number of commercial and free Virtual Machine solutions:
808+
809+- [VMware Fusion Pro for Mac](https://www.vmware.com/products/fusion.html) - Host system must be running macOS (Commercial).
810+- [VMware Fusion Player for Mac](https://www.vmware.com/products/fusion.html) - Host system must be running macOS (dual-licence: Commercial/Free for Personal Use). Do not be fooled by the name; this is able to create VMs. The difference between Pro and Player is that Player lacks some of the advanced features (eg encrypted VMs) which can be found in the Pro version.
811+- [VMware Workstation Player](https://www.vmware.com/products/workstation-player.html) - Host system running Windows 64 bit or Linux 64 bit (Commercial/Free for personal use).
812+- [VMware Workstation Pro](https://www.vmware.com/products/workstation-pro.html) - Host system running Windows 64 bit or Linux 64 bit (Commercial/Free trial).
813+- [Parallels Desktop for Mac](https://www.parallels.com/) - Host system must be running macOS (Commercial/Free trial).
814+- [VirtualBox](https://www.virtualbox.org/) - Host system can be running macOS, Windows, Linux or Solaris (Open Source).
815+
816+Some, eg Parallels on the Mac, make it trivial to install a desktop Linux operating system with a single click.
817+
818+### Why cross compile from Unix to Windows and not the other way around?
819+
820+See [[Cross compiling for Win32 under Linux|Why Unix to Windows and not the other way around]]
821+
822+### I want more information on building Free Pascal. Where is it?
823+
824+There is a general FAQ in pdf format about how to build and configure FPC: [[buildfaq]].
825+
826+### Errors like compiler "/usr/bin/fpc" does not support target arm-linux
827+
828+Apart from other causes, this error may occur if you edited fpc.cfg with incorrect options for the cross compiler (e.g. specifying parameters all on one line instead of one per line).
829+
830+## References
831+
832+1. S. Ribić and M. Beganović, "Cross compilation under Lazarus IDE," 2013 21st Telecommunications Forum Telfor (TELFOR), Belgrade, 2013, pp. 1007-1010, [doi 10.1109/TELFOR.2013.6716402](https://doi.org/10.1109/TELFOR.2013.6716402).
833+
834+---
835+*From the Free Pascal wiki, page "Cross compiling", as it stood on 2023-10-07 after a change by Dbannon, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history