Un compilador cruzado es un compilador capaz de crear código ejecutable para una plataforma distinta a aquella en la que se ejecuta el compilador. Por ejemplo, un compilador que se ejecuta en una PC pero genera código que se ejecuta en dispositivos Android es un compilador cruzado.
Un compilador cruzado resulta útil para compilar código para múltiples plataformas desde un host de desarrollo. La compilación directa en la plataforma de destino puede resultar inviable, por ejemplo, en sistemas integrados con recursos informáticos limitados.
Los compiladores cruzados son distintos de los compiladores de código fuente a código fuente . Un compilador cruzado sirve para generar código máquina en software multiplataforma , mientras que un compilador de código fuente a código fuente traduce de un lenguaje de codificación a otro en código de texto. Ambos son herramientas de programación .
El uso fundamental de un compilador cruzado es separar el entorno de compilación del entorno de destino. Esto resulta útil en varias situaciones:
El uso de máquinas virtuales (como la JVM de Java ) resuelve algunas de las razones por las que se desarrollaron los compiladores cruzados. El paradigma de la máquina virtual permite utilizar la misma salida del compilador en varios sistemas de destino, aunque esto no siempre es ideal porque las máquinas virtuales suelen ser más lentas y el programa compilado solo se puede ejecutar en equipos con esa máquina virtual.
Normalmente, la arquitectura del hardware difiere (por ejemplo, al codificar un programa destinado a la arquitectura MIPS en una computadora x86 ), pero la compilación cruzada también se puede utilizar cuando solo difiere el entorno del sistema operativo , 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 .
La técnica Canadian Cross es una técnica para crear compiladores cruzados para otras máquinas, donde la máquina original es mucho más lenta o menos conveniente que la de destino. Dadas tres máquinas A, B y C, se utiliza la máquina A (por ejemplo, ejecutando Windows XP en un procesador IA-32 ) para crear un compilador cruzado que se ejecute en la máquina B (por ejemplo, ejecutando macOS en un procesador x86-64 ) para crear ejecutables para la máquina C (por ejemplo, ejecutando Android en un procesador ARM ). La ventaja práctica en este ejemplo es que la máquina A es lenta pero tiene un compilador propietario, mientras que la máquina B es rápida pero no tiene compilador en absoluto, y la máquina C es imprácticamente lenta para ser utilizada para la compilación.
Al utilizar la Cruz Canadiense con GCC, y como en este ejemplo, puede haber cuatro compiladores involucrados
El compilador cruzado de resultado final (4) no podrá ejecutarse en la máquina de compilación A; en su lugar, se ejecutará en la máquina B para compilar una aplicación en código ejecutable que luego se copiará en la máquina C y se ejecutará en la máquina C.
Por ejemplo, NetBSD proporciona un script de shell Unix POSIX llamado que primero construirá su propia cadena de herramientas con el compilador del host; este, a su vez, se utilizará para construir el compilador cruzado que se usará para construir todo el sistema.build.sh
El término Cruz Canadiense surgió porque en el momento en que se discutieron estos temas, Canadá tenía tres partidos políticos nacionales. [1]
GCC , una colección de compiladores de software libre , se puede configurar para realizar compilaciones cruzadas. Es compatible con muchas plataformas e idiomas.
GCC requiere que haya una copia compilada de binutils disponible para cada plataforma de destino. Especialmente importante es el ensamblador GNU . Por lo tanto, binutils primero debe compilarse correctamente con la opción --target=some-target
enviada al script configure . GCC también debe configurarse con la misma --target
opción. GCC puede ejecutarse normalmente siempre que las herramientas que crea binutils estén disponibles en la ruta , lo que se puede hacer utilizando lo siguiente (en sistemas operativos tipo UNIX con bash):
PATH=/ruta/a/binutils/bin:${PATH} make
La compilación cruzada de GCC requiere que una parte de la biblioteca estándar de C de la plataforma de destino esté disponible en la plataforma anfitriona . El programador puede optar por compilar la biblioteca de C completa, pero esta opción puede resultar poco fiable. La alternativa es utilizar newlib , que es una pequeña biblioteca de C que contiene solo los componentes más esenciales necesarios para compilar el código fuente de C.
Los paquetes GNU Autotools (es decir , autoconf , automake y libtool ) utilizan la noción de una plataforma de compilación , una plataforma de host y una plataforma de destino . La plataforma de compilación es donde se compila realmente el compilador. En la mayoría de los casos, build debe dejarse sin definir (se utilizará de forma predeterminada host). La plataforma de host siempre es donde se ejecutarán los artefactos de salida del compilador, ya sea que la salida sea otro compilador o no. La plataforma de destino se utiliza cuando se compilan compiladores cruzados; representa qué tipo de código objeto producirá el paquete; de lo contrario, la configuración de la plataforma de destino es irrelevante. [2] Por ejemplo, considere la compilación cruzada de un videojuego que se ejecutará en un Dreamcast . La máquina donde se compila el juego es la plataforma de compilación, mientras que Dreamcast es la plataforma de host . Los nombres host y target son relativos al compilador que se usa y se cambian como son y grandson . [3]
Otro método que utilizan popularmente los desarrolladores de Linux integrado implica la combinación de compiladores GCC con entornos sandbox especializados como Scratchbox y Scratchbox 2 , o PRoot. Estas herramientas crean un entorno sandbox " en chroot " donde el programador puede crear las herramientas, libc y bibliotecas necesarias sin tener que establecer rutas adicionales. También se proporcionan funciones para "engañar" al entorno de ejecución para que "crea" que realmente se está ejecutando en la CPU de destino prevista (como una arquitectura ARM); esto permite que los scripts de configuración y similares se ejecuten sin errores. Scratchbox se ejecuta más lentamente en comparación con los métodos "no en chroot", y la mayoría de las herramientas que están en el host deben trasladarse a Scratchbox para funcionar.
Manx Software Systems , de Shrewsbury , Nueva Jersey , produjo compiladores de C a partir de la década de 1980 dirigidos a desarrolladores profesionales para una variedad de plataformas, incluidas las compatibles con IBM PC y Mac .
El lenguaje de programación Aztec C de Manx estaba disponible para una variedad de plataformas, incluidas MS-DOS , Apple II , DOS 3.3 y ProDOS , Commodore 64 , Mac 68k [4] y Amiga .
Desde la década de 1980 y durante toda la década de 1990 hasta la desaparición de Manx Software Systems, la versión MS-DOS de Aztec C [5] se ofreció tanto como compilador en modo nativo como compilador cruzado para otras plataformas con procesadores diferentes, incluidos Commodore 64 [6] y Apple II. [7] Todavía existen distribuciones de Internet para Aztec C, incluidos sus compiladores cruzados basados en MS-DOS, que todavía se utilizan en la actualidad.
El compilador nativo de MS-DOS Aztec C86 de Manx, el compilador 8086 , también era un compilador cruzado. Aunque no compilaba código para un procesador diferente como sus compiladores cruzados Aztec C65 6502 para Commodore 64 y Apple II, creaba ejecutables binarios para los sistemas operativos antiguos de la familia de procesadores 8086 de 16 bits.
Cuando se presentó por primera vez el IBM PC, estaba disponible con una selección de sistemas operativos, entre ellos CP/M-86 y PC DOS . Aztec C86 se proporcionó con bibliotecas de enlace para generar código para ambos sistemas operativos IBM PC . A lo largo de la década de 1980, las versiones posteriores de Aztec C86 (3.xx, 4.xx y 5.xx) agregaron soporte para las versiones "transitorias" 1 y 2 de MS-DOS [8] y que eran menos robustas que la versión "básica" de MS-DOS 3 y posteriores a las que Aztec C86 apuntó hasta su desaparición.
Finalmente, Aztec C86 proporcionó a los desarrolladores de lenguaje C la capacidad de producir código "HEX" compatible con ROM que luego podía transferirse mediante un quemador de ROM directamente a un procesador basado en 8086. La paravirtualización puede ser más común hoy en día, pero la práctica de crear código ROM de bajo nivel era más común per cápita durante aquellos años en los que el desarrollo de controladores de dispositivos a menudo lo hacían los programadores de aplicaciones para aplicaciones individuales y los nuevos dispositivos representaban una industria casera . No era raro que los programadores de aplicaciones interactuaran directamente con el hardware sin el soporte del fabricante. Esta práctica era similar al desarrollo de sistemas integrados en la actualidad.
Thomas Fenwick y James Goodnow II fueron los dos principales desarrolladores de Aztec-C. Fenwick se hizo famoso más tarde como el autor del núcleo de Microsoft Windows CE o NK ("Nuevo núcleo") como se lo denominaba entonces. [9]
Microsoft C (MSC) tiene una historia más corta que otros [10] que se remonta a la década de 1980. Los primeros compiladores de Microsoft C fueron creados por la misma empresa que creó Lattice C y fueron rebautizados por Microsoft como propios, hasta que se lanzó MSC 4, que fue la primera versión que Microsoft produjo por sí mismo. [11]
En 1987, muchos desarrolladores comenzaron a migrar a Microsoft C, y muchos más seguirían su ejemplo durante el desarrollo de Microsoft Windows hasta su estado actual. Surgieron productos como Clipper y, posteriormente, Clarion , que ofrecían un desarrollo sencillo de aplicaciones de bases de datos mediante técnicas de lenguaje cruzado, lo que permitía compilar parte de sus programas con Microsoft C.
Borland C (empresa de California) estuvo disponible para su compra años antes de que Microsoft lanzara su primer producto C.
Mucho antes de Borland, BSD Unix (Universidad de Berkeley) había obtenido C de los autores del lenguaje C: Kernighan y Ritchie, quienes lo escribieron al unísono mientras trabajaban para AT&T (laboratorios). Las necesidades originales de K&R no eran solo una sintaxis elegante analizada de segundo nivel para reemplazar la sintaxis analizada de primer nivel de asm: estaba diseñado para que se escribiera una cantidad mínima de asm para soportar cada plataforma (el diseño original de C era la capacidad de compilar de forma cruzada usando C con el menor código de soporte por plataforma, que era lo que necesitaban). También el C de ayer se relacionaba directamente con el código ASM siempre que no dependiera de la plataforma. El C de hoy (más aún C++) ya no es compatible con C y el código asm subyacente puede ser extremadamente diferente al escrito en una plataforma dada (en Linux: a veces reemplaza y desvía las llamadas a la biblioteca con opciones de distribuidor). El C de hoy es un lenguaje de tercer o cuarto nivel que se usa a la antigua usanza como un lenguaje de segundo nivel.
Los programas en C se han vinculado desde hace mucho tiempo con módulos escritos en lenguaje ensamblador . La mayoría de los compiladores de C (incluso los actuales) ofrecen un pase de lenguaje ensamblador (que se puede modificar para lograr mayor eficiencia y luego vincularlo al resto del programa después del ensamblaje).
Los compiladores como Aztec-C convertían todo a lenguaje ensamblador en una pasada distinta y luego ensamblaban el código en una pasada distinta, y se destacaron por su código pequeño y muy eficiente, pero en 1987 el optimizador incorporado en Microsoft C era muy bueno, y solo las partes "críticas para la misión" de un programa se consideraban para reescribir. De hecho, la programación en lenguaje C se había convertido en el lenguaje de "nivel más bajo", y la programación se convirtió en una industria en crecimiento multidisciplinaria y los proyectos se hicieron más grandes, con programadores escribiendo interfaces de usuario e interfaces de bases de datos en lenguajes de nivel superior, y había surgido una necesidad de desarrollo entre lenguajes que continúa hasta el día de hoy.
En 1987, con el lanzamiento de MSC 5.1, Microsoft ofreció un entorno de desarrollo de lenguaje cruzado para MS-DOS. El código objeto binario de 16 bits escrito en lenguaje ensamblador ( MASM ) y otros lenguajes de Microsoft, incluidos QuickBASIC , Pascal y Fortran , se podían vincular entre sí en un solo programa, en un proceso que llamaron "Programación de lenguaje mixto" y ahora "Llamada entre lenguajes". [12] Si se usaba BASIC en esta mezcla, el programa principal necesitaba estar en BASIC para soportar el sistema de tiempo de ejecución interno que compilaba BASIC requerido para la recolección de basura y sus otras operaciones administradas que simulaban un intérprete de BASIC como QBasic en MS-DOS.
La convención de llamada para el código C, en particular, era pasar parámetros en "orden inverso" en la pila y devolver valores en la pila en lugar de en un registro del procesador . Había otras reglas de programación para hacer que todos los lenguajes trabajaran juntos, pero esta regla en particular persistió a través del desarrollo de lenguajes cruzados que continuó a lo largo de las versiones de 16 y 32 bits de Windows y en el desarrollo de programas para OS/2 , y que persiste hasta el día de hoy. Se conoce como la convención de llamada de Pascal .
Otro tipo de compilación cruzada para la que se utilizó Microsoft C durante esta época fue en aplicaciones minoristas que requieren dispositivos portátiles como el Symbol Technologies PDT3100 (utilizado para realizar inventarios ), que proporcionaba una biblioteca de enlaces dirigida a un lector de códigos de barras basado en 8088. La aplicación se creaba en la computadora host y luego se transfería al dispositivo portátil (a través de un cable serial ) donde se ejecutaba, de manera similar a lo que se hace hoy para ese mismo mercado utilizando Windows Mobile por parte de empresas como Motorola , que compró Symbol.
A lo largo de la década de 1990 y a partir de MSC 6 (su primer compilador compatible con ANSI C ), Microsoft reorientó sus compiladores de C hacia el mercado emergente de Windows, y también hacia OS/2 y hacia el desarrollo de programas GUI . La compatibilidad con lenguajes mixtos se mantuvo hasta MSC 6 en el lado MS-DOS, pero la API para Microsoft Windows 3.0 y 3.1 se escribió en MSC 6. MSC 6 también se amplió para proporcionar compatibilidad con ensamblajes de 32 bits y compatibilidad con los emergentes Windows para Trabajo en Grupo y Windows NT , que formarían la base para Windows XP . Se introdujo una práctica de programación llamada thunk para permitir el paso entre programas de 16 y 32 bits que aprovechaban el enlace en tiempo de ejecución ( enlace dinámico ) en lugar del enlace estático que se favorecía en las aplicaciones monolíticas de 16 bits de MS-DOS. El enlace estático todavía es el preferido por algunos desarrolladores de código nativo, pero generalmente no proporciona el grado de reutilización de código requerido por las mejores prácticas más nuevas, como el Modelo de Madurez de Capacidad (CMM).
El soporte para MS-DOS todavía se proporcionaba con el lanzamiento del primer compilador C++ de Microsoft, MSC 7, que era compatible con versiones anteriores del lenguaje de programación C y MS-DOS y admitía la generación de código de 16 y 32 bits.
MSC tomó el relevo de Aztec C86 . La cuota de mercado de los compiladores de C se había volcado hacia los compiladores cruzados que aprovechaban las últimas y mejores características de Windows, ofrecían C y C++ en un único paquete y seguían dando soporte a sistemas MS-DOS que ya tenían una década de antigüedad, y las empresas más pequeñas que producían compiladores como Aztec C ya no podían competir y se dirigieron a nichos de mercado como los sistemas integrados o desaparecieron.
El soporte para MS-DOS y la generación de código de 16 bits continuó hasta MSC 8.00c, que se incluyó con Microsoft C++ y Microsoft Application Studio 1.5, el precursor de Microsoft Visual Studio, que es el entorno de desarrollo cruzado que Microsoft proporciona hoy.
MSC 12 se lanzó con Microsoft Visual Studio 6 y ya no brindaba soporte para binarios MS-DOS de 16 bits, sino que brindaba soporte para aplicaciones de consola de 32 bits, pero brindaba soporte para la generación de código de Windows 95 y Windows 98 , así como para Windows NT . Las bibliotecas de enlaces estaban disponibles para otros procesadores que ejecutaban Microsoft Windows; una práctica que Microsoft continúa hasta el día de hoy.
MSC 13 se lanzó con Visual Studio 2003, y MSC 14 se lanzó con Visual Studio 2005 , los cuales aún producen código para sistemas más antiguos como Windows 95, pero que producirán código para varias plataformas de destino, incluido el mercado móvil y la arquitectura ARM .
En 2001, Microsoft desarrolló Common Language Runtime (CLR), que constituyó el núcleo de su compilador .NET Framework en el IDE de Visual Studio. Esta capa del sistema operativo, que se encuentra en la API, permite la combinación de lenguajes de desarrollo compilados en distintas plataformas que ejecutan el sistema operativo Windows.
El entorno de ejecución de .NET Framework y CLR proporcionan una capa de mapeo a las rutinas principales del procesador y los dispositivos en el equipo de destino. El compilador de C de línea de comandos en Visual Studio compilará código nativo para una variedad de procesadores y se puede utilizar para crear las rutinas principales.
Las aplicaciones Microsoft .NET para plataformas de destino como Windows Mobile en la arquitectura ARM se compilan de forma cruzada en máquinas Windows con una variedad de procesadores y Microsoft también ofrece emuladores y entornos de implementación remota que requieren muy poca configuración, a diferencia de los compiladores cruzados de antaño o en otras plataformas.
Las bibliotecas de tiempo de ejecución, como Mono , brindan compatibilidad para programas .NET compilados en forma cruzada con otros sistemas operativos, como Linux .
Las bibliotecas como Qt y sus predecesoras, incluido XVT, ofrecen la posibilidad de desarrollar código fuente en varias plataformas, al tiempo que siguen utilizando Microsoft C para crear las versiones de Windows. Otros compiladores como MinGW también se han vuelto populares en esta área, ya que son más directamente compatibles con los sistemas Unix que comprenden el lado no Windows del desarrollo de software, lo que permite a los desarrolladores apuntar a todas las plataformas utilizando un entorno de compilación familiar.
Free Pascal fue desarrollado desde el principio como un compilador cruzado. El ejecutable del compilador (ppcXXX donde XXX es una arquitectura de destino) es capaz de producir ejecutables (o simplemente archivos de objeto si no existe un enlazador interno, o incluso simplemente archivos de ensamblaje si no existe un ensamblador interno) para todos los sistemas operativos de la misma arquitectura. Por ejemplo, ppc386 es capaz de producir ejecutables para i386-linux, i386-win32, i386-go32v2 (DOS) y todos los demás sistemas operativos (consulte [13] ). Sin embargo, para compilar para otra arquitectura, primero se debe crear una versión de arquitectura cruzada del compilador. El ejecutable del compilador resultante tendría 'ross' adicional antes de la arquitectura de destino en su nombre. es decir, si el compilador está creado para apuntar a x64, entonces el ejecutable sería ppcrossx64.
Para compilar para una arquitectura de sistema operativo seleccionada, se pueden usar los parámetros de compilación (para el controlador del compilador fpc) -P y -T. Esto también se hace cuando se compila de forma cruzada el compilador en sí, pero se configura mediante las opciones de creación CPU_TARGET y OS_TARGET. Se requiere el ensamblador y enlazador GNU para la plataforma de destino si Free Pascal aún no tiene una versión interna de las herramientas para la plataforma de destino.
Clang es de forma nativa un compilador cruzado. En el momento de la compilación puedes seleccionar a qué arquitecturas quieres que Clang pueda apuntar.
El sistema heterogéneo Plan 9 y su cadena de herramientas no distinguen entre compilación cruzada y nativa. Los archivos Makefile son independientes de la arquitectura.
Se denomina "Cruce canadiense" porque en el momento en que se necesitaba un nombre, Canadá tenía tres partidos nacionales.
i386