Sign in Join
Wiki copytemporary

Cross compiling: what changed

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

OldNewLine
11## Introduction
22
33> **Note:** Before going any further, consider [[Cross compiling|Why not to cross compile?]] below
44
55This 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".
66
77Free 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.
88
99### Host and target on the same CPU
1010
1111FPC 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.
1212
1313### Host and target on different CPUs
1414
1515If 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.
1616
1717### Supported targets
1818
1919See the [[Free Pascal supported targets|Supported target operating systems]] article for the full list.
2020
2121### Assembler and linker
2222
2323The 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.
2424
2525See [[Binutils]].
2626
2727### Units for target
2828
2929After 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).
3030
3131Its 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-
3232
33-`arm-linux`\
34-`i386-linux`\
35-`i386-win32`\
36-`x86_64-linux`\
37-`x86_64-win64`
33+```text
34+arm-linux
35+i386-linux
36+i386-win32
37+x86_64-linux
38+x86_64-win64
39+```
3840
3941Each of those directories will contain a directory for each of the FPC units, each one with .o and .ppu files.
4042
4143### Configuration
4244
4345Then 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.).
4446
4547### Basic Steps
4648
4749There are a few common steps involved in cross compiling that you must do in every case:
4850
4951- Have already a Free Pascal compiler for the platform you wish to compile from.
5052- You need to have the Free Pascal source code (except for the special case of having everything prepared by someone else).
5153- 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.
5254- Sometimes you will need some files from the target you are compiling to.
5355
5456## From Linux
5557
5658### From Linux x64 to Linux i386
5759
5860Chances 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.
5961
6062#### Install the 32bit libraries
6163
6264On 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.
6365
6466``` bash
6567sudo dpkg --add-architecture i386
6668sudo apt update
6769sudo 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
6870```
6971
7072Note 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.
7173
7274This 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 -
7375
7476``` bash
7577# path to the gcclib,
7678#ifdef cpui386
7779-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
7880#endif
7981```
8082
8183Check 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
8284
8385#### Create ld and as files
8486
8587Check if you already have the files i386-linux-ld and i386-linux-as by doing the following commands:
8688
8789``` bash
8890$ which i386-linux-ld
8991$ which i386-linux-as
9092```
9193
9294If you get nothing, it means you need to create them. If you have these files skip to the **Compile FPC** (see below).
9395
9496Those 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:
9597
9698``` bash
9799#!/bin/bash
98100ld -A elf32-i386 $@
99101```
100102
101103**/usr/bin/i386-linux-as** must contain:
102104
103105``` bash
104106#!/bin/bash
105107as --32 $@
106108```
107109
108110Both can be created using following commands:
109111
110112``` bash
111113# Create /usr/bin/i386-linux-ld
112114$ cat >/usr/bin/i386-linux-ld << EOF
113115#!/bin/bash
114116ld -A elf32-i386 \$@
115117EOF
116118$ chmod +x /usr/bin/i386-linux-ld
117119
118120# Create /usr/bin/i386-linux-as
119121$ cat >/usr/bin/i386-linux-as << EOF
120122#!/bin/bash
121123as --32 \$@
122124EOF
123125$ chmod +x /usr/bin/i386-linux-as
124126```
125127
126128#### Compile The Cross Compiler
127129
128130You 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 -
129131
130132``` bash
131133
132134$ cd /usr/share/fpcsrc/<version>
133135$ sudo make all OS_TARGET=linux CPU_TARGET=i386
134136$ sudo make crossinstall OS_TARGET=linux CPU_TARGET=i386 INSTALL_PREFIX=/usr
135137$ ls -la /usr/lib/fpc/<version>/ppcross386
136138```
137139
138140If the last command there shows you a nice file called ppcross386, great, proceed to the next command
139141
140-`$ sudo ln -s /usr/lib/fpc/<version>/ppcross386  /usr/bin/ppcross386`
142+```text
143+$ sudo ln -s /usr/lib/fpc/<version>/ppcross386 /usr/bin/ppcross386
144+```
141145
142146If, 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 -
143147
144-`$ sudo ln -s  /usr/share/fpcsrc/<version>/compiler/ppcross386  /usr/bin/ppcross386`\
148+```text
149+$ sudo ln -s /usr/share/fpcsrc/<version>/compiler/ppcross386 /usr/bin/ppcross386
150+```
145151
146152On the other hand perhaps you are installing in user space and assuming your existing compiler is in in \$HOME/bin/FPC you might do -
147153
148154``` bash
149155
150156$ cd $HOME/bin/FPC/SRC/fpc-3.2.0
151157$ make all CPU_TARGET=i386
152158$ make crossinstall CPU_TARGET=i386 INSTALL_PREFIX=$HOME/bin/FPC
153159$ ln -s $HOME/bin/FPC/lib/fpc/3.2.0/ppcross386 $HOME/bin/FPC/bin/ppcross386
154160```
155161
156162Thats it ! You may need to edit your fpc.cfg (it lives in either /etc/fpc.cfg or \$HOME/.fpc.cfg).
157163
158164Note 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 -
159165
160166``` bash
161167#ifdef cpui386
162168-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
163169#endif
164170```
165171
166172Make it look like this, one additional line -
167173
168174``` bash
169175#ifdef cpui386
170176-Fl/usr/lib/gcc/x86_64-linux-gnu/9/32
171177-Fl/usr/lib32
172178#endif
173179```
174180
175181Again, the above says /usr/lib/gcc/x86_64-linux-gnu/**9**/32, the '9' will change over time, on Bullseye its '10'.
176182
177183#### Testing
178184
179185Before you proceed any further, its a good idea to test what you have done so far.
180186
181187With a simple hello.pas file
182188
183189``` bash
184190$> fpc -Pi386 hello.pas <enter>
185191$> file hello <enter>
186192```
187193
188194### From Linux to ARM Linux
189195
190196#### Maemo 5 OS
191197
192198Information about targeting Linux running on ARM (e.g. Zaurus) may be found in [[Setup Cross Compile For ARM]].
193199
194200#### Raspberry Pi
195201
196202Information about targeting Linux running on a Raspberry Pi may be found in [[Cross Compile to RasPi from Linux]].
197203
198204### From Linux to Windows
199205
200206Information on cross-compilation with Lazarus can be found in [[Cross compiling for Windows under Linux]]
201207
202208### From Linux to macOS
203209
204210Please see [[Cross compiling OSX on Linux|Cross compiling macOS on Linux]].
205211
206212## From Windows
207213
208214### From Windows to Android
209215
210216For a tutorial on how to create Android apps with Lazarus on Windows, see [[Android tutorial]].
211217
212218### From Windows to Linux
213219
214220This is less trivial, there is some info in the [[buildfaq]]
215221
216222See also [[fpcup]] for descriptions on which binutils work and what libraries/files to copy.
217223
218224As 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:
219225
220226``` bash
221227$ grep -i "ld script" *
222228```
223229
224230Remove 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.
225231
226232### From Windows to GO32v2
227233
228234Detailed information may be found in [[Cross-compilation from Win32 to GO32v2]].
229235
230236### From Windows to winCE
231237
232238- [[arm-wince]] describes how to setup a crosscompiler for arm CPU
233239- [[i386-wince]] describes how to setup compiling for i386 CPU (no crosscompiling)
234240
235241> **Note:** Lazarus installers have an installer that adds Windows to WinCE cross compilation options automatically
236242
237243### From win32 to win64
238244
239245If you are compiling the 2.1.1 or greater branch of fpc you can just do:
240246
241247``` bash
242248$ make all OS_TARGET=win64 CPU_TARGET=x86_64
243249```
244250
245251and then
246252
247253``` bash
248254$ make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64
249255```
250256
251257### From win64 to win32
252258
253259Assuming that Lazarus 2.0.10 was previously installed, now install
254260
255-**`lazarus-2.0.10-fpc-3.2.0-cross-i386-win32-win64.exe`**` `
261+```text
262+lazarus-2.0.10-fpc-3.2.0-cross-i386-win32-win64.exe
263+```
256264
257265in the same base directory and then setup your project options to:
258266
259267- Target OS : Win32
260268- Target CPU : i386
261269
262270Failing to set the CPU (Default) lead to incorrect win32-x86_64 platform!
263271
264272### Lazarus guide to cross-compile Win 32/64-bit
265273
266274Download the installers from sourceforge.net (click on the Files tab):
267275
268276**[<https://sourceforge.net/projects/lazarus/>](https://sourceforge.net/projects/lazarus/)**
269277
270278The installers include FPC and the Lazarus help files *(as of Oct. 20, 2019)*:
271279
272280- Lazarus 32-bit
273281 - lazarus-2.0.4-fpc-3.0.4-win32.exe
274282 - lazarus-2.0.4-fpc-3.0.4-cross-x86_64-win64-win32.exe
275283
276284- Lazarus 64-bit
277285 - lazarus-2.0.4-fpc-3.0.4-win64.exe
278286 - lazarus-2.0.4-fpc-3.0.4-cross-i386-win32-win64.exe
279287
280288To install Lazarus 32-bit, and cross-compile a Windows 64-bit exe:
281289
2822901. Install the win32.exe
2832912. Install the cross-x86_64-win64-win32.exe in the same folder
284292
285293To install Lazarus 64-bit, and cross-compile a Windows 32-bit exe:
286294
2872951. Install the win64.exe
2882962. Install the cross-i386-win32-win64.exe in the same folder
289297
290298(The following assumes Lazarus 64-bit with cross-i386-win32-win64)
291299
292300To cross-compile 32-bit or 64-bit without creating Build Modes:
293301
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+```text
303+ Project, Options, Compiler Options, Config and Target:
304+ Target OS =Default=Win64 or Win32 for 32-bit
305+ Target CPU family =Default=x86_64 or i386 for 32-bit
306+ Target processor =Default
307+ Press OK to exit Project Options
308+ Build and run the project
309+ Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit
310+```
302311
303312To Configure Build Modes:
304313
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`
314+```text
315+ Project, Options, Compiler Options, Config and Target:
316+ Check 'Build Modes', then press the [...] button
317+ Press [Create Debug and Release Modes] button
318+ Press OK
319+
320+ Create a Debug 32-bit Build Mode:
321+ Lazarus menu: Project, Options, Compiler Options, Config and Target
322+ Select Build Mode = Debug
323+ Press the Build Modes [...] button
324+ Click to select Debug on the list
325+ Press the [ + ] button to add a new build mode
326+ Rename to 'Debug 32-bit', press OK
327+ Set Target Platform to 32-bit:
328+ Target OS =Win32
329+ Target CPU family =i386
330+ Target processor =Default
331+ Press OK to exit Project Options and save Build Mode 'Debug 32-bit'
332+
333+ Create a Debug 64-bit Release Mode:
334+ Lazarus menu: Project, Options, Compiler Options, Config and Target
335+ Select Build Mode = Release
336+ Press the Build Modes [...] button
337+ Click to select Release on the list
338+ Press the [ + ] button to add a new build mode
339+ Rename to 'Release 32-bit', press OK
340+ Set Target Platform to 32-bit:
341+ Target OS =Win32
342+ Target CPU family =i386
343+ Target processor =Default
344+ Press OK to exit Project Options and save Build Mode 'Release 32-bit'
345+ Build and run the project
346+ Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit
347+```
337348
338349To use Build Modes:
339350
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`
351+```text
352+ Lazarus IDE Menu: Change Build Mode dropdown (left of Run button)
353+ Build and run the project
354+ Use Windows Task Manager, Details tab, to see if Project exe is 32/64-bit
355+```
343356
344357## From macOS (Darwin)
345358
346359You 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.
347360
348361### From macOS to Win32
349362
350363To 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:
351364
352365- to build FPC v3.2.0, you need an FPC v3.0.4 ppc386 i386 bootstrap compiler;
353366- to build trunk (v3.3.1) you need an FPC v3.2.0 ppc386 i386 bootstrap compiler.
354367
355368Once 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:
356369
357-`# Open a Terminal and navigate to the FPC source code directory.`\
358-`$ cd /usr/local/share/fpcsrc/`
370+```text
371+# Open a Terminal and navigate to the FPC source code directory.
372+$ cd /usr/local/share/fpcsrc/
373+```
359374
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`
375+```text
376+# Compile the FPC trunk cross compiler using the released FPC 3.2.0 compiler.
377+$ sudo make clean all FPC=/usr/local/lib/fpc/3.2.0/ppc386 OS_TARGET=win32 CPU_SOURCE=i386
378+```
362379
363-`# Install the cross compiler.`\
364-`$ sudo make crossinstall OS_TARGET=win32 CPU_TARGET=i386`
380+```text
381+# Install the cross compiler.
382+$ sudo make crossinstall OS_TARGET=win32 CPU_TARGET=i386
383+```
365384
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`
385+```text
386+# Soft link the cross compiler to the bin directory with the other compiler binaries.
387+$ sudo ln -s /usr/local/lib/fpc/3.3.1/ppcross386 /usr/local/bin/ppcross386
388+```
368389
369390Now go to the Lazarus IDE and setup the Project Options and Tools Options as follows:
370391
371392- Project Options
372393 - Config and Target
373394 - Target OS Win32
374395 - Target CPU i386
375396 - Target Processor (Default)
376397 - Target specific options \[X\] Win32 gui application
377398 - Current LCL widgetset: "win32"
378399
379400- Tools
380401 - Options
381402 - Environment
382403 - Files
383404 - Compiler executable: /usr/local/bin/ppcross386
384405
385406Once 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.
386407
387408To use the FPC compiler without Lazarus, I use the following shell script:
388409
389410``` bash
390411#!/bin/sh
391412/usr/local/bin/ppcross386 -FUwin32 -FEwin32 -Twin32 ${1}
392413```
393414
394415as follows:
395416
396417``` bash
397418win32 program.pas
398419```
399420
400421This 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.
401422
402423### From macOS to Win64
403424
404425To 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:
405426
406427- to build FPC v3.2.2, you need an FPC v3.2.0 ppcx64 x86_64 bootstrap compiler;
407428- to build trunk (v3.3.1) you need an FPC v3.2.2 ppcx64 x86_64 bootstrap compiler.
408429
409430Once 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:
410431
411-`# Open a Terminal and navigate to the FPC source code directory`\
412-`$ cd /usr/local/share/fpcsrc/`
432+```text
433+# Open a Terminal and navigate to the FPC source code directory
434+$ cd /usr/local/share/fpcsrc/
435+```
413436
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"`
437+```text
438+# Compile the FPC trunk cross compiler using the released FPC 3.2.2 compiler.
439+$ 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"
440+```
416441
417-`# Install the cross compiler.`\
418-`$ sudo make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64`
442+```text
443+# Install the cross compiler.
444+$ sudo make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64
445+```
419446
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`
447+```text
448+# Soft link the cross compiler to the bin directory with the other compiler binaries.
449+$ sudo ln -s /usr/local/lib/fpc/3.3.1/ppcrossx64 /usr/local/bin/ppcrossx64
450+```
422451
423452Now go to the Lazarus IDE and setup the Project Options and Tools Options as follows:
424453
425454- Project Options
426455 - Config and Target
427456 - Target OS Win64
428457 - Target CPU x86_64
429458 - Target Processor (Default)
430459 - Target specific options \[X\] Win32 gui application \[win32 is not a mistake\]
431460 - Current LCL widgetset: "win32" \[win32 is not a mistake\]
432461
433462- Tools
434463 - Options
435464 - Environment
436465 - Files
437466 - Compiler executable: /usr/local/bin/ppcrossx64
438467
439468Once 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.
440469
441470To use the FPC compiler without Lazarus, I use the following shell script located in `/usr/local/bin`:
442471
443472``` bash
444473#!/bin/sh
445474/usr/local/bin/ppcrossx64 -FUwin64 -FEwin64 -Twin64 ${1}
446475```
447476
448477as follows:
449478
450479``` bash
451480win64 program.pas
452481```
453482
454483This 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.
455484
456485### From macOS i386 to PowerPC
457486
458487The 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.
459488
460489- Compile FPC:
461490
462491``` bash
463492$ cd fpc
464493$ make all CPU_TARGET=powerpc -j 2
465494```
466495
467496This creates the powerpc cross-compiler compiler (fpc/compiler/ppcrosspcc) and all units. You can install them using the following commands:
468497
469498``` bash
470499$ sudo make FPC=`pwd`/compiler/ppc386 install CPU_TARGET=powerpc CROSSINSTALL=1
471500$ INSTALLED_VERSION=`./compiler/ppc386 -iV`
472501$ sudo mv /usr/local/lib/fpc/$INSTALLED_VERSION/ppcrossppc /usr/local/lib/fpc/$INSTALLED_VERSION/ppcppc
473502```
474503
475504Reminder: Universal binaries are created from the individual (i386 and powerpc) binaries using lipo.
476505
477506### From macOS i386 to x86_64
478507
479508The 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.
480509
481510- Compile FPC:
482511
483512``` bash
484513$ cd fpc
485514$ make all CPU_TARGET=x86_64
486515```
487516
488517This creates the x86_64 cross-compiler (fpc/compiler/ppcrossx64) and all units. You can install them using the following commands:
489518
490519``` bash
491520$ sudo make crossinstall CPU_TARGET=x86_64
492521$ sudo mv /usr/local/lib/fpc/2.7.1/ppcrossx64 /usr/local/lib/fpc/2.7.1/ppcx64
493522```
494523
495524If 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:
496525
497526``` bash
498527$ sudo ln -sf /usr/local/lib/fpc/2.7.1/ppcx64 /usr/local/bin/ppcx64
499528```
500529
501530Assuming 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):
502531
503532``` bash
504533$ lazbuild -B project1.lpr --ws=cocoa --cpu=x86_64 --os=darwin --compiler=/usr/local/bin/ppcx64
505534```
506535
507536You can check that your executable is 64-bit uses the "file" command:
508537
509538``` bash
510539$ file ./project1
511540$ ./project1: Mach-O 64-bit executable x86_64
512541```
513542
514543Alternatively, you can set your project to compile as 64-bit using the Lazarus graphical interface:
515544
516545- Choose the Project/ProjectOptions menu item
517546- For CompilerOptions/ConfigAndTarget set the "Target CPU family" to "x86_64"
518547- For CompilerOptions/AdditionsAndOverrides store the "LCLWidgetType := cocoa" in the LPI
519548
520549> **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.
521550
522551If 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.
523552
524553``` bash
525554$ lipo -create project32 project64 -o projectUniversal
526555```
527556
528557### From macOS x86_64 to i386
529558
530559The 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.**
531560
532561You 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:
533562
534563- to build FPC v3.2.2, you need an FPC v3.2.0 ppc386 i386 bootstrap compiler;
535564- to build trunk you need an FPC v3.2.2 ppc386 i386 bootstrap compiler.
536565
537566Once you have a bootstrap i386 compiler, then to use that compiler you pass it on the command line with FPC= as below:
538567
539568``` bash
540569$ make FPC=/usr/local/lib/fpc/3.2.2/ppc386 distclean CPU_SOURCE=i386
541570```
542571
543572And install with:
544573
545574``` bash
546575$ make install CPU_TARGET=i386
547576```
548577
549578### From macOS to any using fink
550579
551580The 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.
552581
553582Examples for installing a cross compiler are:
554583
555584``` bash
556585$ fink install fpc-cross-i386-win32
557586```
558587
559588or
560589
561590``` bash
562591$ fink install fpc-cross-arm-linux
563592```
564593
565594To compile use these commands:
566595
567596``` bash
568597fpc -Pi386 -Twin32 FILENAME
569598fpc -Parm -Tlinux FILENAME
570599```
571600
572601This command gives the list of cross compilers:
573602
574603``` bash
575604$ fink list fpc-cross
576605```
577606
578607For 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.
579608
580609## From FreeBSD
581610
582611### FreeBSD to SPARC
583612
584613> **Warning:** This section appears to date from around 2005 and may not be relevant anymore. Updates are welcome.
585614
586615I managed to crosscompile from x86 to Sparc Solaris 9. However the result doesn't work very well, but here is my command-line:
587616
588617in compiler/ execute:
589618
590619``` bash
591620$ gmake cycle CPU_TARGET=sparc OS_TARGET=solaris CROSSBINUTILPREFIX=solaris-sparc- CROSSOPT='-Xd -Fl~/src/sollib'
592621```
593622
594623~/src/sollib is a directory that contains:
595624
596625- a set of .o's from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
597626- libgcc.a from /usr/local/gcc-3.3-32bit/lib/gcc-lib/sparc-sun-solaris/3.3
598627- a set of lib*.so from /usr/lib: libaio.so libmd5.so libc.so libelf.so librt.so libdl.so libm.so
599628
600629Problem is illustrated by the following binary.
601630
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`
631+``` pascal
632+ Free Pascal Compiler version 2.1.1 [2006/03/17] for sparc
633+ Copyright (c) 1993-2005 by Florian Klaempfl
634+ Target OS: Solaris for SPARC
635+ Compiling system.pp
636+ system.pp(15,1) Fatal: Syntax error, "BEGIN" expected but "identifier UNIT" found
637+```
607638
608639I suspect wrong .o's are taken.
609640
610641## From within Docker container
611642
612643Cross compiling hello world with Docker image and Free Pascal Compiler 3.0.4
613644
6146451\. Pull docker image:
615646
616647``` bash
617648$ sudo docker pull taraworks/lazarus-cross:0.0.2 # (do not use latest)
618649```
619650
6206512\. Create container with virtual volume based on the pulled image:
621652
622653a\. Identify image ID (first 4 digits are needed):
623654
624655``` bash
625656$ sudo docker images
626657```
627658
628659b\. Use the image for the container, map virtual volume from host:
629660
630661``` bash
631662$ sudo docker create --name pascalContainer -v /home/tudi/pascal_files:/home/tudi/pascal_files -ti image ID
632663```
633664
6346653\. Start the container
635666
636667a\. Identify container ID (first 4 digits are needed):
637668
638669``` bash
639670$ sudo docker ps -a
640671```
641672
642673b\. Start container:
643674
644675``` bash
645676$ sudo docker start container ID
646677```
647678
6486794\. Compile file
649680
650681a\. Copy Pascal file hello.pas from <https://github.com/taraworks/lazarus-cross> to folder /home/tudi/pascal_files on host
651682
652683b\. Run on host:
653684
654685``` bash
655686$ cd /home/tudi/pascal_files
656687```
657688
658689``` bash
659690$ git clone https://github.com/taraworks/lazarus-cross.git
660691```
661692
662693b\. Attach to container to check the cloned repo is presented:
663694
664695c\. Run on host:
665696
666697``` bash
667698$ sudo docker attach container ID
668699```
669700
670701Press 'Enter' one more time and check hello.pas is in container folder. Do not detach with exit from container as container will stop.
671702
672703c\. Compile from container. Change directory to the folder containing hello.pas:
673704
674705For Windows:
675706
676707``` bash
677708PATH=$PATH:/opt/clang/bin:/opt/osxcross/target/bin /opt/windows/lib/fpc/3.0.4/ppcross386 -Twin32 -va hello.pas
678709```
679710
680711For macOS:
681712
682713``` bash
683714PATH=$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
684715```
685716
686717d\. Compile from host.
687718
688719``` bash
689720$ 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"
690721```
691722
692723## General Unix/Linux notes
693724
694725Option -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\>.
695726
696727Option -XR\<sysroot\> (recent trunk) that can be used to specify the target system root. It's used for:
697728
698729- 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.
699730- detecting the C library (linux specific): glibc or uclibc. E.g. for uclibc detection '\<sysroot\>/lib/ld-uClibc.so.0' is tried.
700731
701732## Cross compiling the LCL
702733
703734Since 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.
704735
705736If something goes wrong, here are some hints that might help to find out why:
706737
707738### Test cross compiler
708739
709740Test if you have installed the cross compiled FPC correctly:
710741
711742Create a hello world program test.pas:
712743
713744``` pascal
714745program test;
715746begin
716747 writeln('DATE ',{$i %DATE%});
717748 writeln('FPCTARGET ',{$i %FPCTARGET%});
718749 writeln('FPCTARGETCPU ',{$i %FPCTARGETCPU%});
719750 writeln('FPCTARGETOS ',{$i %FPCTARGETOS%});
720751 writeln('FPCVERSION ',{$i %FPCVERSION%});
721752end.
722753```
723754
724755And compile it with your source/original platform. Example for x86 Windows:
725756
726757``` bash
727758fpc -Twin32 -Pi386 test.pas
728759```
729760
730761Then test source compiler:
731762
732763``` bash
733764test
734765```
735766
736767Replace *win32* and *i386* with your targets. Example for target Windows 64 bit:
737768
738769``` bash
739770fpc -Twin64 -Px86_64 test.pas
740771```
741772
742773Then test cross compiler:
743774
744775``` bash
745776test
746777```
747778
748779The program **fpc** is a wrapper that searches the right compiler (eg ppcrossx64) for the target and executes it.
749780
750781If this does not work, your cross compiler was not installed correctly. When this works you can cross compile the LCL.
751782
752783### Cross compiling the LCL in Lazarus 0.9.30 and below
753784
754785If you are sure your cross compiler works, you can do the actual cross compile.
755786
756787Perform the following steps in the Lazarus IDE to do an LCL cross compile: In older IDEs:
757788
758789- Set in *Tools -\> Options -\> Environment -\> Files* the *Compiler path* to the path to *fpc*. Normally this is already done.
759790- Then open *Tools -\> Configure Build Lazarus*.
760791- Set *Target OS* (e.g. to *Win64*) and *Target CPU* (e.g. to *x86_64*)
761792- Click the *Build* button.
762793
763794### Command line
764795
765796Apart from the IDE, the command line also allows you to build a cross compiled LCL.
766797
767798> **Note:** Since 0.9.31 you should use lazbuild to cross compile Lazarus packages. See lazbuild -h for a list of options.
768799
769800An example: you would cross compile a Windows 64 cross compiler using:
770801
771802- First thoroughly clean any 64 bit leftovers. This does not touch your 32 bit environment:
772803
773804``` bash
774805make distclean LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64
775806```
776807
777808- 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).
778809
779810``` bash
780811make packager/registration lazutils lcl LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64
781812```
782813
783814The LCL for your normal OS is untouched.
784815
785816## Cross compiling LCL applications
786817
787818You first need to cross compile the LCL. See above.
788819
789820Cross 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:
790821
791-`/usr/local/bin/arm-linux-ld: cannot find -lX11`
822+```text
823+/usr/local/bin/arm-linux-ld: cannot find -lX11
824+```
792825
793826This 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.
794827
795828## Cross compile FAQ
796829
797830### Why cross compile?
798831
799832So you can develop a program for one OS/CPU and compile it for another OS/CPU without rebooting or switching computers.
800833
801834### Why not to cross compile?
802835
803836In 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.
804837
805838One 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.
806839
807840There are a number of commercial and free Virtual Machine solutions:
808841
809842- [VMware Fusion Pro for Mac](https://www.vmware.com/products/fusion.html) - Host system must be running macOS (Commercial).
810843- [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.
811844- [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).
812845- [VMware Workstation Pro](https://www.vmware.com/products/workstation-pro.html) - Host system running Windows 64 bit or Linux 64 bit (Commercial/Free trial).
813846- [Parallels Desktop for Mac](https://www.parallels.com/) - Host system must be running macOS (Commercial/Free trial).
814847- [VirtualBox](https://www.virtualbox.org/) - Host system can be running macOS, Windows, Linux or Solaris (Open Source).
815848
816849Some, eg Parallels on the Mac, make it trivial to install a desktop Linux operating system with a single click.
817850
818851### Why cross compile from Unix to Windows and not the other way around?
819852
820853See [[Cross compiling for Win32 under Linux|Why Unix to Windows and not the other way around]]
821854
822855### I want more information on building Free Pascal. Where is it?
823856
824857There is a general FAQ in pdf format about how to build and configure FPC: [[buildfaq]].
825858
826859### Errors like compiler "/usr/bin/fpc" does not support target arm-linux
827860
828861Apart 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).
829862
830863## References
831864
8328651. 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).
833866
834867---
835868*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