Android CMake使用预构建。一个库

Android CMake使用预构建。一个库,android,c++,cmake,java-native-interface,Android,C++,Cmake,Java Native Interface,我对CMake和NDK的共同使用是完全陌生的。我想写我的JNI接口并使用两种方法,它们是C库的一部分。我把这个库编译成一个静态库,并得到了.a文件。现在我有点不知所措了,因为我不知道在尝试查找调用的函数时如何告诉AndroidStudio使用这个库 这是我当前的CMakeLists.txt,位于“应用程序”模块文件夹中 cmake_minimum_required(VERSION 3.4.1) add_library(my-lib SHARED src/main/cpp/my-lib.cpp

我对CMake和NDK的共同使用是完全陌生的。我想写我的JNI接口并使用两种方法,它们是C库的一部分。我把这个库编译成一个静态库,并得到了.a文件。现在我有点不知所措了,因为我不知道在尝试查找调用的函数时如何告诉AndroidStudio使用这个库

这是我当前的CMakeLists.txt,位于“应用程序”模块文件夹中

cmake_minimum_required(VERSION 3.4.1)

add_library(my-lib SHARED src/main/cpp/my-lib.cpp )

target_link_libraries(my-lib z crypto)

target_link_libraries(my-lib ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a)

在编译时,我得到一个警告:找不到对被调用函数的引用。我的CMakeLists.txt是否正确?如何为函数包含.h文件?提前感谢您的帮助

首先,您还需要使用 命令 其次,您似乎希望将静态库(.a)与最终共享库链接。这是不可能做到的。您需要整个共享库或整个静态库

我不明白在尝试查找调用的函数时,如何告诉Android Studio使用此库

为了使用本机lib,即
libmy lib。因此
对于您的情况,您需要在java部件中加载此共享lib,如下所示

    static {
        System.loadLibrary("my-lib");
    }
我的CMakeLists.txt正确吗

是的,这是正确的,但不是很完美

如何为函数包含.h文件

为了使自己更容易添加头文件include,您需要稍微配置
CMakelists.txt
。例如,您可能有如下目录结构,如果您只有
app/src/main/cpp
,则可以删除那些不相关的目录和配置

    app
    ├── CMakeLists.txt
    └── src
        ├── foo
        │   ├── CMakeLists.txt
        │   ├── foo.cpp
        │   └── foo.h
        ├── main
        │   └── cpp
        │       ├── CMakeLists.txt
        │       └── my-lib.cpp
        └── test
            ├── CMakeLists.txt
            └── google_test_classXXX.cpp
然后,您需要如下配置
app/CMakelists.txt

    # set the root directory as ${CMAKE_CURRENT_SOURCE_DIR} which is a
    # CMAKE build-in function to return the current dir where your CMakeLists.txt is. 
    # Specifically, it is "<your-path>/App/"
    set(APP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})

    # set your 3 other root dirs, i.e. foo, main and test under app/src.
    set(APP_ROOT_SRC_DIR ${APP_ROOT_DIR}/src)
    set(APP_ROOT_FOO_DIR ${APP_ROOT_SRC_DIR}/foo)
    set(APP_ROOT_MAIN_DIR ${APP_ROOT_SRC_DIR}/main)
    set(APP_ROOT_TEST_DIR ${APP_ROOT_SRC_DIR}/test)

    # set your include paths into "SHARED_INCLUDES" variable so that you can quote your header file without adding its relative paths. 
    set(SHARED_INCLUDES
                    ${APP_ROOT_FOO_DIR}
                    # ${APP_ROOT_FOO_DIR}/<your-other-child-dirs>

                    ${APP_ROOT_MAIN_DIR}
                    ${APP_ROOT_MAIN_DIR}/cpp
                    # ${APP_ROOT_MAIN_DIR}/<your-other-child-dirs>

                    ${APP_ROOT_TEST_DIR}
                    # ${APP_ROOT_TEST_DIR}/<your-other-child-dirs>
                    )

    # This function will have effect to all the downstream cmakelist files. 
    include_directories(${SHARED_INCLUDES})

    add_library(my-lib SHARED src/main/cpp/my-lib.cpp )

    target_link_libraries(my-lib z crypto)

    target_link_libraries(my-lib ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a)

    # remember to include downstream cmakelist files for foo, main and test.
    add_subdirectory(${APP_ROOT_FOO_DIR} bin-dir)
    add_subdirectory(${APP_ROOT_MAIN_DIR} bin-dir)
    add_subdirectory(${APP_ROOT_TEST_DIR} bin-dir)
----编辑以回答您的三个问题--

cpp directoy中的CMakeLists.txt是什么? 它需要在cpp目录中还是在主目录中

理论上,您可以为所有源代码目录和标题目录使用一个
CMakelists.txt
,但一旦您的项目发展到一个非常大的规模,这个集成的
CMakelists.txt
将变得非常复杂,不可读和不可维护。通常,每个cmake模块都应该有自己的
CMakeLists.txt
文件,以便模块化并易于管理。例如,
cpp
dir有一个
CMakeLists.txt
来管理它的所有子dir(如果有),也有
main
test
“模块”

以及如何包含我的.a lib-#include不起作用的.h文件

如上所述,您需要配置
SHARED\u INCLUDES
以将相对路径添加到
.a
的头(
.h
),这样您就可以简单地使用
#include
包含头

    set(SHARED_INCLUDES
                ${APP_ROOT_FOO_DIR}
                # ${APP_ROOT_FOO_DIR}/<your-other-child-dirs>

                ${APP_ROOT_MAIN_DIR}
                ${APP_ROOT_MAIN_DIR}/cpp
                # ${APP_ROOT_MAIN_DIR}/<your-other-child-dirs>

                ${APP_ROOT_TEST_DIR}
                # ${APP_ROOT_TEST_DIR}/<your-other-child-dirs>
       )
CMake构建过程将逐个获取每个ABI。
CMakelists.txt中的变量
${ANDROID_ABI}
可以告诉您它正在构建的当前ABI(体系结构)。如果需要,还可以使用此变量配置库路径

例如,此变量
${ANDROID_ABI}
内部

target_link_libraries(${SHARED_LIBRARY_NAME} -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/${ANDROID_ABI}/libmine.a -Wl,--no-whole-archive)

在构建期间将替换为
armeabi-v7a
arm64-v8a
x86
x86_64

您使用了什么工具链来构建静态库?在交叉编译时,您需要使用Android工具链来编译所有代码。我如何使用CMake直接编译它呢?这里有文档记录:记住,Android的构建通常是针对各种风格的ARM芯片(和其他芯片)的交叉编译。谢谢,我会在那里看一看。非常感谢你的详细回答。三个问题:cpp directoy中的CMakeLists.txt是什么?它需要在cpp目录中还是在主目录中?我如何包含我的.a lib-#include的.h文件?include不起作用。这意味着我必须将头文件保存在应用程序中,对吗?我想我误解了这一点,在你可以将头文件放在任何你喜欢的地方之前没有添加它们,但是请记住将目录路径添加到你的include_目录中,这样你就不必添加它的相对路径。谢谢,这很有帮助。还有一个问题:CMake中有没有办法告诉目标库我们使用的是哪种体系结构?我包括了arm64-v8a、armeabi-v7a、x86和x86_64,但是否有一个变量可以让CMake知道应该使用哪一个?再次感谢您提供的详细答案:)
    defaultConfig {
        externalNativeBuild {
            cmake {
                ...
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                ...
            }
        }
    }
target_link_libraries(${SHARED_LIBRARY_NAME} -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/${ANDROID_ABI}/libmine.a -Wl,--no-whole-archive)