Android链接器:对bsd_信号的未定义引用
我正在运行Android链接器:对bsd_信号的未定义引用,android,android-ndk,static-libraries,build.gradle,Android,Android Ndk,Static Libraries,Build.gradle,我正在运行gradlew来编译一个具有静态lib依赖项的Android应用程序。不知何故,我对bsd\U信号有一个未定义的引用 我能够用gradle 1.X编译这个应用程序,但我不得不切换到gradle 2.10,并放弃我的Android.mk文件,转而在我的gradle.build文件中加入更多的构建指令,这就是问题所在 有谁能告诉我是否有一个定义bsd\U信号的库,我应该链接到我的项目 编译器输出 Starting process 'command '/home/myself/Android
gradlew
来编译一个具有静态lib依赖项的Android应用程序。不知何故,我对bsd\U信号有一个未定义的引用
我能够用gradle 1.X编译这个应用程序,但我不得不切换到gradle 2.10,并放弃我的Android.mk
文件,转而在我的gradle.build
文件中加入更多的构建指令,这就是问题所在
有谁能告诉我是否有一个定义bsd\U信号的库,我应该链接到我的项目
编译器输出
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\u信号
是在platforms/android-9/arch-x86/usr/lib/libc.a的signal.o
组件中定义的,但即使我上面的ldLibs
调用包括c
,我也会得到错误。这是android NDK中的ABI破坏。使用signal()使用android-21之前的NDK构建的库/二进制文件无法与android-21或更高版本一起使用。反过来说。这张铁锈票有更详细的解释:
还有这张安卓NDK的票:直到Android-19包括NDK-ssignal.h
声明了bsd\U信号
extern和signal
是一个内联呼叫bsd\U信号
以android-21signal
开头是一个extern,bsd\u signal
根本没有声明
有趣的是,bsd_信号
在NDK r10e android-21libc中仍然可以作为符号使用。因此
(因此使用r10e时没有链接错误),但在NDK r11及以上版本中不可用
从NDK-sandroid-21+libc中删除bsd\u信号
。因此,如果使用android-21+构建的代码与调用信号或bsd\u信号的较低NDK级别构建的静态libs链接,则
会导致链接错误。最流行的调用信号的库是OpenSSL
警告:使用android-21+构建那些静态LIB(将直接放置信号
符号)将链接正常,但会导致*。因此
无法加载到较旧的android操作系统设备上,因为信号
符号未在它们的libc中找到。因此
因此,最好还是坚持使用,而且可能需要使用此标题#ifdef uuuuuuuu安卓uuu#include#include#include##endif@AntonPechenko是的,当然,让我们把它们放在我答案的代码中。如果找不到bsd_信号,那么尝试通过dlsym加载信号是否有意义,因为其中一个信号总是可用的?据我所知,在Android 7.0之前,bsd_信号已经在设备的libc.so中被发现,并且bsd_信号将在r13中恢复,但由于Android设备种类繁多,这似乎是一种合理的保护措施。会有任何负面后果吗?我不认为会有任何负面后果,我以前在代码注释中把它作为一个建议,tbh我在我的生产代码中有它以防将来。我唯一不喜欢的是,我在代码上测试了“信号”在Android 6.0和7.0设备上,使用RTLD_默认值获取的地址与从dlopen(“libc.so”)返回的句柄获取的地址不同。RTLD_接下来也有同样的问题。因此,在我的生产代码中,我从RTLD_NEXT获取“信号”。当然,我可以使用dlopen来确保获得正确的“信号”符号,但我希望我的代码尽可能干净,而无需在关闭应用程序时在某处调用dlclose以减少引用计数器。不过,我不是POSIX/Linux专家,而且我非常确信,在没有dlclose的情况下,杀死该应用程序不会造成任何泄漏。总而言之:这只是我的学究气;)
#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