Android linker: undefined link to bsd_signal

I run gradlew to compile an Android application having a static lib dependency. For some reason, I have an undefined link to bsd_signal .

I managed to compile this application with gradle 1.X, but I had to switch to gradle 2.10 and leave my Android.mk file in favor of adding more build instructions to my gradle.build , and this is the problem.

Can someone tell me if there is a library that defines bsd_signal which I should link to my project?

Compiler output

 Starting process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++''. Working directory: /home/myself/projects/DroidEar/app Command: /home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ @/home/myself/projects/DroidEar/app/build/tmp/linkNativeArmeabi-v7aDebugSharedLibrary/options.txt Successfully started process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++'' /android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal' /android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal' collect2: error: ld returned 1 exit status 

TMI: Here is my gradle.build file

 apply plugin: 'com.android.model.application' model { repositories { libs(PrebuiltLibraries) { Superpowered { binaries.withType(StaticLibraryBinary) { def prefix = "src/main/jniLibs/Superpowered" headers.srcDir "${prefix}" if (targetPlatform.getName() == "armeabi-v7a") staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM.a") else if (targetPlatform.getName() == "arm64-v8a") staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM64.a") else if (targetPlatform.getName() == "x86_64") staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86_64.a") else if (targetPlatform.getName() == "X86") staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86.a") } } } } android { compileSdkVersion = 23 buildToolsVersion = "23.0.3" sources { main { jni { dependencies { library "Superpowered" linkage "static" } } } } ndk { ldLibs.addAll(['log', 'android', 'c']) } defaultConfig { applicationId = "edu.ucdavis.auditoryenhancer" minSdkVersion.apiLevel = 22 targetSdkVersion.apiLevel = 23 versionCode = 1 versionName = "1.0" } } android.ndk { moduleName = "native" } android.buildTypes { release { minifyEnabled = false proguardFiles.add(file("proguard-rules.pro")) } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' } 

It seems to me that bsd_signal is defined in the signal.o component of platforms/android-9/arch-x86/usr/lib/libc.a , but even with my call to ldLibs , including c , I get an error.

+6
source share
2 answers

Prior to Android-19 inclusive of NDK-s signal.h declared bsd_signal extern and signal was a built-in call to bsd_signal .

Starting with android-21, the signal is extern, and bsd_signal not declared at all.

Interestingly, bsd_signal is still available as a character in the NDK r10e android-21 libc.so (so when using r10e there were no binding errors) but it is not available in NDK r11 and higher.

Removing bsd_signal from NDK-s android-21 + libc.so results in error binding if the code built with android-21 + is linked to static libs built with a lower level of NDK that cause signal or bsd_signal . The most popular library that calls signal is OpenSSL .

WARNING : creating these static libraries with android-21 + (which would put the signal symbol directly) will bind a penalty, but will result in a *.so error for loading on older Android OS devices due to the signal symbol was not found in their libc.so .

Therefore, it is best to stick with <= android-19 for any code that calls signal or bsd_signal .

To link the library created using <android-21 , I declared a bsd_signal wrapper that will call bsd_signal from libc.so (it is still available on the libc.so device, even before Android 7.0).

 #if (__ANDROID_API__ > 19) #include <android/api-level.h> #include <android/log.h> #include <signal.h> #include <dlfcn.h> extern "C" { typedef __sighandler_t (*bsd_signal_func_t)(int, __sighandler_t); bsd_signal_func_t bsd_signal_func = NULL; __sighandler_t bsd_signal(int s, __sighandler_t f) { if (bsd_signal_func == NULL) { // For now (up to Android 7.0) this is always available bsd_signal_func = (bsd_signal_func_t) dlsym(RTLD_DEFAULT, "bsd_signal"); if (bsd_signal_func == NULL) { // You may try dlsym(RTLD_DEFAULT, "signal") or dlsym(RTLD_NEXT, "signal") here // Make sure you add a comment here in StackOverflow // if you find a device that doesn't have "bsd_signal" in its libc.so!!! __android_log_assert("", "bsd_signal_wrapper", "bsd_signal symbol not found!"); } } return bsd_signal_func(s, f); } } #endif 

PS. It looks like the bsd_signal character will be returned to libc.so in NDK r13 :

https://github.com/android-ndk/ndk/issues/160#issuecomment-236295994

+13
source

This is an ABI anomaly in Android NDK. Libraries / binaries created using the NDK signal with the preliminary android-21 using the signal () will not work with android-21 or newer. And vice versa. This Rust ticket has a more detailed explanation: https://github.com/rust-lang/libc/issues/236#issuecomment-198774409

There is also this Android NDK ticket: https://github.com/android-ndk/ndk/issues/48

+1
source

All Articles