cómo usar mkfifo usando el NDK de Android

Recientemente actualicé el NDK y ahora mi aplicación se bloquea con el símbolo mkfifo falta:

 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 plataforma versión 21 se cambió a una statement externa:

 extern int mkfifo(const char*, mode_t); 

Entonces eso explica la excepción de símbolo faltante … mi pregunta es ¿cómo lo arreglo?

Esto sucede si comstack contra los encabezados de la plataforma android-21 . Establezca APP_PLATFORM en jni/Application.mk en una versión anterior, para comstackr con los encabezados anteriores, para asegurarse de que solo enlaza a las funciones disponibles anteriormente.

(Antes de android-21 , las características y encabezados de la biblioteca C realmente no cambiaban significativamente, por lo que para las funciones normales de la biblioteca C, no importa si comstack la segmentación 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 nuevas características de android-21 , solo cree usando encabezados anteriores. (No importa que esté apuntando a una versión de plataforma anterior si quiere intentar construir, por ejemplo, arm64-v8a o x86_64 que no existía antes; ndk-build crearía las partes de 32 bits utilizando el objective anterior, y los de 64 bits que usan el objective más antiguo que los admite).

En caso de que desee intentar utilizar nuevas funciones desde la plataforma android-21 condicionalmente si se ejecuta en dicha plataforma, probablemente necesite usar dlopen y dlsym para cargarlo de manera condicional de todos modos, entonces debe duplicar las otras definiciones del nuevo encabezados también, para permitirle construir usando los encabezados de plataforma más antiguos.

Probé la solución de mstorsjo y parece funcionar, sin embargo, estaba un poco preocupado de que, a partir del enlace que publicó, parece que Google no cree que sea una buena idea. Como resultado, investigué un poco más y parece que la solución “adecuada” es enviar varios archivos APK, con (al menos) un objective para android-20 y de abajo, y otro de orientación para android-21 y superior.

El problema surge de un cambio en el NDK para forzar el uso de la opción ‘fPIE’ cuando se realiza una comstackción NDK. De las notas de la versión de NDK 10d :

Introdujo el requisito, a partir del nivel API 21, para usar -fPIE -pie al comstackr. En los niveles API 16 y superiores, ndk-build usa PIE al construir. Este cambio tiene una serie de implicaciones, que se analizan en Developer Preview Issue 888. Estas implicaciones no se aplican a las bibliotecas compartidas.

Si nos fijamos en Developer Preview Issue 888 , indica lo siguiente:

Bionic commit 76e289c026f y su predecesor, 2aebf5429bb, requieren que todos los ejecutables nativos dinámicamente enlazados se creen con -fPIE -pie. Esto tiene una serie de efectos secundarios posiblemente no deseados, que incluyen:

  • Las aplicaciones antiguas / sin mantenimiento que funcionaban correctamente con KitKat ahora pueden fallar al ejecutar en “L”. Esto podría afectar incluso las aplicaciones simples que no usan la red, manejan datos que no son de confianza o se dirigen a la nueva API SDK “L”.

  • Las aplicaciones mantenidas de forma activa que deseen apuntar a “L” deben enviar ejecutables PIE o ejecutables estáticos. Si una aplicación desea apuntar a ICS o más abajo, también debe enviar ejecutables que no sean PIE o ejecutables estáticos. Incluso un simple progtwig “Hello world” creado con -fPIE -pie segfault en ICS y GB.

Obviamente, es posible que prefiera ir con la solución anterior, pero pensé que valía la pena señalarlo.