Conjuntos de ferramentas autônomos (obsoletos)

Você pode usar os conjuntos de ferramentas fornecidos com o Android NDK de forma independente ou como plug-ins com um ambiente de desenvolvimento integrado já existente. Essa flexibilidade pode ser útil se você já tem um sistema de compilação próprio e só precisa do recurso para invocar o compilador cruzado a fim de incluir a compatibilidade com o Android.

Selecionar o conjunto de ferramentas

Antes de tudo, é preciso escolher a que arquitetura de processador o conjunto de ferramentas autônomo será destinado. Isso pode ser feito com a sinalização --arch.

Selecionar o sysroot

O próximo passo é definir seu sysroot. O sysroot é um diretório que contém os cabeçalhos e as bibliotecas do sistema para seu destino. Para definir o sysroot, é necessário saber para qual nível da API do Android você oferecerá compatibilidade nativa. As APIs nativas disponíveis variam de acordo com o nível da API do Android.

As bibliotecas para APIs nativas dos respectivos níveis da API do Android (link em inglês) ficam em $NDK/platforms/. Cada diretório no nível da API contém subdiretórios para as CPUs e arquiteturas diversas. Os cabeçalhos residem em $NDK/sysroot.

Para saber mais sobre os níveis da API do Android e as respectivas APIs nativas compatíveis, consulte APIs nativas.

Criar o conjunto de ferramentas

O NDK oferece o script make_standalone_toolchain.py para instalação de um conjunto de ferramentas personalizado pela linha de comando.

Essa é uma nova ferramenta que substitui make-standalone-toolchain.sh. Ela foi reimplementada em Python para que os usuários do Windows não precisem instalar o Cygwin ou MSYS (links em inglês) para executar a ferramenta.

O script está localizado no diretório $NDK/build/tools/, em que $NDK é a raiz da instalação do NDK.

Veja um exemplo do uso desse script:

$NDK/build/tools/make_standalone_toolchain.py \
    --arch arm --api 21 --install-dir /tmp/my-android-toolchain

Esse comando cria um diretório chamado /tmp/my-android-toolchain/, contendo uma cópia do sysroot android-21/arch-arm e dos binários do conjunto de ferramentas para ARM de 32 bits.

Os binários do conjunto de ferramentas não dependem nem contêm caminhos específicos para o host. Em outras palavras, é possível instalá-los em qualquer local ou até movê-los, se necessário.

O argumento --arch é obrigatório, mas o nível da API padrão será o mínimo compatível com a arquitetura (atualmente, 16 para arquiteturas de 32 bits e 21 para arquiteturas de 64 bits).

Desde a versão r18, todos os conjuntos de ferramentas autônomos usam Clang e libc++. Por padrão, a biblioteca compartilhada libc++ será usada, exceto durante a compilação de executáveis estáticos. Para forçar o uso da biblioteca estática, transmita -static-libstdc++ durante a vinculação. Esse comportamento corresponde ao de um conjunto de ferramentas de host normal.

Como mencionado em Compatibilidade com a biblioteca C++, normalmente é necessário transmitir -latomic ao fazer vinculação com a libc++.

Se a opção --install-dir for omitida, a ferramenta criará um tarball chamado $TOOLCHAIN_NAME.tar.bz2 no diretório atual. É possível colocar o tarball em um diretório diferente usando a opção --package-dir.

Para ver mais opções e detalhes, use --help.

Trabalhar com Clang

Os binários do Clang são incluídos automaticamente nos conjuntos de ferramentas autônomos.

Há também dois scripts de wrapper chamados clang e clang++ em <install-dir>/bin. Esses scripts invocam o binário clang com as sinalizações de arquitetura apropriadas. Em outras palavras, eles precisam funcionar sem exigir nenhuma modificação, e você poderá usá-los nas suas compilações simplesmente configurando as variáveis de ambiente CC e CXX para apontar para eles.

Há também os scripts de wrapper gcc e g++, que também chamam o Clang. Eles fornecem certo nível de compatibilidade para arquivos de compilação que se referem explicitamente ao GCC, embora o NDK não contenha mais o GCC. Obviamente, se um arquivo de compilação usar opções de linha de comando não compatíveis com o Clang, será necessário removê-las ou substituí-las.

Alvos do Clang com ARM

Em compilações para ARM, o Clang altera o alvo com base na presença das sinalizações de compilador -march=armv7-a e/ou -mthumb:

Tabela 1. Valores -march especificáveis e alvos resultantes.

Valor -march Alvo resultante
-march=armv7-a armv7-none-linux-androideabi
-mthumb thumb-none-linux-androideabi
-march=armv7-a e -mthumb thumbv7-none-linux-androideabi

Se quiser, você também pode substituir por seu -target.

clang e clang++ precisam ser substituídos para gcc e g++ em um makefile. Em caso de dúvida, use as seguintes opções ao invocar o compilador para verificar se eles estão funcionando corretamente:

  • -v para fazer o despejo de comandos associados a problemas de driver do compilador.
  • -###-para fazer o despejo de opções de linha de comando, incluindo as predefinidas implicitamente.
  • -x c < /dev/null -dM -E para fazer o despejo de predefinições do pré-processador
  • -save-temps para comparar os arquivos pré-processados de *.i ou *.ii.

Compatibilidade com ABI

Por padrão, um conjunto de ferramentas autônomo Clang ARM terá como alvo a ABI armeabi-v7a. Para modificar essa configuração, use a opção -march ou -target adequada.

É recomendável usar a sinalização do compilador -mthumb para forçar a geração de instruções Thumb-2 de 16 bits. Caso essa sinalização seja omitida, o conjunto de ferramentas gerará instruções para ARM de 32 bits.

Para usar as instruções de NEON, use a seguinte sinalização do compilador -mfpu: -mfpu=neon.

Essa configuração força o uso de VFPv3-D32 de acordo com a especificação da ARM.

Além disso, forneça estas duas sinalizações ao vinculador: -march=armv7-a -Wl,--fix-cortex-a8.

A primeira sinalização instrui o vinculador a selecionar as bibliotecas de conjunto de ferramentas adequadas para armv7-a. A segunda sinalização é necessária como uma alternativa a um bug da CPU em algumas implementações de Cortex-A8.

Não é necessário usar nenhum sinalizador de compilador específico para trabalhar com outros ABIs.

Para saber mais sobre a compatibilidade com ABIs, consulte ABIs do Android.

Avisos e limitações

Compatibilidade com Windows

Os binários do Windows não dependem do Cygwin. Essa falta de dependência faz com que eles sejam mais rápidos. No entanto, o ponto negativo é que eles não entendem especificações de caminho do Cygwin, como cygdrive/c/foo/bar, ao contrário de C:/foo/bar.

Exceções, RTTI e STL

Os binários do conjunto de ferramentas são compatíveis com exceções de C++ e RTTI por padrão. Para desativar as exceções de C++ e RTTI ao compilar fontes (para, por exemplo, gerar um código de máquina mais leve), use -fno-exceptions e -fno-rtti.

Compatibilidade com STL C++

O conjunto de ferramentas autônomo inclui uma implementação da Standard Template Library (STL) de C++.

  • Use -static-libstdc++ para conseguir a versão da biblioteca estática da libc ++. Isso garante que todo código STL C++ necessário seja incluído no binário final. Esse método é o ideal para gerar um único executável ou biblioteca compartilhada, que é a nossa recomendação.

  • A versão de biblioteca compartilhada do libc++ será usada por padrão. Nenhuma outra sinalização é necessária para fazer a vinculação com a biblioteca compartilhada. Você precisa incluir libc++_shared.so no seu app para que o código seja carregado.

    A Tabela 2 mostra a localização desse arquivo para cada arquitetura.

    Tabela 2. Valores -march especificáveis e alvos resultantes.

    Conjunto de ferramentas Local
    arm $TOOLCHAIN/arm-linux-androideabi/lib/
    arm64 $TOOLCHAIN/aarch64-linux-android/lib/
    x86 $TOOLCHAIN/i686-linux-android/lib/
    x86_64 $TOOLCHAIN/x86_64-linux-android/lib/

Criar projetos de código aberto com conjuntos de ferramentas autônomos

Considere este exemplo de conjunto de ferramentas:

# Create an arm64 API 26 libc++ toolchain.
$NDK/build/tools/make_standalone_toolchain.py \
  --arch arm64 \
  --api 26 \
  --install-dir=my-toolchain

Veja como configurar seu ambiente para usá-lo na criação de um projeto de código aberto tradicional:

# Add the standalone toolchain to the search path.
export PATH=$PATH:`pwd`/my-toolchain/bin

# Tell configure what tools to use.
target_host=aarch64-linux-android
export AR=$target_host-ar
export AS=$target_host-clang
export CC=$target_host-clang
export CXX=$target_host-clang++
export LD=$target_host-ld
export STRIP=$target_host-strip

# Tell configure what flags Android requires.
export CFLAGS="-fPIE -fPIC"
export LDFLAGS="-pie"

Projetos com sistemas de compilação personalizados

Veja um exemplo de como criar um toybox após realizar as etapas anteriores:

git clone https://github.com/landley/toybox.git
cd toybox
make defconfig && make

Projetos com autoconf

Como alternativa, os projetos baseados em autoconf teriam a seguinte aparência:

tar zxvf make-4.2.tar.gz
cd make-4.2
./configure --host=$target_host && make

Os projetos baseados em autoconf variam consideravelmente quanto à compatibilidade com a compilação cruzada. Além disso, se você usar git clone em um projeto baseado em autoconf, provavelmente não haverá um script configure registrado. Por isso, você precisará seguir a documentação do projeto para descobrir como fazer a inicialização.