$$HEADER$$
Este tutorial explica como criar um CCG+Newlib toolchain que poderá ser usado para compilar programas na arquitetura Cortex(Thumb2), tornando assim possível a compilação de programas para um grande número de CPUs Cortex(Luminary Micro, ST, com nova CPU Cortex sendo anunciada pela Atmel e outras companhias). Estou escrevendo este tutorial porque eu precisei trabalhar com uma CPU Cortex para o projeto eLua e não consegui encontrar em lugar nenhum, alguma ajuda para construir uma GCC para essa arquitetura. Você precisará de uma toolchain se quiser compilar eLua para CPUs Cortex-M3.
AVISO: Não sou um especialista no processo de compilação de CGC/newlib/binutils. Tenho certeza de que existem melhores formas de realizar o que estou descrevendo aqui, no entanto desejo apenas uma maneira rápida de construir um toolchain, não tenho nenhuma intenção de ficar muito íntimo do processo de construção. Se você acha que o que fiz aqui está errado, impreciso ou, simplesmente, escandalosamente feio, não hesite em contactar-me e farei as correcções necessárias. E claro, este tutorial é fornecido sem qualquer garantia.
Para construir seu toolchain você precisará de:
Você ainda precisará de outros programas e bibliotecas a fim de montar o toolchain. Para instalá-los execute o seguinte comando:
$ sudo apt-get install flex bison libgmp3-dev libmpfr-dev autoconf texinfo build-essential |
---|
Em seguida, decida onde pretende instalar o seu toolchain. Eles geralmente são instalados no diretório /usr/local/, logo, assumiremos o diretório /usr/local/cross-cortex para este tutorial. Para agilizar a digitação, defina este caminho como padrão na variável do ambiente:
$ export TOOLPATH=/usr/local/cross-cortex |
---|
Este é o passo mais fácil: descompactar, configurar, montar.
$ tar -xvjf binutils-2.19.tar.bz2 |
---|
$ cd binutils-2.19 |
$ mkdir build |
$ cd build |
$ ../configure --target=arm-elf --prefix=$TOOLPATH --enable-interwork --enable-multilib --with-gnu-as --with-gnu-ld --disable-nls |
$ make all |
$ sudo make install |
$ export PATH=${TOOLPATH}/bin:$PATH |
Agora você tem os "binutils" da CPU Cortex(assembler, linker, disassembler ...) em seu PATH. Eles funcionam com a arquitetura Thumb2.
Nesta etapa vamos construir um GCC "básico" (ou seja, uma GCC sem nenhuma lib, a qual usaremos, a fim de criar todas as bibliotecas para o nosso objetivo). Mas primeiro temos de fazer uma rápida modificação nos arquivos de configuração. Fora desse ambiente, o pacote GCC 4.3.1/newlib não compilará corretamente, dando um erro muito estranho "Link tests are not allowed after GCC_NO_EXECUTABLES". Após googlear um pouco, encontrei a solução para isso:
$ tar -xvjf gcc-4.3.1.tar.bz2 |
---|
$ cd gcc-4.3.1/libstdc++-v3 |
$ joe configure.ac |
Estou usando "joe" aqui como meu editor de texto Linux favorito, você pode usar qualquer outro editor de texto. Agora encontre a linha que tem "AC_LIBTOOL_DLOPEN" e adicione um "#" no inicio da linha:
# AC_LIBTOOL_DLOPEN
Salve o arquivo e saia do editor de texto.
$ autoconf |
---|
$ cd .. |
Ótimo, agora sabemos que podemos compilar, então vamos em frente:
$ mkdir build |
---|
$ cd build |
$ ../configure --target=arm-elf --prefix=$TOOLPATH --enable-interwork --enable-multilib --enable-languages="c,c++" --with-newlib --without-headers --disable-shared --with-gnu-as --with-gnu-ld |
$ make all-gcc |
$ sudo make install-gcc |
No meu sistema, a execução da última linha acima(sudo make install-gcc) gera um erro, devido a impossibilidade de encontrar o arquivo binutils. Se isso também acontece no seu sistema, aqui está uma maneira rápida de resolver:
$ sudo -s -H |
---|
# export PATH=/usr/local/cross-cortex/bin:$PATH |
# make install-gcc |
# exit |
Mais uma vez, algumas modificações s;ão necessárias antes de começarmos a compilação. Devido a versão CVS da NewLib parecer não permitir o suporte necessário para o Thumb2, precisamos fazer a NewLib saltar algumas de suas libraries durante a compilação:
$ cd [directory where the newlib CVS is located] |
---|
$ joe configure.ac |
Localize o código abaixo:
arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
noconfigdirs="$noconfigdirs target-libffi target-qthreads"
libgloss_dir=arm
;;
And add "target-libgloss" to the "noconfigdirs" variable:
arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
noconfigdirs="$noconfigdirs target-libffi target-qthreads target-libgloss"
libgloss_dir=arm
;;
Salve o arquivo e saia do editor
$ autoconf
Em um dos sistemas onde executei a sequência acima, aconteceram erros, indicando que o arquivo autoconf 2.59 não tinha sido encontrado. Não entendi porque isto aconteceu. Como a vers;ão 2.59 já não é tão recente, e a compilação roda muito bem com a 2.61 (a vers;ão do autoconf no sistema que apresentou erro). Se isto acontece com você, execute inicialmente o autoconf --version para saber qual a versão corrente de seu autoconf, e então faça o seguinte:
$ joe config/override.m4
Localize esta linha:
[m4_define([_GCC_AUTOCONF_VERSION], [2.59])])
E substitua 2.59 pela sua versão atual (no meu caso 2.61).
$ autoconf
Agora estamos prontos para compilar a Newlib. Mas é necessário informar que a compilação será feita para Thumb2. Como já foi dito antes, eu não sou um especialista, e quando se trata de montar uma Newlib, escolhi uma solução rápida, porém não tão elegante para passar os parametros de compilação diretamente na linha de comando. Além disso, como eu prefiro que a minha biblioteca tenha o menor tamanho possível (em contraposição a maior performance possível) e manter no programa executável somente o necessário, acrescentei o parametro "-ffunction-seções-fdata-sections" para permitir que o linker possa executar dead code stripping:
$ mkdir build |
---|
$ cd build |
$ ../configure --target=arm-elf --prefix=$TOOLPATH --enable-interwork --disable-newlib-supplied-syscalls --with-gnu-ld --with-gnu-as --disable-shared |
$ make CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -Os -fomit-frame-pointer -mcpu=cortex-m3 -mthumb -D__thumb2__ -D__BUFSIZ__=256" CCASFLAGS="-mcpu=cortex-m3 -mthumb -D__thumb2__" |
$ sudo make install |
Algumas observações sobre os parâmetros usados na sequência acima:
--disable-newlib-supplied-syscalls:
isso merece um capítulo a parte, porém n&ão agora. Apenas como esclarecimento, veja os exemplos nesta página.-DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__:
compile a Newlib otimizando o tamanho, e não a performance (utilizado para Newlib específica).-mcpu=cortex-m3 -mthumb:
indica para a GCC que a compilação é para Cortex. É necessário utilizar os dois flags.-D__thumb2__:
É necessário quando compilando a Newlib para o Cortex.-Os -fomit-frame-pointer:
indica para a GCC para otimizar pelo tamanho, e não pela performance.-D__BUFSIZ__=256:
parâmetro específico navamente, este é o tamanho do buffer alocado por default para arquivos abertos via fopen(). O default é 1024, o qual acredito ser muito para eLua, logo utilizo aqui 256. Certamente, você poderá mudar este valor.Finalmente, no último passo deste nosso tutorial, completamos a montagem do GCC. Nesta etapa, várias bibliotecas de suporte do compilador foram montadas (sendo a mais importante a libgcc.a). Felizmente este é o passo mais simples para a montagem da NewLib, e como você se lembra, ainda queremos montar nosso compilador para a arquitetura Cortex:
$ cd gcc-4.3.1/build |
---|
$ make CFLAGS="-mcpu=cortex-m3 -mthumb" CXXFLAGS="-mcpu=cortex-m3 -mthumb" LIBCXXFLAGS="-mcpu=cortex-m3 -mthumb" all |
$ sudo make install |
UFA! Esse tutorial foi um pouco confuso, com um monte de flags e linhas de comando muito longas :) No entanto, você possui agora um GCC toolchain para Cortex funcionando, o que parece ser uma coisa bastante rara hoje, então aproveite com orgulho. Se você precisar de mais explicações, ou se as instruções acima não funcionaram para você, sinta-se a vontade para contactar-me.
$$FOOTER$$