Android CMake使用prebuild .a库 [英] Android CMake use prebuild .a library

查看:112
本文介绍了Android CMake使用prebuild .a库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆