Com o advento do software de código aberto e a aceitação dessas soluções na criação de sistemas complexos, a capacidade de desenvolver aplicativos que possam ser executados perfeitamente em várias plataformas de hardware torna-se inerentemente importante. Existe uma necessidade constante de desenvolver o software em uma arquitetura, mas ter a capacidade de executá-lo em outras arquiteturas de destino. Uma técnica comum para alcançar isso é a compilação cruzada da aplicação para a arquitetura de destino.
Cross-compilaçãoé significativa em sistemas embarcados onde a intenção é executar aplicativos em hardware especializado como placas ARM e PowerPC. Esses sistemas têm recursos limitados e, portanto, a compilação direta não é uma opção.Assim, os desenvolvedores aproveitarão a arquitetura comum x86 como hospedeira e usarão ferramentas específicas para o hardware de destino, gerando binários compatíveis com o hardware de destino.
Este artigo abrange um estudo de caso onde a cross-compilação de um pacote de código aberto foi feita para PowerPC. O artigo abordará os detalhes das ferramentas e toolchains utilizadas e um tutorial passo a passo sobre como a cross-compilação foi alcançada para esta arquitetura.
The Declaração do Problema
Dado um quadro de destino com arquitetura PowerPC, a intenção era adicionar capacidades de roteamento L3 a este quadro. Para esse fim, foi considerado um popular conjunto de protocolos de roteamento de código aberto, FRRouting (FRR).
FRR é um conjunto de protocolos que permite que qualquermáquina Linux se comporte como umroteador completo. Ele é empacotado para amd64, arm64,armhf, e i386, masnão paraPowerPC. Issonecessitou a compilação cruzada do FRR.
Build host | target host | |
---|---|---|
Arquitetura da CPU |
x86_64 |
Powerpc(32-bit) |
Sistema Operacional |
Ubuntu 18.4 |
QorIQ SDK |
CPU |
12 |
2 (e5500) |
RAM |
12GB |
1GB |
Tabela 1. Diferença na plataforma de construção e de destino
A jornada da compilação cruzada
Existem duas etapas principais na compilação cruzada:
Configurando o Ambiente de Compilação e a Toolchain Pré-Compilada
1. Instale as ferramentas de compilação necessárias no ambiente. As ferramentas comuns de compilação incluem autoconf, make, cmake, build-essentials, pkg-config, libtool, etc.
2. Configure a toolchain pré-compilada específica para o ambiente do host de destino. Os fornecedores de CPU/Placa fornecem suas próprias toolchains específicas de arquitetura. A toolchain específica da placa de destino foi obtida no site do produto do fornecedor.
3. A toolchain vem com um arquivo de ambiente, que é usado para configurar as variáveis de ambiente como CC, GCC, PKG_CONFIG_PATH, etc., que são necessárias para a compilação cruzada. Edite o arquivo de ambiente /opt/fsl-qoriq/2.0/environment-setup-ppce5500-fsl-linux
e atualize o caminho das variáveis em relação ao caminho do diretório da toolchain.
export SDKTARGETSYSROOT=/opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux
export PATH=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/../x86_64-fslsdk-linux/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-uclibc:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-musl:$PATH
export CCACHE_PATH=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/../x86_64-fslsdk-linux/bin:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-uclibc:/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc-fsl-linux-musl:$CCACHE_PATH
export PKG_CONFIG_SYSROOT_DIR=$SDKTARGETSYSROOT
export PKG_CONFIG_PATH=$SDKTARGETSYSROOT/usr/lib/pkgconfig
export CONFIG_SITE=/opt/fsl-qoriq/2.0/site-config-ppce5500-fsl-linux
export PYTHONHOME=/opt/fsl-qoriq/2.0/sysroots/x86_64-fslsdk-linux/usr unset command_not_found_handle
export CC="powerpc-fsl-linux-gcc -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export CXX="powerpc-fsl-linux-g++ -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export CPP="powerpc-fsl-linux-gcc -E -m32 -mhard-float -mcpu=e5500 --sysroot=$SDKTARGETSYSROOT"
export AS="powerpc-fsl-linux-as "
export LD="powerpc-fsl-linux-ld --sysroot=$SDKTARGETSYSROOT"
export GDB=powerpc-fsl-linux-gdb
export STRIP=powerpc-fsl-linux-strip
export RANLIB=powerpc-fsl-linux-ranlib
export OBJCOPY=powerpc-fsl-linux-objcopy
export OBJDUMP=powerpc-fsl-linux-objdump
export AR=powerpc-fsl-linux-ar
export NM=powerpc-fsl-linux-nm
export M4=m4
export TARGET_PREFIX=powerpc-fsl-linux-
export CONFIGURE_FLAGS="--target=powerpc-fsl-linux --host=powerpc-fsl-linux --build=x86_64-linux --with-libtool-sysroot=$SDKTARGETSYSROOT"
export CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
export CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
export LDFLAGS="-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed"
export CPPFLAGS=""
export KCFLAGS="--sysroot=$SDKTARGETSYSROOT"
export OECORE_DISTRO_VERSION="2.0"
export OECORE_SDK_VERSION="2.0"
export ARCH=powerpc
export CROSS_COMPILE=powerpc-fsl-linux-
Resolvendo Dependências em Toolchain Pré-Compilada
Cada software tem seu próprio conjunto de dependências (ferramentas/bibliotecas), que precisam ser resolvidas antes da compilação cruzada.
Dependendo da disponibilidade dos pacotes dessas ferramentas/bibliotecas na arquitetura alvo, existem duas opções para resolvê-las. Ou instale-as diretamente a partir dos pacotes disponíveis ou compile-as também a partir do código-fonte.
Especificamente para a compilação do FRR, as bibliotecas libpcre2, libyang, clippy, libelf e json-c precisam ser construídas a partir do código-fonte. Além dessas, os pacotes de biblioteca protobuf e libcap estavam disponíveis para a arquitetura PPC (PowerPC), que podem ser instalados diretamente na toolchain.
1. Instalando Bibliotecas a partir de Pacotes
Pacotes de biblioteca disponíveis para a arquitetura alvo podem ser instalados na sysroot da toolchain de duas maneiras:
- A primeira maneira usa a ferramenta
dpkg-deb
baseada no Ubuntu/Debian para instalar diretamente pacotes Debian, conforme mencionado abaixo:Shell$ dpkg-deb -x <pkg_name>.deb <toolchain_directory_path>
#Exemplo de libcap:
$ wget http://launchpadlibrarian.net/222364908/libcap-dev_2.24-12_powerpc.deb
$ dpkg-deb -x libcap-dev_2.24-12_powerpc.deb /opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/
Nota:
- Baixe todos os pacotes de dependência e instale-os em ordem.
- Os pacotes de biblioteca podem ser instalados em uma estrutura de diretório diferente. Copie esses arquivos de biblioteca para os diretórios corretos conforme o toolchain.
- Dessa forma, os pacotes debian/rpm são extraídos e colocados manualmente no caminho do diretório da ferramenta conforme mencionado abaixo:
- Para extrair o pacote debian, use as ferramentas
ar
etar
conforme mencionado abaixo:Texto Puro$ ar -x <pacote>.deb
$ tar -xJf data.tar.xz
Nota: Este método é útil para sistemas sem suporte ao
dpkg-deb
. - Para extração de pacotes rpm, use a ferramenta
rpm2cpio
conforme o comando abaixo:Texto Puro$ rpm2cpio <pacote>.rpm | cpio -idmv
-
Exemplo de extração de pacote e colocação de arquivo com libcap:
Shell# Extrair pacote .deb
$ ar -x libcap-dev_2.24-12_powerpc.deb
# Três arquivos serão extraídos (control.tar.gz, data.tar.xz, debian-binary)
$ ls
control.tar.gz data.tar.xz debian-binary libcap-dev_2.24-12_powerpc.deb
# data.tar.xz possui os arquivos do programa do pacote
# control.tar.gz possui os metadados do pacote
# debian-binary possui a versão do formato de arquivo deb
# Descompacte data.tar.xz para extrair os arquivos do programa do pacote.
$ tar -xJf data.tar.xz
# NOTA: rpm2cpio <pacote>.rpm irá extrair diretamente os arquivos do programa.
# Faça o mesmo para todos os pacotes dependentes debian ou rpm no mesmo caminho, isso irá extrair todos os arquivos de programa e links simbólicos necessários na mesma estrutura de diretório.
# Os arquivos extraídos sob os diretórios usr/lib, usr/include e usr/bin devem ser copiados para o diretório do caminho do diretório da ferramenta /usr, ao lado dos arquivos existentes já presentes.
$ cp usr/include/sys/capability.h /opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/usr/include/sys/
-
Para verificar se os pacotes/bibliotecas foram instalados com sucesso, execute o comando abaixo:
Shell# Certifique-se de exportar a variável PKG_CONFIG_PATH do arquivo de ambiente da ferramenta
$ pkg-config --list-all | grep <nome_da_biblioteca_do_pacote>
Nota: Instale o
pkg-config
se ainda não estiver instalado.
- Para extrair o pacote debian, use as ferramentas
2. Compilando Bibliotecas para Plataformas Cruzadas
Os pacotes de biblioteca não estão disponíveis para a arquitetura de destino e são compilados a partir do código-fonte. Antes de iniciar a compilação, carregue o arquivo de ambiente empacotado com o conjunto de ferramentas para configurar todos os parâmetros necessários para a compilação cruzada.
$ source <env_file_path>
Siga os passos de compilação fornecidos no arquivo README da biblioteca. Além disso, defina os parâmetros abaixo no procedimento de construção:
- Defina o parâmetro
--host
ao executar o script./configure
Shell$ ./configure --host=<target_host_parameter>
# Exemplo:
$ ./configure --host=powerpc-fsl-linux
Nota:
- <target_host_parameter> é o sistema para o qual a biblioteca/ferramenta está sendo construída. Pode ser encontrado no arquivo de ambiente da cadeia de ferramentas. É um prefixo comum encontrado em $CC, $LD, etc.
- Haverá dois tipos de bibliotecas dependentes. Uma é necessária apenas para o processo de compilação, e a outra é um requisito de dependência para execução no host alvo. Defina o parâmetro
--host
de acordo.
- Ao usar “make install” para construir bibliotecas dependentes, defina DESTDIR como o diretório raiz da ferramenta de cadeia de ferramentas.
Shell
$ make DESTDIR=<caminho_do_diretório_da_ferramenta> install
Exemplo:
$ make DESTDIR=/opt/fsl-qoriq/2.0/sysroots/ppce5500-fsl-linux/ install
Conclusão
As diferenças nas arquiteturas de sistemas, bibliotecas, dependências e ferramentas tornam a técnica de compilação cruzada complexa de ser executada. Para facilitar as complexidades, este artigo revela as fases da compilação cruzada. FRR e PowerPC foram utilizados como exemplos para o software desejado e o hardware de destino, respectivamente. No entanto, os passos abordados neste artigo fornecem uma estratégia razoável para a compilação cruzada de qualquer software em um hardware específico. As configurações de ambiente, a ferramenta de compilação e as dependências variarão com base nos requisitos.
Source:
https://dzone.com/articles/heterogeneity-computing-environments-cross-compilation