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.
Till android-19 inclusive NDK-s
signal.h
declaredbsd_signal
extern andsignal
was an inline callingbsd_signal
.Starting with android-21
signal
is an extern andbsd_signal
is not declared at all.What's interesting,
bsd_signal
was still available as a symbol in NDK r10e android-21libc.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 callsignal
orbsd_signal
. Most popular library which callssignal
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 tosignal
symbol not found in theirslibc.so
.Therefore it's better to stick with <=android-19 for any code that calls
signal
orbsd_signal
.To link a library built with <android-21 I ended up declaring a
bsd_signal
wrapper which would callbsd_signal
fromlibc.so
(it's still available in device'slibc.so
, even up to Android 7.0).PS. Looks like the
bsd_signal
symbol will be brought back tolibc.so
in NDK r13:https://github.com/android-ndk/ndk/issues/160#issuecomment-236295994
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