Android 链接器:未定义对 bsd_signal 的引用 [英] Android linker: undefined reference to bsd_signal

查看:58
本文介绍了Android 链接器:未定义对 bsd_signal 的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行 gradlew 来编译具有静态库依赖项的 Android 应用程序.不知何故,我对 bsd_signal 有一个未定义的引用.

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

我能够使用 gradle 1.X 编译这个应用程序,但我不得不切换到 gradle 2.10 并删除我的 Android.mk 文件,以便将更多构建指令放入其中我的 gradle.build 文件,这就是问题所在.

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.

谁能告诉我是否有一个定义bsd_signal的库,我应该链接到我的项目?

Can anyone tell me whether there is a library that defines bsd_signal, which I should link to my project?

编译器输出

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:这是我的 gradle.build 文件

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'
}

在我看来,bsd_signal 是在 platforms/android-9/arch-x86/usr/lib/libc 的 signal.o 组件中定义的.a,但即使上面的 ldLibs 调用包括 c,我也会收到错误消息.

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.

推荐答案

直到 android-19 包含 NDK-s signal.h 声明 bsd_signal externsignal 是一个 inline 调用 bsd_signal.

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

android-21开头的signal是一个extern,而bsd_signal根本没有被声明.

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

有趣的是,bsd_signalNDK r10e android-21 libc.so 中仍然可以作为符号使用(因此没有链接错误如果使用 r10e),但在 NDK r11 及更高版本中不可用.

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.

从 NDK-s android-21+ libc.so 中删除 bsd_signal 如果代码使用 android 构建,则会导致链接错误-21+ 与使用较低 NDK 级别构建的静态库链接,这些库调用 signalbsd_signal.调用 signal 的最流行的库是 OpenSSL.

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.

警告:使用 android-21+ 构建那些静态库(将直接放置 signal 符号)将链接正常,但会导致在 *.so 中,由于在他们的 libc.so 中找不到 signal 符号,因此无法在较旧的 Android OS 设备上加载.

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.

因此,对于任何调用 signalbsd_signal 的代码,最好坚持使用 <=android-19.

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

要链接使用 <android-21 构建的库,我最终声明了一个 bsd_signal 包装器,该包装器将从 调用 bsd_signallibc.so(它仍然可以在设备的 libc.so 中使用,甚至到 Android 7.0).

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.看起来 bsd_signal 符号将被带回 NDK r13 中的 libc.so:

PS. Looks like the bsd_signal symbol will be brought back to libc.so in NDK r13:

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

这篇关于Android 链接器:未定义对 bsd_signal 的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆