如何在 android 应用程序中的 cmake 中使用两个预构建的相互依赖的共享库

How to use two prebuilt interdependent shared libraries in cmake in android Application

我想在我的 android 应用程序中包含两个共享库 liba.solibb.so。其中 libb.so 的函数是从 liba.so 中的函数调用的。

我有一个 Java class 调用本机 JNI 函数,

 package com.test.myapplication;

    public class MainActivity extends AppCompatActivity {

    static{
      System.loadLibrary(a);
      System.loadLibrary(b);
    }
    public native void testSample();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      testSample();
    }
  }

我的 JNI 文件是

#include"a.h"

extern "C" void JNICALL Java_com_test_myapplication_MainActivity_testSample( JNIEnv* env, jobject thiz) {
    a_foo();
}

a.cpp 属于我的库 liba.so 的文件是

#include"b.h"
void a_foo()
    {
         /* ..... code .....*/
         b_foo();
         /* ..... code .....*/
    }

我的 b.cpp 是 libb.so 的一部分

void b_foo()
    {
         /* ..... code .....*/
    }

我想将 liba.so 和 libb.so 作为库而不是源包含在我的应用程序中。这两个库都是使用 android-ndk 独立构建的。

我假设你已经弄清楚了 Java/Android 部分,因为我已经很多年没有做过任何 Java 或 Android 了(甚至在那时是大学水平)。如果您不这样做,我刚刚阅读了一篇关于 JNI 的 short post,它让我大致了解了实际需要发生什么才能使 Java 代码正常工作。

您需要从您的 JNI 源代码构建一个新库,并使用 System.loadLibrary() 调用从您的 Java 源加载它。我们暂且称之为libjni.so

在 CMake 中,您可以通过以下方式执行此操作:

# jni.c is the file containing the **testSample** function with call to **a_foo()**
add_library(jni SHARED jni.c)
target_link_libraries(jni PRIVATE liba)

这将为您创建一个 libjni.so 文件,它将 link 到 liba.so.您可以像这样从 Java 文件加载它:

System.loadLibrary(jni);

如果 liba.so 不是从同一个 CMake 项目构建的,您需要*使用 CMake 的 find_library and add_library 将其作为目标导入。在线和 CMake Find 模块中有大量示例。当它被构建时,它应该已经指定了它的依赖关系(即如果你做 ldd liba.so 它应该说它 links 到 libb.so) .如果没有,并且您自己无法解决此问题,则可以导入 libb.so 作为另一个目标并将其附加到 target_link_library 行以上。

这应该足以让您使用 Java/Android 代码工作所需的共享对象文件,再次假设在 CMake 中将所有 Java/Android 位放在一起的过程可以be/has 已实现。


* 您实际上可以在 target_link_libraries 调用中使用库的完整路径,但根据 "Modern CMake" 技术,这不是很惯用。


编辑

But how should I link libb to liba

谁构建了 libalibb

它们是您维护的独立项目的来源吗?如果是这样,您需要更改 liba 构建系统,使其 link 变为 libb。然后重建 liba 和你的 JNI 库,你的问题就会消失。

如果您不自己维护它们,则需要:

a) 以相同的方式导入 libb.so liba.so (find_library 随后通过 add_library - links 以上),然后改变 liba.so 的目标,使 libb.so 目标作为 link 依赖使用 set_target_properties

b) 向 liba.so 的维护者提出问题 - 如果一个库使用另一个库,则维护者的工作是满足这种依赖性,而不是用户。