$$HEADER$$
Esse tutorial explica como criar um toolchain com GCC+Newlib para ser usado na compilação de programas usando a arquitetura ARM, tornando assim possível a compilação de programas para um grande número de CPUs com arquitetura ARM. Você precisará desse recurso se pretende compilar eLua para as CPUs com arquitetura ARM. Esse tutorial é semelhante a muitos outros encontrados na Internet (particularmente o gnuarm, que serviu de base para esse tutorial), no entanto, este possui um maior detalhamento e mostra alguns "dicas" que você poderá utilizar quando estiver compilando a Newlib.
AVISO: Eu não sou um especialista no processo de montagem de CGC/newlib/binutils. Tenho certeza de que existem melhores formas de realizar o que estou descrevendo aqui, no entanto, apresento apenas uma maneira rápida de construir um toolchain, não tenho nenhuma intenção de me aprofundar no processo de montagem. Se você encontrar algum erro, por favor entre em contato comigo e farei as correções necessárias. Acrescento ainda, que esse tutorial não possui nenhum tipo de 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:
$ sudo apt-get install flex bison libgmp3-dev libmpfr-dev autoconf texinfo |
---|
Em seguida, defina onde pretende instalar o seu toolchain. Eles geralmente são instalados no diretório /usr/local/, logo, assumiremos o diretório /usr/local/cross-arm para este tutorial. Para agilizar a digitação, defina este caminho como padrão na variável de ambiente:
$ export TOOLPATH=/usr/local/cross-arm |
---|
Este é o passo mais fácil: descompactar, configurar, compilar.
$ tar -xvjf binutils-2.17.tar.bz2 |
---|
$ cd binutils-2.17 |
---|
$ 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 ARM(assembler, linker, disassembler ...) em seu PATH.
Nesta etapa vamos montar uma "base" GCC (ou seja, uma GCC sem nenhuma lib, a qual usaremos, a fim de criar todas as bibliotecas para o nosso objetivo). Mas primeiro temos que 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 GCCNOEXECUTABLES". Após uma procura no google, 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 tenha o string "AC_LIBTOOL_DLOPEN" e adicione um "#" no inicio da linha:
# AC_LIBTOOL_DLOPEN
Salve o arquivo alterado e saia do editor.
$ 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 última linha acima (sudo make install-gcc) termina com erros, devido a impossibilidade de encontrar a binutils recentemente compilada. Se isso acontece para qualquer tipo de comando "make install", aqui está uma maneira rápida de resolver isso:
$ sudo -s -H |
---|
# export PATH=/usr/local/cross-arm/bin:$PATH |
# make install-gcc |
# exit |
Mais uma vez, este etapa é tão fácil quanto descompactar, configurar, compilar. Mas eu preciso que a minha biblioteca seja do menor tamanho possível (em contraposição, tão rápida quanto possível) e eu só queria manter o que é necessário no executável, por isso, acrescentei os flags "-ffunction-sections -fdata-sections" para permitir que o linker execute "dead code stripping":
$ tar xvfz newlib-1.16.0.tar.gz |
---|
$ cd newlib-1.16.0 |
$ 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 -D__BUFSIZ__=256" |
$ sudo make install |
Algumas observações sobre os flags usados na sequência acima:
--disable-newlib-supplied-syscalls
: isto merece uma página própria, mas não vou fazê-lo aqui. Para uma explicação, por exemplo, ver esta página-DPREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__
: compila Newlib otimizando o tamanho, não a performance (estes são específicos da Newlib).-Os -fomit-frame-pointer
: indica para GCC otimizar o tamnho, não a velocidade.-D__BUFSIZ__=256
:
novamente específico da Newlib, este é o tamanho default do buffer alocado para arquivos abertos via fopen(). O padrão é 1024, cujo tamanho considerei muito para eLua, logo estou usando 256 aqui. Certamente, você pode mudar este valor.Finalmente, no último passo deste tutorial, completamos a construção do GCC. Nesta etapa, várias bibliotecas de suporte do compilador são montadas (sendo a mais importante a libgcc.a). Felizmente este á o mais simples dos passos de compilação da NewLib:
$ cd gcc-4.3.1/build |
---|
$ make all |
$ sudo make install |
Agora você pode finalmente desfrutar do seu toolchain para ARM, e compile eLua com ele :) Se você precisar de mais explicações, ou se as instruções acima não funcionaram para você, sinta-se a vontade para entrar em contato comigo..
$$FOOTER$$