我对CMake完全陌生,并且经常使用NDK。我想出要编写我的JNI接口并使用C库中2种方法的方法。我将此库编译为静态库,并获得了.a文件。现在,我有点不知所措,因为我不明白在尝试查找被调用的函数时如何告诉Android Studio使用该库。
这是我当前的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文件?预先感谢您的帮助!
答案 0 :(得分:2)
首先,您还需要使用以下命令指定包含目录 include_directories()命令。 其次,似乎您想将 static 库(.a)与最终的 shared 库链接。无法做到这一点。您要么需要共享库,要么需要静态库。
答案 1 :(得分:1)
我不明白如何在尝试查找被调用函数时告诉Android Studio使用该库
要使用您的本机库,即libmy-lib.so
,您需要将此共享库加载到Java部分中,如下所示。
static {
System.loadLibrary("my-lib");
}
我的CMakeLists.txt是否正确?
是的,这是正确的,但不是很完美。
以及如何为功能添加.h文件
为了使自己更容易添加头文件包括,您需要进行一些配置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)
----已编辑----
有关如何链接预构建.a库的信息。
# 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(my-lib -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a -Wl,--no-whole-archive)
----编辑为回答您的三个问题----
cpp Directoy内CMakeLists.txt的一部分是什么? 它需要在cpp目录中还是在主目录中?
从理论上讲,您可以为所有源代码目录和标头目录使用一个CMakelists.txt
,但是一旦您的项目发展到非常大的规模,这个多合一的CMakelists.txt
就会变得非常实用复杂且不可读和不可维护。通常,每个cmake模块都应具有自己的CMakeLists.txt
文件,以便对其进行模块化和易于管理。例如。 cpp
目录有一个CMakeLists.txt
来管理其所有子目录(如果有),main
和test
“模块”也是如此。
以及如何包含.a lib的.h文件-#include不起作用。
如上所述,您需要配置SHARED_INCLUDES
以将相对路径添加到.h
的标头(.a
)中,以便可以简单地使用{{1} }包含标头。
#include <xxx.h>
将包含路径设置为“ SHARED_INCLUDES”变量,以便您可以引用头文件而无需添加其相对路径。
编辑以回答有关如何配置体系结构的问题
您可以在 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>
)
内部配置目标,如下所示:
build.gradle
CMake的构建过程将逐个处理每个ABI。 defaultConfig {
externalNativeBuild {
cmake {
...
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
...
}
}
}
中的变量${ANDROID_ABI}
可以告诉您它正在构建的当前ABI(体系结构)。并且,如果需要,您还可以使用此变量来配置库PATH。
例如
中的CMakelists.txt
变量
${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
替换。