CapÃtulo 3 : Compilador cruzado
Um compilador que é capaz de produzir código que é executável em uma plataforma que é diferente daquela na qual o compilador está operando agora é referido como um compilador cruzado. Um exemplo de um compilador cruzado é um compilador que é projetado para ser executado em um computador pessoal, mas também gera código que pode ser executado em dispositivos Android.
Para compilar código para diferentes plataformas a partir de um único host de desenvolvimento, um compilador cruzado é uma ferramenta extremamente útil. A compilação direta na plataforma de destino pode não ser possível, por exemplo, em dispositivos incorporados que têm uma quantidade restrita de recursos da CPU.
As comparações entre compiladores source-to-source e compiladores cruzados não são as mesmas. A diferença entre um compilador source-to-source e um compilador cruzado é que o primeiro é usado para gerar código de máquina para aplicativos multiplataforma, enquanto o segundo é usado para traduzir código de texto de uma linguagem de programação para outra. Ambos são ferramentas de programação.
Uma das aplicações mais fundamentais de um compilador cruzado é permitir a separação do ambiente de destino e do ambiente de construção. Isso é útil em várias situações diferentes:
Uma das razões pelas quais os compiladores cruzados foram desenvolvidos foi para superar alguns dos problemas causados pelo uso de máquinas virtuais, como a JVM do Java. O paradigma da máquina virtual torna possível usar a mesma saída do compilador em muitos sistemas de destino. No entanto, essa nem sempre é a melhor opção porque as máquinas virtuais geralmente são mais lentas do que outros tipos de computadores e o programa compilado só pode ser executado em computadores que tenham essa máquina virtual.
No entanto, a compilação cruzada também pode ser utilizada quando apenas o ambiente do sistema operacional é diferente, como ao compilar um programa FreeBSD no Linux, ou mesmo apenas a biblioteca do sistema, como ao compilar programas com uClibc em um host glibc. Na maioria dos casos, a arquitetura de hardware é diferente (por exemplo, ao codificar um programa destinado à arquitetura MIPS em um computador x86).
Um método para construir compiladores cruzados para diferentes máquinas é conhecido como Canadian Cross. Este método é utilizado em situações em que a máquina de origem é significativamente mais lenta ou menos conveniente do que o computador de destino. Um compilador cruzado é construído usando a máquina A (por exemplo, executando o Windows XP em um processador IA-32) para desenvolver um compilador cruzado que é executado na máquina B (por exemplo, executando macOS em um processador x86-64) para criar executáveis para a máquina C (por exemplo, executando o Android em um processador ARM). Um compilador cruzado é usado para criar executáveis para a máquina C. A máquina A é lenta, mas tem um compilador proprietário, a máquina B é rápida, mas não tem compilador, e a máquina C é impraticável para utilizar para compilação. A vantagem prática neste exemplo é que a Máquina A tem um compilador específico que não está disponível para outras máquinas.
Quando o Canadian Cross é usado em conjunto com o GCC, como visto neste exemplo, pode haver um total de quatro compiladores disponíveis.
Embora o compilador cruzado de resultado final (4) não possa ser executado na máquina de compilação A, ele poderá ser executado na máquina B para compilar um aplicativo em código executável. Este código seria então copiado para a máquina C e executado na máquina C.
Por exemplo, o NetBSD tem um shell script POSIX Unix chamado build.sh. Este script inicialmente construirá sua própria cadeia de ferramentas utilizando o compilador do host. Esta cadeia de ferramentas será então utilizada para construir o compilador cruzado, que será utilizado para construir todo o sistema.
Como havia três partidos políticos nacionais no Canadá na época em que essas preocupações estavam sendo discutidas, o termo "Cruz Canadense" passou a existir.
O GCC, que é uma coleção de compiladores de software livre, pode ser configurado para executar a compilação cruzada. Muitas linguagens e plataformas diferentes são suportadas por ele.
Uma versão compilada do binutils deve estar acessível para cada plataforma que está sendo direcionada, pois este é um requisito do GCC. Em particular, o GNU Assembler é de grande importância. Portanto, a primeira etapa é garantir que binutils seja compilado com êxito enviando o switch --target=some-target para o script configure. Além disso, a opção --target precisa ser especificada sempre que o GCC estiver sendo usado. Depois disso, o GCC pode ser executado normalmente, assumindo que as ferramentas que o binutils gera estão presentes no caminho. Isso pode ser feito usando o seguinte (em sistemas operacionais semelhantes ao UNIX e usam bash):
Ao usar o GCC para compilação cruzada, é necessário que a plataforma host tenha acesso a um subconjunto da biblioteca padrão C usada pela plataforma de destino. Existe a possibilidade de o programador decidir compilar toda a biblioteca C; no entanto, esta decisão pode não ser fiável. A alternativa é fazer uso de newlib, que é uma biblioteca C compacta que inclui apenas os componentes que são absolutamente necessários para a compilação do código-fonte C.
É possível empregar os conceitos de uma plataforma de construção, uma plataforma host e uma plataforma de destino enquanto trabalha com os pacotes GNU Autotools, que incluem autoconf, automake e libtool. Durante o processo de compilação, o compilador é realmente compilado na plataforma de compilação. Recomenda-se que a compilação seja deixada indefinida na maioria das situações (será padrão do host). É sempre a plataforma host que será responsável por executar os artefatos de saída do compilador, independentemente de a saída também ser produzida por outro compilador ou não. Ao compilar compiladores cruzados, a plataforma de destino é utilizada; é uma representação do tipo de código objeto que o pacote irá gerar; em outros casos, a opção de plataforma de destino é inútil. Considere, por exemplo, a possibilidade de compilar um videogame de forma que ele possa ser jogado em um Dreamcast. Enquanto o Dreamcast serve como plataforma de hospedagem, a plataforma de construção refere-se ao sistema que é responsável pela compilação do jogo. De acordo com o compilador que está sendo usado, os nomes host e target estão relacionados entre si e podem ser alterados como filho e neto.
A combinação de compiladores GCC com sandboxes específicos, como Scratchbox e Scratchbox 2, ou PRoot, é outra maneira que é frequentemente utilizada por desenvolvedores que trabalham com Linux incorporado. O uso dessas ferramentas resulta na criação de um sandbox "chrooted", que permite ao programador construir ferramentas críticas, libc e bibliotecas sem a necessidade de definir caminhos adicionais. Além disso, recursos são fornecidos para "enganar" o tempo de execução para que ele "acredite" que está realmente operando na CPU de destino pretendida (por exemplo, uma arquitetura ARM). Isso permite que scripts de configuração e outros scripts semelhantes sejam executados sem erros. Quando comparado a abordagens "não-chrooted", o Scratchbox é executado mais lentamente e, para que a maioria das ferramentas que agora estão instaladas no host funcionem, elas precisam ser realocadas dentro do Scratchbox.
A partir da década de 1980, a Manx Software Systems, com sede em Shrewsbury, Nova Jersey, começou a produzir compiladores C com a intenção de atender desenvolvedores profissionais para uma ampla gama de plataformas, incluindo IBM PC compatíveis e Macs.
A linguagem de programação Aztec C foi disponibilizada para uso em vários sistemas diferentes, como MS-DOS, Apple II, DOS 3.3 e ProDOS, Commodore 64, Mac 68k e Amiga.
A versão MS-DOS do Aztec C estava disponível para uso como um compilador de modo nativo e como um compilador cruzado para outras plataformas com diferentes processadores, como o Commodore 64 e o Apple II, começando na década de 1980 e continuando até a década de 1990 até a Manx Software Systems sair do mercado. Distribuições de Internet para Aztec C, incluindo seus compiladores cruzados baseados em MS-DOS, ainda estão disponíveis hoje. O uso deles continua até hoje.
Além de ser um compilador MS-DOS 8086 de modo nativo, o Aztec C86 do Manx utilizava recursos de compilação cruzada. Mesmo que não gerasse código para uma CPU diferente, como seus compiladores cruzados Aztec C65 6502 para o Commodore 64 e Apple II, ele construiu executáveis binários para sistemas operacionais que eram considerados legados na época. Esses executáveis foram projetados para a família de processadores 8086 de 16 bits.
Quando o IBM Personal Computer foi lançado pela primeira vez, ele foi oferecido com uma seleção de sistemas operacionais, incluindo CP/M-86 e PC DOS, que eram duas das opções disponíveis. Bibliotecas de links foram disponibilizadas para o Aztec C86 para que ele pudesse gerar código para ambos os sistemas operacionais de computador usados pelos IBM PCs. À medida que a década de 1980 progrediu, outras versões do Aztec C86 (3.xx, 4.xx e 5.xx) ganharam suporte para MS-DOS versões "transitórias" 1 e 2. Estas versões eram menos robustas do que a "linha de base" MS-DOS versão 3 e posterior, que Aztec C86 visou até o seu fim. Durante este tempo, Aztec C86 foi capaz de lidar com essas versões.
Por último, mas não menos...