Android linker: undefined reference to bsd_signal

匿名 (未验证) 提交于 2019-12-03 02:17:01

问题:

I'm running gradlew to compile an Android app that has a static lib dependency. Somehow, I have an undefined reference to bsd_signal.

I was able to compile this app with gradle 1.X, but I've been obliged to switch to gradle 2.10 and to drop my Android.mk file in favour of putting more build instruction into my gradle.build file, and this is where the trouble arises.

Can anyone tell me whether 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 looks to me like bsd_signal is defined in the signal.o component of platforms/android-9/arch-x86/usr/lib/libc.a, but even with my ldLibs call above including c, I get the error.

回答1:

Till android-19 inclusive NDK-s signal.h declared bsd_signal extern and signal was an inline calling bsd_signal.

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

What's interesting, bsd_signal was still available as a symbol in NDK r10e android-21 libc.so (so there were no linking errors if using r10e), but is not available in NDK r11 and up.

Removing of bsd_signal from NDK-s android-21+ libc.so results in linking errors if code built with android-21+ is linked with static libs built with lower NDK levels that call signal or bsd_signal. Most popular library which calls signal is OpenSSL.

WARNING: Building those static libs with android-21+ (which would put signal symbol directly) would link fine, but would result in *.so failing to load on older Android OS devices due to signal symbol not found in theirs libc.so.

Therefore it's better to stick with <=android-19 for any code that calls signal or bsd_signal.

To link a library built with <android-21 I ended up declaring a bsd_signal wrapper which would call bsd_signal from libc.so (it's still available in device's libc.so, even up to 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. Looks like the bsd_signal symbol will be brought back to libc.so in NDK r13:

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



回答2:

This is ABI breakage in the Android NDK. Libraries/binaries built with a pre-android-21 NDK using signal() won't work with android-21 or newer. And the other way around. This Rust ticket has a more detailed explanation: https://github.com/rust-lang/libc/issues/236#issuecomment-198774409

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



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!