CapÃtulo 3 : Compilador cruzado
Un compilador que es capaz de producir código que se puede ejecutar en una plataforma diferente de aquella en la que el compilador está operando ahora se conoce como compilador cruzado. Un ejemplo de compilador cruzado es un compilador que está diseñado para ejecutarse en una computadora personal, pero también genera código que se puede ejecutar en dispositivos Android.
Con el fin de compilar código para diferentes plataformas desde un solo host de desarrollo, un compilador cruzado es una herramienta extremadamente útil. Es posible que la compilación directa en la plataforma de destino no sea posible, por ejemplo, en dispositivos integrados que tienen una cantidad restringida de recursos de CPU.
Las comparaciones entre compiladores de código fuente y compiladores cruzados no son lo mismo. La diferencia entre un compilador de código fuente a código fuente y un compilador cruzado es que el primero se usa para generar código máquina para aplicaciones multiplataforma, mientras que el segundo se usa para traducir código de texto de un lenguaje de programación a otro. Las dos son herramientas para programar.
Una de las aplicaciones más fundamentales de un compilador cruzado es permitir la separación del entorno de destino y el entorno de compilación. Esto es útil en una serie de situaciones diferentes:
Una de las razones por las que se desarrollaron los compiladores cruzados fue para superar algunos de los problemas causados por el uso de máquinas virtuales, como la JVM de Java. El paradigma de máquina virtual permite usar la misma salida del compilador en muchos sistemas de destino. Sin embargo, esta no siempre es la mejor opción porque las máquinas virtuales suelen ser más lentas que otros tipos de computadoras y el programa compilado solo se puede ejecutar en computadoras que tengan esa máquina virtual.
Sin embargo, la compilación cruzada también se puede utilizar cuando solo el entorno del sistema operativo es diferente, como cuando se compila un programa FreeBSD en Linux, o incluso solo la biblioteca del sistema, como cuando se compilan programas con uClibc en un host glibc. En la mayoría de los casos, la arquitectura de hardware es diferente (por ejemplo, cuando se codifica un programa destinado a la arquitectura MIPS en un equipo x86).
Un método para construir compiladores cruzados para diferentes máquinas se conoce como cruz canadiense. Este método se utiliza en situaciones en las que la máquina de origen es significativamente más lenta o menos conveniente que la computadora de destino. Un compilador cruzado se construye mediante el equipo A (por ejemplo, que ejecuta Windows XP en un procesador IA-32) para desarrollar un compilador cruzado que se ejecuta en el equipo B (por ejemplo, que ejecuta macOS en un procesador x86-64) para crear ejecutables para el equipo C (por ejemplo, que ejecuta Android en un procesador ARM). Se utiliza un compilador cruzado para crear ejecutables para la máquina C. La máquina A es lenta pero tiene un compilador propietario, la máquina B es rápida pero no tiene ningún compilador, y la máquina C es poco práctica para utilizar para la compilación. La ventaja práctica en este ejemplo es que la máquina A tiene un compilador específico que no está disponible para otras máquinas.
Cuando se utiliza Canadian Cross junto con GCC, como se ve en este ejemplo, puede haber un total de cuatro compiladores disponibles.
Aunque el compilador cruzado de resultados finales (4) no podrá ejecutarse en el equipo de compilación A, podrá ejecutarse en el equipo B para compilar una aplicación en código ejecutable. A continuación, este código se copiaría en la máquina C y se ejecutaría en la máquina C.
Por ejemplo, NetBSD tiene un script de shell POSIX Unix que se llama build.sh. Este script construirá inicialmente su propia cadena de herramientas utilizando el compilador del host. Esta cadena de herramientas se utilizará para construir el compilador cruzado, que se utilizará para construir todo el sistema.
Debido a que había tres partidos políticos nacionales en Canadá en el momento en que se discutían estas preocupaciones, surgió el término "Cruz Canadiense".
El GCC, que es una colección de compiladores de software libre, se puede configurar para realizar compilaciones cruzadas. Es compatible con muchos idiomas y plataformas diferentes.
Se debe acceder a una versión compilada de binutils para cada plataforma a la que se dirige, ya que este es un requisito de GCC. En particular, el ensamblador GNU es de gran importancia. Por lo tanto, el primer paso es asegurarse de que binutils se compile correctamente enviando el switch --target=some-target al script de configuración. Además, la opción --target debe especificarse siempre que se utilice GCC. Después de eso, GCC se puede ejecutar normalmente, asumiendo que las herramientas que genera binutils están presentes en la ruta. Esto se puede lograr mediante el uso de lo siguiente (en sistemas operativos que son similares a UNIX y usan bash):
Cuando se utiliza GCC para la compilación cruzada, es necesario que la plataforma host tenga acceso a un subconjunto de la biblioteca estándar de C que utiliza la plataforma de destino. Existe la posibilidad de que el programador decida compilar toda la biblioteca C; Sin embargo, esta decisión podría no ser confiable. La alternativa es hacer uso de newlib, que es una biblioteca C compacta que solo incluye los componentes que son absolutamente necesarios para la compilación del código fuente de C.
Es posible emplear los conceptos de una plataforma de compilación, una plataforma anfitriona y una plataforma de destino mientras se trabaja con los paquetes de GNU Autotools, que incluyen autoconf, automake y libtool. Durante el proceso de compilación, el compilador se compila realmente en la plataforma de compilación. Se recomienda que la compilación se deje sin definir en la mayoría de las situaciones (se establecerá de forma predeterminada desde el host). Siempre es la plataforma host la responsable de ejecutar los artefactos de salida del compilador, independientemente de si la salida también es producida por otro compilador o no. Al compilar compiladores cruzados, se utiliza la plataforma de destino; Es una representación del tipo de código objeto que generará el paquete; En otros casos, la opción de plataforma de destino es inútil. Considere, por ejemplo, la posibilidad de compilar un videojuego de manera que se pueda jugar en una Dreamcast. Mientras que la Dreamcast sirve como plataforma anfitriona, la plataforma de construcción se refiere al sistema que es responsable de la compilación del juego. Según el compilador que se está utilizando, los nombres host y target están relacionados entre sí y se pueden cambiar como hijo y nieto.
La combinación de compiladores GCC con sandboxes específicos como Scratchbox y Scratchbox 2, o PRoot, es otra forma que utilizan con frecuencia los desarrolladores que trabajan con Linux embebido. El uso de estas herramientas da como resultado la creación de un sandbox "chrooted", que permite al programador construir herramientas críticas, libc y bibliotecas sin la necesidad de definir rutas adicionales. Además, se proporcionan facilidades para "engañar" al tiempo de ejecución para que "crea" que realmente está operando en la CPU de destino prevista (por ejemplo, una arquitectura ARM). Esto permite que los scripts de configuración y otros scripts similares se ejecuten sin errores. En comparación con los enfoques "no chrooteados", Scratchbox se ejecuta más lentamente, y para que la mayoría de las herramientas que ahora están instaladas en el host funcionen, deben reubicarse dentro de Scratchbox.
A partir de la década de 1980, Manx Software Systems, con sede en Shrewsbury, Nueva Jersey, comenzó a producir compiladores de C con la intención de atender a desarrolladores profesionales para una amplia gama de plataformas, incluidas las compatibles con IBM PC y Mac.
El lenguaje de programación Aztec C se puso a disposición para su uso en varios sistemas diferentes, como MS-DOS, Apple II, DOS 3.3 y ProDOS, Commodore 64, Mac 68k y Amiga.
La versión MS-DOS de Aztec C estaba disponible para su uso como compilador de modo nativo y como compilador cruzado para otras plataformas con diferentes procesadores, como el Commodore 64 y el Apple II, comenzando en la década de 1980 y continuando durante la década de 1990 hasta que Manx Software Systems dejó de funcionar. Las distribuciones de Internet para Aztec C, incluidos sus compiladores cruzados basados en MS-DOS, todavía están disponibles hoy en día. El uso de ellos continúa hasta el día de hoy.
Además de ser un compilador de MS-DOS 8086 en modo nativo, el Aztec C86 de Manx utilizaba capacidades de compilación cruzada. Aunque no generó código para una CPU diferente, como sus compiladores cruzados Aztec C65 6502 para el Commodore 64 y el Apple II, sí construyó ejecutables binarios para sistemas operativos que se consideraban heredados en ese momento. Estos ejecutables fueron diseñados para la familia de procesadores 8086 de 16 bits.
Cuando se debutó por primera vez el IBM Personal Computer, se ofrecía con una selección de sistemas operativos, incluyendo CP/M-86 y PC DOS, que eran dos de las opciones disponibles. Las bibliotecas de enlaces se pusieron a disposición de Aztec C86 para que pudiera generar código para ambos sistemas operativos de computadora utilizados por las PC de IBM. A medida que avanzaba la década de 1980, otras versiones de Aztec C86 (3.xx, 4.xx y 5.xx) obtuvieron soporte para las versiones "transitorias" 1 y 2 de MS-DOS. Estas versiones eran...