$$HEADER$$
Inicialmente, a idéia de um "i386" cross "compiler" em Linux parece estranha. Afinal, você já roda Linux numa plataforma compatível com i386. Porém, o compilador as vezes segue certos caminhos misteriosos junto com o sistema operacional onde este está rodando (veja por exemplo esta página para alguns sintomas possíveis). E ainda, você deseja usar uma NewLib, e não uma Libc, e ainda adaptar o máximo possível o seu ambiente às suas necessidades. Portanto, este tutorial irá mostrá-lo como fazer isso.
AVISO: Não sou um especialista no processo de construção de uma GCC/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 neste processo. Se você acha que, o que fiz aqui está errado, impreciso ou, simplesmente, escandalosamente feio, não hesite em contactar-me e farei as correções necessárias. E claro, este tutorial é fornecido sem qualquer tipo de garantia.
Para construir seu toolchain você precisará de:
Você ainda precisará de outros programas e bibliotecas a fim de construir o toolchain. Para instalá-los:
$ sudo apt-get install flex bison libgmp3-dev libmpfr-dev autoconf texinfo |
---|
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-i386 para este tutorial. Para agilizarmos a digitação, defina este caminho como padrão na variável de ambiente:
$ export TOOLPATH=/usr/local/cross-i686 |
---|
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=i686-elf --prefix=$TOOLPATH --with-gnu-as --with-gnu-ld --disable-nls |
$ make all |
$ sudo make install |
$ export PATH=${TOOLPATH}/bin:$PATH |
Agora você tem os "binutils" para a CPU i386(assembler, linker, disassembler ...) em seu PATH.
Nesta etapa iremos criar uma GCC "básica" (ou seja, uma GCC sem nenhuma bibliotecas de suporte, a qual utilizaremos 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, emitindo o seguinte erro muito estranho "Link tests are not allowed after GCC_NO_EXECUTABLES". Após googlear um pouco, encontrei a seguinte solução:
$ tar -xvjf gcc-4.3.1.tar.bz2 |
---|
$ cd gcc-4.3.1/libstdc++-v3 |
$ joe configure.ac |
Estou usando o "joe", como meu editor de Linux favorito, no entanto, 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 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=i686-elf --prefix=$TOOLPATH --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-i686/bin:$PATH
# make install-gcc
# exit
Outra vez, esse passo 3 NewLib, é tão fácil quanto descompactar, configurar e compilar. Mas eu preciso que a minha biblioteca seja do menor tamanho possível (em contraposição, a tão rápida quanto possível) e só quero manter o 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=i686-elf --prefix=$TOOLPATH --disable-newlib-supplied-syscalls --with-gnu-ld --with-gnu-as --disable-shared |
$ make CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -D__PREFER_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 inteira, mas não dá para fazê-lo aqui. Para um melhor entendimento, veja esta página.-D__PREFER_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 criaçã da GCC. Nesta etapa, várias bibliotecas de suporte do compilador são montadas (sendo a mais importante a libgcc.a). Felizmente isto é mais simples do que a compilacriação da NewLib:
$ cd gcc-4.3.1/build |
---|
$ make all |
$ sudo make install |
Finalmente, você poderá usar o seu toolchain para i386, e compilar eLua com ele :) Após completar os passos acima, você será capaz de dar boot em eLua direto do seu PC, como descrito aqui, e não precisará fazer o download do arquivo ELF da página do projeto eLua, já que você o gerou usando sua própria toolchain! 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$$