Android CMake使用prebuild .a库 [英] Android CMake use prebuild .a library
问题描述
我对CMake完全陌生,并且经常使用NDK。我想出编写我的JNI接口并使用C库中2种方法的方法。我将此库编译为静态库,并获得了.a文件。现在我有点迷茫,因为我不明白如何在尝试查找被调用函数时告诉Android Studio使用该库。
I am totally new to CMake and using NDK in common. I figured out to write my JNI interface and use 2 methods which are part of a C library. I compiled this library as a static library and got the .a file. 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.
这是我目前的情况CMakeLists.txt,位于应用程序模块文件夹中。
This is my current CMakeLists.txt which is located in the "app" module folder.
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文件?在此先感谢您的帮助!
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? Thanks in advance for any help!
推荐答案
我不知道如何告诉Android Studio尝试查找被调用的函数时,请使用该库
I don't understand how to tell Android Studio to use this library when trying to find the called functions
为了使用您的本机库,即 libmy-对于lib.so
,您需要像下面这样在Java部分中加载此共享的lib。
In order to use your native libs, i.e. libmy-lib.so
for your case, you need to load this shared lib inside your java part like below.
static {
System.loadLibrary("my-lib");
}
我的CMakeLists.txt是否正确?
Is my CMakeLists.txt correct ?
是的,这是正确的,但并不是很完美。
Yes, it is correct, but not really perfect.
以及如何为功能添加.h文件
and how do I include the .h file for the functions
为了使您自己的工作更容易添加头文件包括,您需要进行一些配置 CMakelists.txt
。例如。您可能具有以下目录结构,如果只有 app / src / main / cpp
,则可以删除那些无关的目录和配置。
In order to make yourself work easier to add the header file includes, you need to configure CMakelists.txt
a little bit. E.g. 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
├── 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
如下。
Then you need to configure your app/CMakelists.txt
as below.
# 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库的信息。
For how to link the prebuild .a libs.
# 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指令中CMakeLists.txt的一部分是什么?
它需要在cpp目录中还是在主目录中?
What is part of the CMakeLists.txt inside of the cpp directoy? Does it need to be in the cpp directory or in the main directory?
理论上,您可以只包含一个 CMakelists.txt
用于所有源代码目录和标头目录,但是一旦您的项目发展到非常大的规模,这个多功能的 CMakelists。 txt
会变得非常复杂,无法阅读和维护。通常,每个cmake模块都应具有自己的 CMakeLists.txt
文件,以便对其进行模块化和易于管理。例如。 cpp
目录有一个 CMakeLists.txt
来管理所有子目录(如果有的话),因此 main
和 test
模块。
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. Usually, each cmake module should have its own CMakeLists.txt
file so that it is modularised and easier to manage. E.g. cpp
dir has one CMakeLists.txt
to manage all its sub dirs if any, so do main
and test
"module".
以及如何包含.a lib的.h文件-#include不起作用。
And how do I include a .h file of my .a lib - #include does not work.
如上所述,您需要配置 SHARED_INCLUDES
将相对路径添加到标头(<$ .a
中的c $ c> .h ),因此您可以简单地使用 #include< xxx。 h>
包含标头。
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.
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>
)
将包含路径设置为 SHARED_INCLUDES变量,以便您可以在不添加其相对路径的情况下引用头文件。
编辑以回答有关如何配置体系结构的问题
您可以在 build.gradle
中配置目标,如下所示:
you can configure your targets inside build.gradle
as below:
defaultConfig {
externalNativeBuild {
cmake {
...
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
...
}
}
}
CMake的构建过程将使每个ABI一张一张。 CMakelists.txt
中的变量 $ {ANDROID_ABI}
可以告诉您它正在构建的当前ABI(体系结构)。并且,如果需要,您还可以使用此变量来配置库PATH。
The CMake build process will take each ABI one by one. The variable ${ANDROID_ABI}
inside CMakelists.txt
can tell you the current ABI (architecture) it is building. And you can also use this variable to configure your library PATHs if you need.
例如
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使用prebuild .a库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!