Quero contar como criei um compilador cruzado para o Raspberry Pi4 usando crosstool-ng. Talvez alguém ache o assunto muito primitivo e enfadonho. A princípio eu mesmo pensei que poderia montar rapidamente um cross-compilador, mas tive que mexer e estudar o problema, algumas das nuances foram inesperadas para mim. Então vou te dizer o que e como eu fiz.
Talvez a primeira pergunta que você precise fazer a si mesmo seja: "Para que serve um compilador cruzado?" Na verdade, o Raspberry Pi4 é muito rápido e você pode compilar programas diretamente nele. Se o projeto for simples, então é bem possível fazê-lo. Mas quando o projeto cresce e se torna mais complexo, então já é melhor mudar para a compilação cruzada. Então fica mais fácil resolver outros problemas, por exemplo, você pode organizar a montagem automática do projeto no servidor de integração. A compilação cruzada em um PC rápido pode aumentar significativamente a velocidade de compilação e você pode encontrar ferramentas melhores para editar programas em um PC.
Segunda pergunta: “Posso pegar um compilador cruzado pronto? Por que coletar o seu? " Para dizer a verdade, não encontrei um compilador cruzado normal para o Raspberry. Talvez eu estivesse mal? No github do Rasberryexiste um projeto de ferramentas e vários compiladores cruzados, mas eles são antigos! Bem, o que há? Versão 4.9.3? De alguma forma, não é sério. Na página de download do Linaro, vejo apenas a versão 7.5, já melhor, mas, em primeiro lugar, no próprio Raspberry Buster OS, a versão 8.3 já está, e em segundo lugar, o compilador Linaro funcionou para mim apenas após alguns patches. É meio estranho ...
Foi depois de tentar rodar o compilador Linaro que pensei que provavelmente poderia construir meu próprio compilador cruzado. Já tive alguma experiência com crosstool-ng. Eu estava fazendo um compilador cruzado para Amber SoC .
Qual é a complexidade da montagem? A ferramenta crosstool-ng tem muitas configurações diferentes que nem sempre são claras. Construir o compilador cruzado em meu laptop leva aproximadamente 45 minutos. Se você cometer um erro com as configurações, o compilador cruzado resultante de alguma forma não funcionará dessa forma, não coletará algo ou coletará, mas o binário resultante não será executado no Raspberry. Depois de verificar o compilador cruzado resultante, novamente tive que alterar algo nas configurações e gerá-lo novamente desde o início. Bem, fiz algumas tentativas até que funcionou do jeito que eu queria.
Talvez a principal coisa que eu realmente não entendi no início é que o compilador deve corresponder ao sistema operacional. Parece um pouco estranho, mas é o que acontece. Na verdade, o sistema operacional já contém as bibliotecas c / c ++ padrão. Eles exportam um conjunto de funções. O código gerado pelo compilador cruzado deve conter chamadas para essas funções de biblioteca. Portanto, as versões das bibliotecas no próprio compilador cruzado e no sistema operacional para o qual o código será gerado devem corresponder.
Vamos tentar criar um compilador cruzado.
O procedimento será o seguinte:
1) Verifique se os seguintes pacotes estão instalados em nosso sistema host (estou usando o Ubuntu 18):
gcc g++ gperf bison flex texinfo help2man make libncurses5-dev python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip patch libstdc++6 rsync git
Se algo estiver faltando, você precisa instalar via sudo apt install.
2) Baixe crosstool-ng versão 1.24.0 de seu site:
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.24.0.tar.bz2
3) Descompacte o arquivo resultante:
tar xjf crosstool-ng-1.24.0.tar.bz2 cd crosstool-ng-1.24.0
4) Juntando crosstool-ng:
./configure make make install
5) Patching crosstool-ng
Esta é uma ação bastante estranha, mas sem ela não obtive um bom resultado. Sem esse patch, o compilador cruzado se recusou por padrão a procurar bibliotecas na pasta / usr / lib / arm-linux-gnueabihf em relação ao sysroot.
O patch deve ser obtido na própria framboesa.
No raspberry pi4 com OS Buster instalado (isso é importante, estou fazendo um compilador cruzado para este sistema operacional em particular), você precisa pegar os fontes binutils:
sudo apt install binutils-source
e veja
/usr/src/binutils/patches/129_multiarch_libpath.patch
Este arquivo que colocamos na pasta crosstool-ng-1.24.0 / packages / binutils / 2.31.1 em nosso computador host. É importante colocá-lo nesta pasta, pois no próprio Raspberry Pi OS Buster, a versão binutils é 2.31.1. Verifique isso com um comando no console do framboesa:
ld --version
Além disso, você precisa verificar qual GLIB está em seu sistema operacional para o squeeze:
ldd --version
Eu tenho 2.28 no Buster, o que significa que o próprio crosstool-ng precisará ser configurado nesta versão do GLIB 2.28; há uma versão diferente por padrão. Se isso não for feito, o compilador cruzado gerará código que não será executado no Raspberry no Buster OS - o binário pode referir-se a funções inexistentes em bibliotecas externas.
6) Prepare a configuração inicial do crosstool-ng
Já existem algumas configurações típicas no próprio crosstool-ng. Inclusive, há uma configuração muito semelhante ao que precisamos para o Raspberry Pi3.
Uma lista de todas as configurações possíveis pode ser visualizada com o comando:
./ct-ng list-samples
Então a configuração selecionada deve ser “ativada” com o comando:
./ct-ng armv8-rpi3-linux-gnueabihf
Um novo arquivo de configuração .config aparecerá, que define completamente as propriedades do futuro cross-compiler. Agora isso precisa ser corrigido um pouco. Você pode editá-lo manualmente, mas é mais fácil de corrigir no menu:
./ct-ng menuconfig
O primeiro menu se parece com isto:
7) Em seguida, altere a opção estranha, possivelmente opcional.
Quase em todos os lugares onde pelo menos algo é escrito sobre a criação de um compilador cruzado para o Raspberry, eles escrevem para desmarcar a opção "Renderizar o conjunto de ferramentas somente leitura". Esta configuração está no menu "Caminhos e opções diversas". A documentação do crosstool-ng diz que, por padrão, o compilador resultante será somente leitura, para que o programa compilado não seja instalado inadvertidamente no sysroot do próprio compilador. Em minha opinião, esta é uma decisão perfeitamente razoável. Não sei por que algum autor escreve para remover a marca daqui ...
8) Próximo. Vá para o item "Opções de destino" e defina os valores de acordo com a imagem:
Devo dizer que, na verdade, o Raspberry Pi4 possui um processador Cortex-A72 e este pode ser atribuído aqui no menu. No entanto, guardei o Cortex-A53 para mim porque irei compilar não apenas para Pi4, mas também para Pi3. Embora a configuração exata já possa ser especificada ao iniciar o compilador gcc usando o parâmetro de linha de comando -mcpu = cortex-a72
Também quero acrescentar que prefiro que o compilador cruzado tenha exatamente a mesma tupla que o compilador na própria placa do Raspberry. Ou seja, o compilador final será arm-linux-gueabihf e nada mais. É mais fácil para mim. Muitos pacotes existentes incluem arquivos cmake prontos, onde o compilador é atribuído a arm-linux-gnueabihf. Não queremos consertar todos esses arquivos cmake manualmente e escrever algo como armv8-mygcc-linux-gnueabihf lá? Para fazer isso, desativo a opção "Omitir parte do fornecedor da tupla de destino".
9) Vá até o menu "Utilitários binários" e instale a versão binutils 2.31.1 (lembra que ainda temos um patch para ele?)
10) Vá até o menu "Sistema operacional" e instale o kernel versão 4.20
Na verdade, o Raspberry Buster OS já possui um kernel 5.10, mas o máximo é que você pode instalá-lo apenas 4.20
11) Vá ao menu "Bibliotecas C" e instale o GLIB 2.28 versão
12) Vá até o "Compilador C" menu
Instale a versão desejada do futuro cross-compiler 8.3.0 e adicione a opção --enable-multiarch às configurações do compilador de configuração extra do gcc. É importante que o compilador cruzado encontre as bibliotecas em sysroot ao longo do caminho / usr / lib / arm-linux-gnueabihf
Agora saímos de todos os menus, salvamos as alterações feitas quando solicitado e começamos a construir.
13) A montagem é realizada com comandos simples:
export DEB_TARGET_MULTIARCH=arm-linux-gnueabihf ./ct-ng build
Terá que esperar. Levei cerca de 45 minutos para montar meu laptop. Após compilar, seu novo compilador cruzado está localizado no caminho ~ / x-tools / arm-linux-gnueabihf.
Você pode verificar quais caminhos de biblioteca serão usados pelo compilador cruzado por padrão. Ele vai procurar no caminho / usr / lib / arm-linux-gnueabihf?
Para fazer isso, execute o comando:
~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ld --verbose | grep "SEARCH"
O comando deve retornar algo assim:
SEARCH_DIR("=/usr/local/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/home/nick/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/lib");
Observe que os caminhos começam com o sinal "=". Isso significa que esses são caminhos relativos ao sysroot, se especificados ao executar o gcc com a opção de linha de comando --sysroot = PATH_TO_YOUR_SYSROOT.
Provavelmente é tudo. Resta decidir onde obter o sysroot. A maneira mais fácil é instalar todos os pacotes de desenvolvimento necessários no Raspberry Pi e, em seguida, retirar o cartão SD do dispositivo, transferi-lo para o PC host. Mas também existem algumas nuances.
Agora que temos um compilador cruzado, podemos construir algum tipo de programa específico de analisador. Por exemplo, as demonstrações de userland do próprio Raspberry:
git clone https://github.com/raspberrypi/userland.git cd userland export PATH=${HOME}/x-tools/arm-linux-gnueabihf/bin:$PATH ./buildme
O resultado da compilação estará na pasta build / bin.
No final do artigo, gostaria de fornecer uma tabela de parâmetros adicionais para compiladores gcc ao construir projetos para diferentes versões do raspberry:
Raspberry Pi 1: -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp (alias for vfpv2) Raspberry Pi 2: -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 Raspberry Pi 3: -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits Raspberry Pi 4: -mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits
Espero que meu artigo seja útil para alguém.