cómo usar mkfifo usando el NDK de Android
android-ndk (2)
Esto sucede si compila contra los encabezados de la plataforma
android-21
.
Establezca
APP_PLATFORM
en
jni/Application.mk
a una versión anterior, para compilar utilizando los encabezados antiguos, para asegurarse de que solo enlace a funciones disponibles anteriormente.
(Antes de
android-21
, las características y los encabezados de la biblioteca C realmente no cambiaban significativamente, por lo que para las funciones normales de la biblioteca C, no importa si compila el objetivo
android-3
o
android-20
).
Esto se ha informado y es un comportamiento intencional, consulte, por ejemplo, https://code.google.com/p/android/issues/detail?id=73725 .
Si no necesita usar las nuevas funciones de
android-21
, simplemente construya usando encabezados más antiguos.
(No importa que esté apuntando a una versión de plataforma anterior si desea intentar compilar, por ejemplo, para
arm64-v8a
o
x86_64
que no existía antes;
ndk-build
construiría las partes de 32 bits utilizando el objetivo anterior, y los de 64 bits que usan el objetivo más antiguo que los admite).
En caso de que desee intentar usar las nuevas funciones de la plataforma
android-21
condicionalmente si se ejecuta en dicha plataforma, es probable que necesite usar
dlopen
y
dlsym
para cargarla de manera condicional de todos modos, por lo que debe duplicar las otras definiciones de la nueva encabezados también, para permitirle construir usando los encabezados de plataforma más antiguos.
Recientemente actualicé el NDK y ahora mi aplicación falla con el símbolo
mkfifo
faltante:
E/dalvikvm(2031): dlopen("/data/app-lib/...mylib.so") failed: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol "mkfifo" referenced by "mylib.so"...
Las plataformas más antiguas mkfifo se definieron en línea en
sys/stat.h
static __inline__ int mkfifo(const char *__p, mode_t __m) {
return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t)0);
}
Pero en la versión 21 de la plataforma se cambió a solo una declinación externa:
extern int mkfifo(const char*, mode_t);
Eso explica la excepción del símbolo que falta ... mi pregunta es ¿cómo lo soluciono?
He intentado la solución de mstorsjo y parece funcionar, sin embargo, estaba un poco preocupado de que desde el enlace que publicó parece que Google realmente no cree que sea una buena idea. Como resultado, investigué un poco más y parece que la solución ''adecuada'' es enviar múltiples APK, con (al menos) un objetivo para Android-20 y menos, y otro dirigido a Android-21 y más.
El problema surge de un cambio en el NDK para forzar el uso de la opción ''fPIE'' al realizar una compilación de NDK. De las notas de lanzamiento de NDK 10d :
Se introdujo el requisito, a partir del nivel 21 de API, para usar -fPIE -pie al compilar. En los niveles API 16 y superiores, ndk-build usa PIE al compilar. Este cambio tiene una serie de implicaciones, que se discuten en Developer Preview Issue 888. Estas implicaciones no se aplican a las bibliotecas compartidas.
Si mira el Problema 888 de la Vista previa del desarrollador , indica lo siguiente:
Bionic commit 76e289c026f y su predecesor, 2aebf5429bb, requieren que todos los ejecutables nativos vinculados dinámicamente se construyan con -fPIE -pie. Esto tiene una serie de efectos secundarios posiblemente no deseados, que incluyen:
Las aplicaciones antiguas / sin mantenimiento que funcionaban correctamente en KitKat ahora pueden fallar al ejecutarse en "L". Esto podría afectar incluso a aplicaciones simples que no usan la red, manejan datos no confiables o se dirigen a la nueva API de SDK "L".
Las aplicaciones mantenidas activamente que deseen apuntar a "L" deben enviar ejecutables PIE o ejecutables estáticos. Si una aplicación quiere apuntar a ICS o inferior, también debe enviar ejecutables no PIE o ejecutables estáticos. Incluso un simple programa "Hello world" creado con -fPIE -pie se convertirá en ICS y GB por defecto.
Obviamente, puede preferir ir con la solución anterior, pero pensé que valía la pena señalar.