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 aplicações que possam ser executadas sem problemas em várias plataformas de hardware torna-se inerentemente importante. Há uma necessidade constante de desenvolver o software em uma arquitetura, mas ter a capacidade de executar esses em outras arquiteturas-alvo. Uma técnica comum para alcançar isso é a compilação cruzada do aplicativo para a arquitetura-alvo.
Compilação cruzada é 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 x86 comum 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 aborda um estudo de caso onde a compilação cruzada de um pacote de código aberto foi feita para PowerPC. O artigo cobrirá os detalhes das ferramentas e cadeias de ferramentas utilizadas e um tutorial passo a passo sobre como a compilação cruzada foi alcançada para esta arquitetura.
Troblema
Dado um alvo com arquitetura PowerPC, a intenção era adicionar capacidades de roteamento L3 a esta placa. Para isso, um popular conjunto de protocolos de roteamento de código aberto, o FRRouting (FRR), foi considerado.
FRR é um conjunto de protocolos que permite que qualquer máquina Linux comporte-se como um roteador completo. É disponibilizado para amd64, arm64, armhf, e i386, mas não para PowerPC. Isso necessitou 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 Construção e Plataforma Alvo
Trilha da Cross-Compilation
Existem duas etapas principais na compilação cruzada:
Configurando o Ambiente de Construção e a Toolchain Pré-Compilada
1. Instale as ferramentas de construção necessárias no ambiente. Ferramentas de construção comuns incluem autoconf, make, cmake, build-essentials, pkg-config, libtool, etc.
2. Configure a toolchain pré-compilada específica para o ambiente host de destino. Fornecedores de CPU/placa disponibilizam suas próprias toolchains específicas para a arquitetura. A toolchain específica para a placa de destino foi obtida no site de produtos do fornecedor.
3. A toolchain vem com um arquivo de ambiente, que é usado para definir 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 na Ferramenta de Compilação Pré-Compilada
Cada software possui 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 de destino, existem duas opções para resolvê-los. Ou instalá-los diretamente a partir dos pacotes disponíveis ou compilá-los 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 disso, os pacotes de bibliotecas protobuf e libcap estavam disponíveis para a arquitetura PPC (PowerPC), que podem ser instalados diretamente na ferramenta de compilação.
1. Instalando Bibliotecas a partir de Pacotes
Pacotes de biblioteca disponíveis para a arquitetura de destino podem ser instalados no sysroot da ferramenta de compilação usando duas maneiras:
- A primeira maneira usa a ferramenta
dpkg-deb
baseada em 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:
- Faça o download de todos os pacotes de dependência e instale-os na ordem correta.
- 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 a ferramenta de cadeia de ferramentas.
- Na segunda maneira, os pacotes debian/rpm são extraídos e colocados manualmente no caminho do diretório da ferramenta, conforme mencionado abaixo:
- Para extrair pacotes debian, use as ferramentas
ar
etar
conforme mencionado abaixo:Texto Simples$ ar -x <pacote>.deb
$ tar -xJf data.tar.xz
Nota: Este método é útil para sistemas sem suporte a
dpkg-deb
. - Para extração de pacotes rpm, use a ferramenta
rpm2cpio
com o comando abaixo:Texto Simples$ rpm2cpio <pacote>.rpm | cpio -idmv
-
Exemplo de extração de pacotes e colocação de arquivos 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 contém os arquivos de programa do pacote
# control.tar.gz contém os metadados do pacote
# debian-binary contém a versão do formato de arquivo deb
# Descompactar data.tar.xz para extrair os arquivos de programa do pacote.
$ tar -xJf data.tar.xz
# NOTA: rpm2cpio <pacote>.rpm irá extrair diretamente os arquivos de programa.
# Faça o mesmo para todos os pacotes debian ou rpm dependentes no mesmo caminho, isso irá extrair todos os arquivos de programa e symlinks 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 toolchain_directory_path’s /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 env da toolchain
$ pkg-config --list-all | grep <nome_biblioteca_pacote>
Nota: Instale
pkg-config
se ainda não estiver instalado.
- Para extrair pacotes debian, use as ferramentas
2. Compilação Cruzada de Bibliotecas
Os pacotes de bibliotecas 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 incluído com a toolchain para definir todos os parâmetros necessários para a compilação cruzada.
$ source <env_file_path>
Siga os passos de compilação descritos no arquivo README da biblioteca. Além disso, defina os parâmetros abaixo nos passos do procedimento de compilação:
- Defina o
--host parameter
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 toolchain. É 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 é uma exigência de dependência para execução no host de destino. Defina o
--host parameter
de acordo.
- Ao usar “make install” para construir bibliotecas dependentes, defina o DESTDIR como o diretório raiz da ferramenta de cadeia de ferramentas.
Shell
$ make DESTDIR=<toolchain_directory_path> install
Examlple:
$ 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 compilação cruzada uma técnica complexa de ser executada. Para facilitar as complexidades, este artigo desvenda as fases da compilação cruzada. FRR e PowerPC foram tomados 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, o conjunto de ferramentas e as dependências variarão com base nos requisitos.
Source:
https://dzone.com/articles/heterogeneity-computing-environments-cross-compilation