Cómo usar el NDK con otros sistemas de compilación

El NDK es oficialmente compatible con ndk-build y CMake. La mayoría de los usuarios deben consultar una de esas guías para compilar el código de la aplicación. El propósito de este documento es describir cómo se compila un fragmento de código existente que usa otros sistemas de compilación. Este suele ser el caso de las dependencias de terceros que no son específicas de Android, como OpenSSL y libbzip2.

Los encargados de mantener sistemas de compilación que buscan agregar compatibilidad nativa con el NDK a sus sistemas de compilación deberían leer la Guía para encargados de mantener sistemas de compilación.

Descripción general

A partir del NDK r19, las cadenas de herramientas instaladas de forma predeterminada con el NDK se pueden usar de forma local. Ya no se necesita la secuencia de comandos make_standalone_toolchain.py para interactuar con sistemas de compilación arbitrarios.

Para asegurarte de compilar la arquitectura correcta, pasa el destino adecuado con -target cuando invoques a Clang, o invoca a Clang con destino prefijado. Por ejemplo, a fin de realizar una compilación para ARM de 64 bits de Android con un minSdkVersion de 21, funcionará cualquiera de las siguientes opciones y podrás usar la que consideres más conveniente:

$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/clang++ \
        -target aarch64-linux-android21 foo.cpp
    
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/aarch64-linux-android21-clang++ \
        foo.cpp
    

En ambos casos, reemplaza $NDK por la ruta de acceso al NDK y $HOST_TAG para que coincida con el NDK que descargaste según la tabla que se incluye a continuación:

Variante del SO del NDK Etiqueta de host
macOS darwin-x86_64
Linux linux-x86_64
Windows de 32 bits windows
Windows de 64 bits windows-x86_64

En este caso, el formato del prefijo o argumento de destino es triple, con un sufijo que indica minSdkVersion. Este sufijo solo se usa con clang o clang++; las herramientas binutils (como ar y strip) no requieren sufijo porque minSdkVersion no las afecta. Los triples destinos de Android son los siguientes:

ABI Triple
armeabi-v7a armv7a-linux-androideabi
arm64-v8a aarch64-linux-android
x86 i686-linux-android
x86-64 x86_64-linux-android

Las secuencias de comandos de compilación de muchos proyectos esperan compiladores cruzados al estilo GCC, en los que cada compilador se orienta solo a una combinación de SO y arquitectura, por lo que es posible que no controlen a -target de manera correcta. En estos casos, es mejor usar los objetos binarios de Clang con prefijo triple.

Autoconf

Los proyectos de Autoconf permiten especificar la cadena de herramientas para usar con las variables de entorno. Por ejemplo, a continuación, se muestra cómo compilar libpng para Android x86-64 con un minSdkVersion de API nivel 21 en Linux.

# Check out the source.
    git clone https://github.com/glennrp/libpng
    cd libpng
    # Only choose one of these, depending on your build machine...
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
    # Only choose one of these, depending on your device...
    export TARGET=aarch64-linux-android
    export TARGET=armv7a-linux-androideabi
    export TARGET=i686-linux-android
    export TARGET=x86_64-linux-android
    # Set this to your minSdkVersion.
    export API=21
    # Configure and build.
    export AR=$TOOLCHAIN/bin/$TARGET-ar
    export AS=$TOOLCHAIN/bin/$TARGET-as
    export CC=$TOOLCHAIN/bin/$TARGET$API-clang
    export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
    export LD=$TOOLCHAIN/bin/$TARGET-ld
    export RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
    export STRIP=$TOOLCHAIN/bin/$TARGET-strip
    ./configure --host $TARGET
    make
    

Proyectos Make que no son de Autoconf

Algunos proyectos con archivos Make permiten compilación cruzada, ya que anulan las mismas variables que anularías tú en un proyecto de Autoconf. A continuación, se muestra cómo compilar libbzip2 para Android x86-64 con un minSdkVersion de 21.

# Check out the source.
    git clone https://gitlab.com/bzip/bzip2.git
    cd bzip2

    # Only choose one of these, depending on your build machine...
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
    export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64

    # Only choose one of these, depending on your device...
    export TARGET=aarch64-linux-android
    export TARGET=armv7a-linux-androideabi
    export TARGET=i686-linux-android
    export TARGET=x86_64-linux-android

    # Set this to your minSdkVersion.
    export API=21

    # Build.
    make \
        CC=$TOOLCHAIN/bin/$TARGET$API-clang \
        AR=$TOOLCHAIN/bin/$TARGET-ar \
        RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib \
        bzip2