Android CMake使用预构建。一个库
我对CMake和NDK的共同使用是完全陌生的。我想写我的JNI接口并使用两种方法,它们是C库的一部分。我把这个库编译成一个静态库,并得到了.a文件。现在我有点不知所措了,因为我不知道在尝试查找调用的函数时如何告诉AndroidStudio使用这个库 这是我当前的CMakeLists.txt,位于“应用程序”模块文件夹中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_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)