[英]Android CMake use prebuild .a library
I am totally new to CMake and using NDK in common. 我对CMake完全陌生,并且经常使用NDK。 I figured out to write my JNI interface and use 2 methods which are part of a C library. 我想出要编写我的JNI接口并使用C库中2种方法的方法。 I compiled this library as a static library and got the .a file. 我将此库编译为静态库,并获得了.a文件。 Now I'm a little bit lost as I don't understand how to tell Android Studio to use this library when trying to find the called functions. 现在,我有点迷茫,因为我不明白在尝试查找被调用的函数时如何告诉Android Studio使用此库。
This is my current CMakeLists.txt which is located in the "app" module folder. 这是我当前的CMakeLists.txt,它位于“ app”模块文件夹中。
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)
On compilation I get the warning that no reference can be found to the called functions. 在编译时,我得到警告,找不到被调用函数的引用。 Is my CMakeLists.txt correct and how do I include the .h file for the functions? 我的CMakeLists.txt是否正确,如何为这些功能包括.h文件? Thanks in advance for any help! 在此先感谢您的帮助!
First of all you need to specify the include directories as well using include_directories() command. 首先,您还需要使用include_directories()命令指定包含目录。 Second it seems you want to link a static library(.a) with your final shared library. 其次,似乎您想将静态库(.a)与最终共享库链接。 This cannot be done. 无法做到这一点。 You either need shared libraries throughout or static libraries throughout. 您要么需要共享库,要么需要静态库。
I don't understand how to tell Android Studio to use this library when trying to find the called functions 我不明白在尝试查找被调用函数时如何告诉Android Studio使用此库
In order to use your native libs, ie libmy-lib.so
for your case, you need to load this shared lib inside your java part like below. 为了使用您的本机libs,即libmy-lib.so
,您需要在Java部分中加载此共享的lib,如下所示。
static {
System.loadLibrary("my-lib");
}
Is my CMakeLists.txt correct ? 我的CMakeLists.txt是否正确?
Yes, it is correct, but not really perfect. 是的,这是正确的,但不是很完美。
and how do I include the .h file for the functions 以及如何为功能添加.h文件
In order to make yourself work easier to add the header file includes, you need to configure CMakelists.txt
a little bit. 为了使自己的工作更容易,添加头文件包括在内,您需要进行一些配置CMakelists.txt
。 Eg You may have a directory structure as below, if you only have the app/src/main/cpp
, then can just remove those unrelated dirs and configurations. 例如,您可能具有以下目录结构,如果仅具有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
Then you need to configure your app/CMakelists.txt
as below. 然后,您需要按以下方式配置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)
----Edited---- ---- ----编辑
For how to link the prebuild .a libs. 有关如何链接预构建.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)
---- Edited to answer your three questions ---- ----编辑为回答您的三个问题----
What is part of the CMakeLists.txt inside of the cpp directoy? cpp Directoy内CMakeLists.txt的一部分是什么? Does it need to be in the cpp directory or in the main directory? 它需要在cpp目录中还是在主目录中?
Theoretically, you can just have one CMakelists.txt
for all your source code dirs and header dirs, but once your project evolves to a very large scale, this all-in-one CMakelists.txt
will become quite complicate and not readable and maintainable. 从理论上讲,您只可以为所有源代码目录和标头目录提供一个CMakelists.txt
,但是一旦您的项目发展到非常大的规模,这种多合一的CMakelists.txt
就会变得非常复杂, CMakelists.txt
和维护。 Usually, each cmake module should have its own CMakeLists.txt
file so that it is modularised and easier to manage. 通常,每个cmake模块应具有其自己的CMakeLists.txt
文件,以便将其模块化并易于管理。 Eg cpp
dir has one CMakeLists.txt
to manage all its sub dirs if any, so do main
and test
"module". 例如, cpp
dir具有一个CMakeLists.txt
来管理其所有子目录(如果有的话),因此main
并test
“模块”。
And how do I include a .h file of my .a lib - #include does not work. 以及如何包含.a lib的.h文件-#include不起作用。
As I mentioned above, you need to configure SHARED_INCLUDES
to add your relative paths to the headers ( .h
) of your .a
, so that you can simply use #include <xxx.h>
for header inclusion. 如前所述,您需要配置SHARED_INCLUDES
将相对路径添加到.a
的标头( .h
),以便您可以简单地使用#include <xxx.h>
进行标头包含。
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>
)
Set your include paths into "SHARED_INCLUDES" variable so that you can quote your header file without adding its relative paths. 将包含路径设置为“ SHARED_INCLUDES”变量,以便可以在不添加其相对路径的情况下引用头文件。
Edit to answer your question about how to configure architectures 编辑以回答有关如何配置体系结构的问题
you can configure your targets inside build.gradle
as below: 您可以在build.gradle
配置目标,如下所示:
defaultConfig {
externalNativeBuild {
cmake {
...
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
...
}
}
}
The CMake build process will take each ABI one by one. CMake的构建过程将使每个ABI一件一件。 The variable ${ANDROID_ABI}
inside CMakelists.txt
can tell you the current ABI (architecture) it is building. CMakelists.txt
的变量${ANDROID_ABI}
可以告诉您它正在构建的当前ABI(体系结构)。 And you can also use this variable to configure your library PATHs if you need. 并且,如果需要,您还可以使用此变量来配置库PATH。
Eg This variable ${ANDROID_ABI}
inside 例如,变量${ANDROID_ABI}
里面
target_link_libraries(${SHARED_LIBRARY_NAME} -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/${ANDROID_ABI}/libmine.a -Wl,--no-whole-archive)
will be replaced with armeabi-v7a
, arm64-v8a
, x86
or x86_64
during the build time. 在构建期间将被armeabi-v7a
, arm64-v8a
, x86
或x86_64
替换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.