Cross compiling/es

From Lazarus wiki
Jump to: navigation, search

Deutsch (de) English (en) español (es) français (fr) magyar (hu) português (pt) русский (ru) 中文(中国大陆)‎ (zh_CN) 中文(台灣)‎ (zh_TW)

Introducción

Esto es una breve introducción para gente nueva en esta temática. Las siguientes secciones describen como configurar un sistema para realizar compilación cruzada - e.g. trabajar bajo linux y generar ejecutables Win32 desde el mismo (o esto mismo para FreeBSD o Darwin, etc.). En este caso la plataforma utilizada para la compilación es referida habitualmente como "host" o anfitrión (Linux en el ejemplo anterior), mientras que la plataforma para la que queremos generar los binaros ejecutables es el "target" u objetivo. FreePascal es un compilador y básicamente convierte el código fuente en binarios (lenguaje máquina). Estos binarios además contienen información sobre como los inicia el sistema operativo. Además, los binarios referencian a las APIs aportadas por un sistema operativo en particular, siendo esta la razón por la que es necesaria una implementación diferente de la Run Time Library (RTL) para cada sistema operativo. Por lo tanto dichos binarios son específicos de cada plataforma. FreePascal por si mismo no necesita demasiada configuración. Puede crear binarios para muchas plataformas. Simplemente indícaselo.

"Host" y "Target" en la misma CPU

FPC se ha diseñado de manera que el compilador distribuido pueda generar código máquina para una cierta CPU (debido a que diferentes CPUs necesitan diferente código máquina) y conozca los requerimientos específicos para todas las plataformas soportadas (Sistemas Operativos) disponibles en una CPU en particular. Esto significa que se puede realizar compilación cruzada (cross-compilation) con un mismo compilador usado para compilación nativa siempre que mantengas la misma CPU.

"Host" y "Target" en diferentes CPUs

Si necesitas crear binarios para una CPU diferente entonces necesitas un compilador cruzado especial, i.e. compilador funcionando en la plataforma host, pero capaz de crear código máquina para una CPU diferente (en el caso de FPC, tal compilador-cruzado debería ser de nuevo capaz de establecer como objetivo final (target) todas las plataformas disponibles en la CPU que deseemos. Este compilador cruzado se encuentra habitualmente almacenado en el mismo directorio que el compilador nativo. Tal compilador cruzado debería poder ser compilado por ti mismo, o por otro lado utilizar uno ya creado distribuible (disponible aportado por el equipo FPC) para algunas plataformas directamente (usualmente plataformas mayoritariamente utilizadas en dispositivos portables tales como arm-linux o arm-wince, debido a que no se utilizan habitualmente como plataformas host). El binario FPC puede entonces seleccionar el compilador correcto (por tanto el compilador nativo o el compilador cruzado) para la CPU objetivo seleccionada utilizando el parámetro -P.

Ensamblador y enlazador

El compilador es solamente una parte, además necesitamos un ensamblador (assembler) y un enlazador (linker). FPC provee un ensamblador interno y/o un enlazador para algunas plataformas, pero otras plataformas necesitas herramientas externas. Habitualmente estas herramientas no son capaces de crear binarios para diferentes plataformas. Es por esto por lo que tenemos que utilizar un enlazador (linker) especial 'ld' y un ensamblador (assembler) 'as' para cada plataforma objetivo (target). Estas on las utilizades binarias (binutils). VerBinutils Assembler y linker

Units para objetivos (target)

Después de crear (o tener/instalar) las utilidades cruzadas necesitamos el FPC RTL y otras unidades compiladas para la plataforma objetivo escogida. Por ejemplo, cada plataforma objetivo necesita una fichero system.ppu diferente (System unit), etc. Estas units pueden ser por tanto compiladas utilizando tu compilador establecido para compilar de acuerdo a la plataforma objetivo, o puedes utilizar potencialmente las unidades compiladas distribuidas oficialmente con la misma versión de FPC (si están disponibles en formato usable bajo la plataforma host en particular).

Configuración

Entonces hay que adaptar el fichero de configuración de FPC, de manera que la compilación cruzada resulte fácil y nos podamos olvidar de todos los aburridos detalles. Lo mismo hay que hacer para el LCL - la Librería de Componentes de Lazarus (en caso de utilizar Lazarus) - Y después de esto ya se puede realizar compilación cruzada para las (distintas)plataformas objetivo. Los binarios resultantes deben a continuación ser copiados a una máquina corriendo la plataforma objetivo, o copiarlas a un sistema virtualizado/emulado (e.g. Wine para binarios Win32 bajo Linux, etc.).

Pasos básicos

Hay unos cuantos pasos comunes relacionados con la compilación cruzada que hay que realizar en todos los casos:

  • Tener un compilador de FreePascal para la plataforma desde la que deseas compilar.
  • Tener el código fuente de FreePascal (excepto para el caso especial de tener todo preparado por alguien previamente).
  • Necesitas además construir a partir del código fuente u obtener las utilidades binarias cruzadas (cross-binutils) que corran en la plataforma actual y están diseñadas para construir programas para la plataforma objetivo deseada.
  • Algunas veces necesitarás algunos ficheros del objetivo para el que estás compilando.

Desde Linux

Desde Linux x64 a Linux i386

Para las ocasiones en que tu distribución de Linux de 64 bits es capaz de compilar programas de 32 bits pero debido al modo en el que el proceso de construcción de FPC fue diseñado existen unas cuantes cosas que tienes que hacer.

  • Primero comprueba si ya tienes los ficheros i386-linux-ld y i386-linux-as:


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


  • Si ya tienes estos ficheros salta a la cabecera "Compilar FPC". En caso contrario ambos se pueden crear utilizando los siguientes script:
#!/bin/bash
 
# Create /usr/bin/i386-linux-ld
cat >/usr/bin/i386-linux-ld << EOF
#!/bin/bash
ld -A elf32-i386 $@
EOF
chmod +x /usr/bin/i386-linux-ld
 
# Create /usr/bin/i386-linux-as
cat >/usr/bin/i386-linux-as << EOF
#!/bin/bash
as --32 $@
EOF
chmod +x /usr/bin/i386-linux-as


  • Compilar FPC:


cd /usr/share/fpcsrc/<version>
sudo make all CPU_TARGET=i386


  • Entonces:


sudo make crossinstall CPU_TARGET=i386


  • Esto es. Edita tu fichero /etc/fpc.cfg file según necesites.

Desde Linux a ARM Linux

Puedes encontrar información sobre como hacer la configuración para un objetivo ARM Linux (e.g. Zaurus) en Setup Cross Compile For ARM.

Desde Linux hacia Windows

La inforamción sobre compilación cruzada con Lazarus se puede encontrar en Cross compiling for Win32 under Linux

Desde Linux a Darwin o Mac OS X

Por favor echa un vistazo a here.

Desde Windows

Desde Windows a Linux

Esto es menos trivial, hay algo de información en el buildfaq

ver también fpcup para descripciones sobre las binutils que funcionan y que librerias/ficheros copiar.

Tal como las Build FAQ (Preguntas Frecuentes) explican, necesitarás librerias (ficheros .so) para el sistema objetivo, e.g. desde /lib y /userTal/lib (pero pueden ser más ubicaciones). En algunos sistemas, algunos ficheros .so son actualmente scripts; verificalos con

grep -i "ld script" *

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.

Desde Windows a GO32v2

Puedes encontrar información detallada en Cross-compilation from Win32 to GO32v2.

Desde Windows a WinCE

arm-wince Describe como configurar un compilador cruzado para ARM CPU
i386-wince Describe como configurar compilación para i386 CPU (sin compilación cruzada)

Note-icon.png

Nota: Los instaladores de Lazarus tienen un instalador que añade Windows a WinCE cross compilation options automatically

Desde Win32 a Win64

Si estás compilando la rama 2.1.1 o superior de FPC puedes hacer:

$ make all OS_TARGET=win64 CPU_TARGET=x86_64

y entonces:

$ make crossinstall OS_TARGET=win64 CPU_TARGET=x86_64

Desde win64 a win32

Instala el fichero lazarus-1.6.0-fpc-3.0.0-cross-i386-win32-win64.exe y a continuación configura las opciones de proyecto a:

  • Target OS : Win32
  • Target CPU : i386

¡ Errando al establecer la CPU (Por defecto) conduce a una plataforma win32-x86_64 incorrecta !

From Darwin (Mac OS X) i386

From Darwin i386 to powerpc

The official FPC installer for Mac OS X/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.

  • Compile FPC:
$ cd fpc
$ make all CPU_TARGET=powerpc -j 2

This creates the powerpc cross-compiler compiler (fpc/compiler/ppcrosspcc) and all units. You can install them using the following commands:

$ sudo make FPC=`pwd`/compiler/ppc386 install CPU_TARGET=powerpc CROSSINSTALL=1
$ INSTALLED_VERSION=`./compiler/ppc386 -iV`
$ sudo mv /usr/local/lib/fpc/$INSTALLED_VERSION/ppcrossppc /usr/local/lib/fpc/$INSTALLED_VERSION/ppcppc

Reminder: Universal binaries are created from the individual (i386 and powerpc) binaries using lipo.


From Darwin i386 to x86_64

The official FPC installer for Mac OS X/i386 includes a 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.

  • Compile FPC:
$ cd fpc
$ make all CPU_TARGET=x86_64

This creates the x86_64 cross-compiler (fpc/compiler/ppcrossx64) and all units. You can install them using the following commands:

$ sudo make crossinstall CPU_TARGET=x86_64
$ sudo mv /usr/local/lib/fpc/2.7.1/ppcrossx64 /usr/local/lib/fpc/2.7.1/ppcx64

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:

$ sudo ln -sf /usr/local/lib/fpc/2.7.1/ppcx64 /usr/local/bin/ppcx64

Assuming all of the LCL components your project uses are supported by the Cocoa widgetset, you can compile a Lazarus project from the command line, using a command like this (full path to the compiler seems required):

$ lazbuild -B project1.lpr --ws=cocoa --cpu=x86_64 --os=darwin --compiler=/usr/local/bin/ppcx64

You can check that your executable is 64-bit uses the "file" command:

$ file ./project1
$ ./project1: Mach-O 64-bit executable x86_64

Alternatively, you can set your project to compile as 64-bit using the Lazarus graphical interface:

a.) Choose the Project/ProjectOptions menu item
b.) In the CompilerOptions/CompilerCommands set the Compiler Command field to "/usr/local/bin/ppcx64"
c.) For CompilerOptions/ConfigAndTarget set the "Target CPU family" to "x86_64"
d.) For CompilerOptions/AdditionsAndOverrides store the "LCLWidgetType := cocoa" in the LPI

Note that a 64-bit OS X computer can run 32-bit executables just fine. However, if you want to create a universal binary that executes on a 32-bit Intel as well as in 64-bit mode on a 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.

$ lipo -create project32 project64 -o projectUniversal

From Darwin to Windows, Linux and others

The package manager fink has packages for crosscompiling to windows, linux, freebsd mainly for Intel Macs, but some for PowerPC Macs, too.

$ fink install fpc-cross-i386-win32

or

$ fink install fpc-cross-arm-linux

install the crosscompilers.

To compile use these commands:

fpc -Twin32 FILENAME
fpc -Parm -Tlinux FILENAME

The current list with fpc 2.6.4 is:

fpc-cross-arm-gba
fpc-cross-arm-linux
fpc-cross-arm-nds
fpc-cross-arm-wince
fpc-cross-arm-armv4t-embedded
fpc-cross-arm-armv7m-embedded
fpc-cross-i386-darwin
fpc-cross-i386-freebsd
fpc-cross-i386-go32v2
fpc-cross-i386-linux
fpc-cross-i386-solaris
fpc-cross-i386-win32
fpc-cross-i386-wince
fpc-cross-powerpc-darwin
fpc-cross-powerpc-linux
fpc-cross-sparc-linux
fpc-cross-x86-64-darwin
fpc-cross-x86-64-freebsd
fpc-cross-x86-64-linux
fpc-cross-x86-64-win64

For other platforms (processors and systems) you have to do the setup by yourself. It is basically always the same scheme: First, you need the corresponding binutils and second, the crosscompiler and the run time library. Some more details of the building procedure can be learned from the fink package description files of the crosscompilers from above.

From FreeBSD

FreeBSD to SPARC

Warning-icon.png

Warning: This section appears to date from around 2005 and may not be relevant anymore. Updates are welcome.

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

in compiler/ execute:

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

~/src/sollib is a directory that contains:

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

Problem is illustrated by the following binary.

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

I suspect wrong .o's are taken.

General Unix/Linux notes

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

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

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

Cross compiling the LCL

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.

If something goes wrong, here are some hints that might help to find out why:

Test cross compiler

Test if you have installed the cross compiled fpc correctly:

Create a hello world program test.pas:

program test;
begin
  writeln('DATE ',{$i %DATE%});
  writeln('FPCTARGET ',{$i %FPCTARGET%});
  writeln('FPCTARGETCPU ',{$i %FPCTARGETCPU%});
  writeln('FPCTARGETOS ',{$i %FPCTARGETOS%});
  writeln('FPCVERSION ',{$i %FPCVERSION%});
end.

And compile it with your source/original platform. Example for x86 Windows:

fpc -Twin32 -Pi386 test.pas

Then test source compiler:

test

Replace win32 and i386 with your targets. Example for target Windows 64 bit:

fpc -Twin64 -Px86_64 test.pas

Then test cross compiler:

test

The program fpc is a wrapper that searches the right compiler (e.g. ppcrossx64) for the target and executes it.

If this does not work, your cross compiler was not installed correctly. When this works you can cross compile the LCL.

Cross compiling the LCL in Lazarus 0.9.30 and below

If you are sure your cross compiler works, you can do the actual cross compile.

Perform the following steps in the Lazarus IDE to do an LCL cross compile: In older IDEs:

  • Set in Tools -> Options -> Environment -> Files the Compiler path to the path to fpc. Normally this is already done.
  • Then open Tools -> Configure Build Lazarus.
  • Set Target OS (e.g. to Win64) and Target CPU (e.g. to x86_64)
  • Click the Build button.

Command line

Apart from the IDE, the command line also allows you to build a cross compiled LCL.

Note-icon.png

Note: Since 0.9.31 you should use lazbuild to cross compile Lazarus packages. See lazbuild -h for a list of options.

An example: you would cross compile a Windows 64 cross compiler using: First thoroughly clean any 64 bit leftovers. This does not touch your 32 bit environment:

make distclean LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64

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).

make packager/registration lazutils lcl LCL_PLATFORM=win32 CPU_TARGET=x86_64 OS_TARGET=win64

As in the previous section, the LCL for your normal OS is untouched.

Cross compiling LCL applications

You first need to cross compile the LCL. See above.

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:

/usr/local/bin/arm-linux-ld: cannot find -lX11

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.

Cross compile FAQ

Why cross compile?

So you can develop a program for one OS/CPU and compile it for another OS/CPU without rebooting or switching computers.

Why not cross compile?

In many cases, you want to test the resulting program on the native platform. Compiling the application on that platform may be easier to set up.

Why cross compile from Unix to Windows and not the other way around?

See Cross compiling for Win32 under Linux

Necesito más información sobre como construir FreePascal. ¿Donde la encuentro?

Hay un fichero en formato PDF sobre las FAQ generales sobre como construir y configurar FPC: buildfaq

Errors like compiler "/usr/bin/fpc" does not support target arm-linux

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).

Ver además