3

I'm using two different custom aar libraries in two separate modules in my application. Libraries are coming with many of ".so" files - like "libc++_shared.so" etc. After including both of them I getting errors like this:

2 files found with path 'lib/arm64-v8a/libc++_shared.so' from inputs

So I used:

packagingOptions {
      pickFirst 
}

Unfortunately it's not a good solution in my case as now after running the application I'm getting:

  java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "vpx_codec_enc_config_default" referenced by "[...]/base.apk!/lib/arm64-v8a/libmediaengine.so"...

Is there any solution that I could use two the same .so files in different modules in different versions?

voximdo
  • 53
  • 2
  • 14
  • Could you update question with how the dependencies list in two modules? I assume final application pack both modules in same apk? – ddassa Jan 09 '23 at 13:17
  • @ddassa - yes, both modules are packed into the same apk. I'm using "implementation project(":myprojectname")" in my gradle from application. – voximdo Jan 09 '23 at 14:45
  • I see that the problem lays in libgnustl_shared.so - two libraries are using differnet version of this file. Any idea how I can combine this? – voximdo Jan 09 '23 at 18:23
  • I might be able to help you, but recently android studio has changed a lot along with gradle and it all depends on which version of gradle and android studio. What versions you use? – ddassa Jan 10 '23 at 11:12
  • I am afraid your new problem is not related to the first. The clash of c++ runtime libraries prevented your app from even looking for the `vpx_codec_enc_config_default` symbol. You seem to be missing **libvpx** library. Which bundle includes **libmediaengine.so**? – Alex Cohn Jan 15 '23 at 08:04
  • Symbolic links are names that reference other files. GNU find will handle symbolic links in one of two ways; Check for symbolic links. – Nadeem Taj Jan 16 '23 at 04:36
  • Also refer to https://stackoverflow.com/questions/27338318/cannot-load-library-reloc-library1285-cannot-locate-rand – Nadeem Taj Jan 16 '23 at 05:33

3 Answers3

0

When you include two different custom aar libraries in your application that contain the same .so files, you may run into issues where the linker can't decide which version of the .so file to use. One solution to this problem is to use different names for the .so files in each library, such as libc++_shared_v1.so and libc++_shared_v2.so. This way, the linker will know which version of the .so file to use for each library.

Another solution is to use different build types or flavors for your application. This way you can include different versions of the .so files for each build type or flavor. For example, you can have a debug build type that uses the first library and a release build type that uses the second library.

You can also use a custom linker script to specify which version of the .so file to use. This script can be used to override the default linker behavior, and you can use it to specify which version of the .so file to use for each library.

It's worth mentioning that using the solution of a custom linker script is not always easy and it requires some experience with android NDK and JNI, and it's important to be familiar with the android build process before attempting this solution.

In summary, there are multiple solutions to use different versions of the same .so files in different modules in android. It depends on your use case and the complexity of the solution that you are willing to implement.

Arbaz Pirwani
  • 935
  • 7
  • 22
0

Take as a starting point the Android Dev Docs on how to use native dependencies with the Android Gradle plugin. Also of interest, though not primarily aiming at native dependencies, are the chapters on how to fix dependency resolution errors and on applying custom build logic.

So, lets take a look at your specific problems.

Duplicate File Conflict

You habe two libc++_shared.so files, with identical name and path. The Android Dev Docs (see above) suggest:

To resolve this issue, remove one of the binary dependencies

Note, that you actually did that by using pickFirst and that your problem with libc++_shared.so has been solved and shifted to another library. But pickFirst as such unluckily affected the further decisions of Gradle.

So change your packagingOptions to pick first a specific file with pickFirst 'lib/arm64-v8a/libc++_shared.so'. Alternatively you can use exclude 'lib/arm64-v8a/libc++_shared.so', which semantically excludes further (duplicate) files of that name after it has been added to your APK.

Strictly speaking exclude and pickFirst are now deprecated. If I'm not mistaken it's now resources.excludes and resources.pickFirsts, used as:

packagingOptions {
    resources.excludes += 'foo'
    resources.excludes += 'bar'

    // or:
    // resources.excludes += setOf(
    //     'foo',
    //     'bar'
    // )
  }

Version Conflicts

You mentioned that

I see that the problem lays in libgnustl_shared.so - two libraries are using different versions of this file.

Commonly it's the proper choice to use the more up-to-date library version, therefore:

To resolve this conflict, the Android Gradle plugin uses the following dependency resolution strategy: when the plugin detects that different versions of the same module are in the dependency graph, by default, it chooses the one with the highest version number.

Usually, that's it and the problem is resolved automatically. I suspect, that you overwrote that behaviour by using pickFirst without naming a concrete file, such applying it to everything.

In case you whyever need both versions, you'll have to treat them as different libraries and rename them, so e.g. libfoo.so.1.1 and libfoo.so.1.2 become libfoo1.so and libfoo2.so or something.

And, of course, check whether you provide all necessary dependencies.


I hope that will help you.

Krokomot
  • 3,208
  • 2
  • 4
  • 20
0

There are two approaches to resolving this issue.

  1. Make sure both modules are built with the same version of NDK. Then the libc++_shared.so would be the same for both modules, and you can pickFirst.

  2. Another option is to build one module with ANDROID_STL=c++_static, then it will not produce libc++_shared.so and hence no conflicts.

Thanks to Jianming Li, my previous colleague, for giving me the above two solutions when I encountered this problem. For my case, we used the 2nd approach to solve the problem.

jhuai
  • 67
  • 1
  • 4