I have a question about the gradle build system. I have a library (for React Native) which depends on OpenSSL, I have declared my dependency as such:
dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-android:+'
implementation 'com.android.ndk.thirdparty:openssl:1.1.1q-beta-1'
}
If my library is the only one in the build process that uses this dependency, then everything compiles fine. However, if another library also depends on openssl, it will also generate it's own libcrypto.so
and then the build process fails with duplicated symbols:
Execution failed for task ':app:mergeDebugNativeLibs'.
A failure occurred while executing com.android.build.gradle.internal.tasks.MergeNativeLibsTask$MergeNativeLibsTaskWorkAction
2 files found with path 'lib/arm64-v8a/libcrypto.so' from inputs:
- D:\Project\sqlst\node_modules@op-engineering\op-sqlcipher\android\build\intermediates\library_jni\debug\jni\arm64-v8a\libcrypto.so
- C:\Users\shiroze\.gradle\caches\transforms-3\e13f88164840fe641a466d05cd8edac7\transformed\jetified-flipper-0.182.0\jni\arm64-v8a\libcrypto.so
If you are using jniLibs and CMake IMPORTED targets, see
developer.android.com/r/tools/jniLibs-vs-imported-targets
One solution is to add the libcrypto.so
from my library to the exclude list, but this means if there is no other library that generates the .so, then it will be missing from the runtime and the app will crash.
packagingOptions {
doNotStrip resolveBuildType() == 'debug' ? "**/**/*.so" : ''
excludes = [
"META-INF",
"META-INF/**",
"**/libjsi.so",
"**/libreact_nativemodule_core.so",
"**/libturbomodulejsijni.so",
"**/libc++_shared.so",
"**/libfbjni.so",
"**/libcrypto.so"
]
}
The other options is to use pickFirst
function:
pickFirst '**/x86/libcrypto.so'
pickFirst '**/x86_64/libcrypto.so'
pickFirst '**/armeabi-v7a/libcrypto.so'
pickFirst '**/arm64-v8a/libcrypto.so'
But from what I understand, this just tells the compiler, just pick the first one that appears when linking the library. What if it picks an incorrect version from another dependency and there are missing symbols or incorrect function signatures.
Just trying to understand what is going on here and if there is any way to guarantee my library will be correctly linked. Thanks a lot!
It seems there is no good answer here, basically the only strategies Gradle provides are forcing a single version onto all dependencies.
You can find a short resume of the strategies here:
https://ospfranco.com/how-to-resolve-duplicated-libraries-on-android/