在Android Studio项目中链接.so库

7
正如标题所示,我正在尝试将本地的.so库链接到Android Studio项目中。我已经查阅了Android开发者网站上的文档和其他一些文章,但是在连接.so文件与项目时没有成功。
每当我尝试运行代码时,就会出现以下错误:

CMake错误:此项目中使用了以下变量,但它们被设置为NOTFOUND。请设置它们或确保在CMake文件中正确地设置和测试它们:testlib

这是我的CMake文件。
cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

add_library(testlib SHARED IMPORTED)

set_property(TARGET testlib PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so")

#find_path(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/RemoteDesktop.h)
find_library(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so)

#add_library(remote SHARED IMPORTED)

#set_target_properties(remote PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libremotedesktop_client.so )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib}

                       ${testlib})

target_include_directories()

我有四个.so文件,分别针对arm64、armeabi、armeabi-v7a、x86。我已经在路径中硬编码了armeabi-v7a库,但是当我这样做时,Android Studio会抛出上述错误。我的实际目标是根据手机中的芯片动态加载库。我非常确定,我的当前代码无法实现这一点。

以下是我的疑问

  1. 如何解决我得到的错误?我尝试过给出相对和绝对路径,但是都没有用,我仍然得到同样的错误。

  2. 如何将.so文件和.h文件添加到一个本地Android Studio项目中?这有所变化,根据代码运行的芯片而异?

  3. 当我直接将.h文件添加到本地文件夹中时,我可以引用该头文件中的类和函数,在我的C代码中运行它们,但是我无法运行该代码。我在.h文件中有一个getInstance()方法。每次我调用 getInstance()函数时,它会显示undefined refernce to getInstance()。我理解这意味着“.h”文件正确链接,但实际上存在于“.so”文件中的函数的定义并未链接。如果回答问题1和2,我相信这个问题将得到解决。

  4. 所有本地Android项目都需要一个.m文件吗?我没有将此文件添加到我的项目中,并认为这可能是我遇到的错误之一。


这是我的查询。在SO问题中,每个帖子应该只有一个问题,而不是多个。 - Jesper Juhl
@JesperJuhl。你可能是对的,如果我的每个查询都有不同的答案,那么这个规则就适用。我相信我在某一行犯了一个新手错误,这将解决我所有的4个疑问,这就是为什么我决定把它们放在一个问题中的原因。如果这些查询的答案似乎不同,我将把它们拆分成不同的问题。干杯 :) - Nirmal Raj
请查看此示例:https://github.com/googlesamples/android-ndk/tree/master/hello-libs。 "此示例使用Android Studio CMake插件支持外部库。它演示了如何:()在您的应用程序中包含预构建的静态库(gmath); ()在您的应用程序中包含__预构建的共享库__(gperf)"。 - Richard Critten
2个回答

6
您的情况下不需要使用find_library。对于log来说,库已经被NDK解析好了;对于libremotedesktop_client.so,您已经知道确切的路径。
以下是适用于您的CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

add_library(remote SHARED IMPORTED)

set_property(TARGET remote PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/${ANDROID_ABI}/libremotedesktop_client.so")

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       log

                       remote)

请注意,在CMake脚本中使用完整路径(E:/project…)并不是最佳实践;你可以使用相对于CMakeLists.txt路径的方式来表达到该库的路径,这可以通过${CMAKE_CURRENT_SOURCE_DIR}来实现。

1
该死。大多数与CMake相关的答案都相当冗长。这个似乎是最短的,解决了我的问题。我的情况是:CMake版本3.10.2,所以我没有target_link_directories,这似乎是一个解决方案,如果你有版本> 3.10。最初,我想链接在Android Studio中构建的库,它在自己的模块中。add_library和set_property的组合解决了问题。谢谢。 - hundolin
1
@hundolin 他们现在正在通过 Prefab 在 AS 中处理模块间的本地依赖关系。请参见 https://github.com/android/ndk/issues/1559 - Alex Cohn

3

1-2). 首先,在CMakeLists.txt的开头(就在cmake_minimum_required(...)之后)添加set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH),以允许其他搜索路径用于库。之后,您可以使用标准的find_library来查找库:

find_library(FOO_LIBRARY
         foo # Lib's full name in this case - libfoo.so
         PATHS path/to/lib/)
if (NOT FOO_LIBRARY)
    message(FATAL_ERROR "Foo lib not found!")
endif()

如果库文件的目录结构是这样的,你可以使用变量ANDROID_ABI来获取特定的库版本:

- path/to/lib
       - armeabi-v7a
           - libfoo.so
       - arm64-v8a
           - libfoo.so
       - x86
           - libfoo.so
       - x86_64
           - libfoo.so

因此,在这种情况下,搜索路径为:path/to/lib/${ANDROID_ABI}/

要在项目中包含头文件,只需使用include_directories

include_directories(path/to/headers)

4). 只有在使用ndk-build时才需要.mk文件(因此您不需要任何文件)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接