La adopción de bibliotecas de 64 bits es esencial para aplicaciones Android modernas, especialmente con procesadores ARM64 dominantes en dispositivos móviles y sistemas de seguridad. Si un proyecto depende de bibliotecas de 32 bits, la transición puede ser compleja, pero es necesaria cuando se integran proveedores que solo ofrecen versiones de 64 bits.
Entorno de compilación requerido
Para compilar bibliotecas de 64 bits para Android, se necesita un sistema operativo como Ubuntu, el NDK (Android Native Development Kit) descargado y configurado, y el código fuente de las bibliotecas. Se recomienda usar versiones estables del NDK para evitar problemas inesperados durante la compilación.
Ejemplo: Compilación de OpenSSL para ARM64
A continuación, se ilustra el proceso usando OpenSSL como caso de estudio, con pasos modificados para reducir similitudes con guías comunes.
Paso 1: Obtención y preparación del código fuente
Clonar el repositorio de OpenSSL desde su fuente oficial y descomprimir el contenido en un directorio de trabajo.
Paso 2: Configuración de opciones de compilación
La configuración inicial puede generar bibliotecas enlazadas incorrectamente para Android. Por ejemplo, al ejecutar un comando simple, se obtiene una biblioteca enlazada a librerías del sistema host, lo cual no es compatible con Android.
# Ejemplo de configuración incorrecta para Android
./Configure linux-aarch64 --cross-compile-prefix=aarch64-linux-gnu-
Para corregir esto, se deben usar herramientas del NDK y rutas específicas de Android. El comando revisado incluye flags para cabeceras y enlaces al NDK:
# Configuración corregida usando NDK
CPPFLAGS="-I$NDK_PATH/platforms/android-21/arch-arm64/usr/include" \
LDFLAGS="-Wl,-rpath-link=$NDK_PATH/platforms/android-21/arch-arm64/usr/lib -L$NDK_PATH/platforms/android-21/arch-arm64/usr/lib" \
LIBS="-ldl" \
./Configure linux-aarch64 \
--cross-compile-prefix=$NDK_PATH/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android- \
--prefix=/ruta/de/salida no-asm shared no-async
Aquí, $NDK_PATH es la ruta del NDK, y se han ajustado los parámetros para apuntar a las bibliotecas Android. Esto asegura que la biblioteca enlace contra el sistema Android en lugar del host.
Paso 3: Resolución de errores de compilación
Durante la compilación, pueden surgir errores como referencias indefinidas a funciones estándar. Esto a menudo se debe a flags de compilación incorrectos. Por ejemplo, remover -nostdlib y evitar definiciones innecesarias como -D__ANDROID_API__=21 puede resolver estos problemas. Las soluciones típicas implican verificar rutas de cabeceras, enlaces de bibliotecas y opciones de compilación adicionales.
Paso 4: Ajuste de nombres de bibliotecas
Las bibliotecas generadas pueden tener nombres con versiones (por ejemplo, libssl.so.3), que Android no reconoce. Para solucionar esto, se modifica el Makefile para eliminar versiones en los nombres y en el campo SONAME. Por ejemplo, cambiar referencias de libcrypto.so.3 a libcrypto.so en el archivo Makefile garantiza compatibilidad.
# Fragmento modificado del Makefile
SHLIBS=libcrypto.so libssl.so
# En la regla de enlace, ajustar el soname
$(CC) $(LIB_CFLAGS) -L. $(LIB_LDFLAGS) -Wl,-soname=libssl.so -o libssl.so ...
Posteriormente, verificar con herramientas como readelf que el SONAME sea correcto (por ejemplo, libssl.so sin versión).
Compilación de curl para Android ARM64
Para bibliotecas como curl, el proceso es similar. Se configura con flags específicos del NDK y se deshabilitan módulos innecesarios para reducir el tamaño. Un ejemplo de comando es:
# Configuración de curl con NDK y OpenSSL compilado previamente
CC=$NDK_PATH/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc \
./configure --target=aarch64-linux-gnu --host=aarch64-linux-gnu \
--enable-shared --without-nss --disable-dict --disable-ftp \
--with-ssl=/ruta/a/openssl/out ...
Además, para generar bibliotecas sin versiones, se edita el archivo configure para modificar las reglas de nombres de bibliotecas, estableciendo soname_spec vacío y ajustando library_names_spec.
Ejemplos adicionales: Otras bibliotecas
SQLite3
Compilar SQLite3 involucra usar el compilador del NDK directamente con flags de enlace. Un comando típico incluye:
# Compilación de libsqlite3.so
$NDK_PATH/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc \
-shared -fPIC -I$NDK_PATH/platforms/android-21/arch-arm64/usr/include \
-L$NDK_PATH/platforms/android-21/arch-arm64/usr/lib \
sqlite3.c -lz -lm -ldl -Wl,-soname,libsqlite3.so -o libsqlite3.so
libevent
Para libevent, se usa configure con el compilador del NDK y se ajustan las reglas de nombres en archivos de configuración. Es crucial modificar secciones específicas en configure para evitar versiones en los nombres de bibliotecas, similar al enfoque con curl.
libspeex y libsrtp
Estas bibliotecas siguen patrones análogos: configurar con el compilador ARM64 del NDK, establecer rutas de inclusión y enlace, y en el caso de libsrtp, generar bibliotecas dinámicas explícitamente mediante comandos como make libsrtp2.so.
Solución a problemas comunes
Los errores de compilación frecuentes incluyen cabeceras no encontradas, enlaces faltantes o configuraciones incorrectas. Se recomienda: primero, validar rutas de cabeceras y bibliotecas; segundo, revisar flags de compilación como -nostdlib o definiciones de API; tercero, para problemas específicos, consultar recursos comunitarios ya que muchos desafíos son conocidos en la compilación cruzada para Android.