【Android小品】OpenCV配置 之一 CMake详解(基于最新平台AS 2.2)
2016-12-19 09:28
363 查看
接下来几篇文章将讲述在Android Studio上配置openCv的过程
做个不太贴切的类比:CmakeList.txt、 Android.mk的作用就好像是build.gradle。
CMake是专门用来辅助C/C++等原生代码的编译。它们会根据CmakeList.txt、 Android.mk操作编译器把.cpp、.h、.hpp这样的源文件编译成Android能看得懂的.so文件。
所谓动态链接,就是说函数的函数体是在运行时确定的。函数的可执行代码存放在.dll(.so) 文件中,.dll(.so)包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
使用动态链接库可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,一个大型网络游戏,如果把整个数百MB甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,更新起来也不方便,而如果把不同功能的代码分别放在数个动态链接库中,无需重新生成或安装整个程序就可以应用更新。
我们在Android中使用原生代码都是根据.so文件的,而CMake是为了操作编译器把.c文件编译成为.so。换句话说其实如果你直接有.so,就不需要使用源代码了。
一般我们首先会在JAVA代码中使用native方法,然后通过javah命令去生成头文件。然后在C代码中包含这个头文件,并对函数体提供定义。如果我们简单的需要C去运算一些密码等等这就够了。但是如果我们需要去调用类似opencv这样的C代码库,则就还需要一些步骤。因为系统是不知道你的C库在哪里,有哪些函数的,所以需要进行配置。
使用第三方库需要三方面准备:
1.将第三方库编译好的.so文件放入工程的jni库目录(如果没有要配置gradle)
2.添加每一个.so为单独的library(动态链接库,告诉系统如果需要函数,就执行我里面的函数体)
3.指定第三方C库的头文件目录(.so是函数体,头文件用来告诉编译器函数签名)
4.链接到你自己的原生库。(系统知道了第三方库的函数签名和函数定义不行,还要告诉系统你的库想要用哪些东西,所以需要链接)
这些和VS里面使用C/C++库非常类似
Android Studio2.2以上版本构建原生库的默认工具是 CMake。但为了兼容性Android Studio 仍支持 ndk-build(后文会提到)。如果在创建新的原生库,则应使用 CMake。
如果执意使用ndk-build,那么需要在build.properties里面加上这一行
CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果只计划使用 ndk-build,则不需要此组件。
LLDB:一种调试程序,Android Studio 使用它来调试原生代码。
可以使用 SDK 管理器(目前Android Studio已经内置)安装这些组件:
在打开的项目中,从菜单栏选择 Tools > Android > SDK Manager。
点击 SDK Tools 标签。
选中 LLDB、CMake 和 NDK 旁的复选框,如图 1 所示。
图 1.从 SDK 管理器中安装 LLDB、CMake 和 NDK。
点击 Apply,然后在弹出式对话框中点击 OK。
安装完成后,点击 Finish,然后点击 OK。
在向导的 Configure your new project 部分,选中 Include C++ Support 复选框。
点击 Next。
正常填写所有其他字段并完成向导接下来的几个部分。
在向导的 Customize C++ Support 部分,可以使用下列选项自定义项目:
C++ Standard:使用下拉列表选择使用的 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
Exceptions Support:如果希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果希望支持 RTTI(运行时类型信息),请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
点击 Finish。
在 Android Studio 完成新项目的创建后,请从 IDE 左侧打开 Project 窗格并选择 Android 视图。如图 2 中所示,Android Studio 将添加 cpp 和 External Build Files 组:
图 2.原生源文件。
在 cpp 组中,你可以找到属于项目的所有原生源文件、标头和预构建库。对于新项目,Android Studio 会创建一个示例 C++ 源文件 native-lib.cpp,并将其置于应用模块的 src/main/cpp/ 目录中。本示例代码提供了一个简单的 C++ 函数 stringFromJNI(),此函数可以返回字符串“Hello from C++”。
在 External Build Files 组中,你可以找到 CMake 或 ndk-build 的构建脚本。与 build.gradle 文件指示 Gradle 如何构建应用一样,CMake 和 ndk-build 需要一个构建脚本来了解如何构建原生库。对于新项目,Android Studio 会创建一个 CMake 构建脚本 CMakeLists.txt,并将其置于模块的根目录中。(后文会介绍如何编写 CMakeLists.txt 和 Android.mk)
Gradle 调用外部构建脚本 CMakeLists.txt。
CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其封装到 APK 中。
运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。
注:使用原生代码,Instant Run就不能用了,Android Studio 会自动停用此功能。
如果想要验证 Gradle 是否已将原生库封装到 APK 中,可以使用 APK 分析器:
选择 Build > Analyze APK。
从 app/build/outputs/apk/ 目录中选择 APK 并点击 OK。
如图 3 中所示,可以在 APK 分析器窗口的 lib/……/ 下看到 libnative-lib.so。
图 3.使用 APK 分析器定位原生库。
创建新的原生源文件并将其添加到 Android Studio 项目中。
如果已经拥有原生代码或想要导入预构建的原生库,则可以跳过此步骤。
创建 CMake 构建脚本,将原生源代码构建到库中。如果导入和关联预构建库或平台库,你也需要此构建脚本。
如果现有原生库已经拥有 CMakeLists.txt 构建脚本或者使用 ndk-build 并包含 Android.mk 构建脚本,则可以跳过此步骤。
提供一个指向 CMake 或 ndk-build 脚本文件的路径,将 Gradle 关联到原生库。Gradle 使用构建脚本将源代码导入 Android Studio 项目并将原生库(SO 文件)封装到 APK 中。
配置完项目后,可以使用 JNI 框架从 Java 代码中访问原生函数。要构建和运行应用,只需点击 Run 从菜单栏运行应用。Gradle 会以依赖项的形式添加外部原生构建流程,用于编译、构建原生库并将其随 APK 一起封装。
从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
导航到moudle > src,右键点击 main 目录,然后选择 New > Directory。
为目录输入一个名称(例如 cpp)并点击 OK。
右键点击刚刚创建的目录,然后选择 New > C/C++ Source File。
为源文件输入一个名称,例如 native-lib。
从 Type 下拉菜单中,为源文件选择文件扩展名,例如 .cpp。
点击 Edit File Types ,可以向下拉菜单中添加其他文件类型,例如 .cxx 或 .hxx。在弹出的 C/C++ 对话框中,从 Source Extension 和 Header Extension 下拉菜单中选择另一个文件扩展名,然后点击 OK。
如果还希望创建一个标头文件,请选中 Create an associated header 复选框。
点击 OK。
注:如果项目使用 ndk-build,则不需要创建 CMake 构建脚本。提供一个指向 Android.mk 文件的路径,将 Gradle 关联到原生库。
要创建一个可以用作 CMake 构建脚本的纯文本文件,请按以下步骤操作:
从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
右键点击moudle的根目录并选择 New > File。
输入“CMakeLists.txt”作为文件名并点击 OK。
现在,你可以添加 CMake 命令,对构建脚本进行配置。要指示 CMake 从原生源代码创建一个原生库,请将 cmake_minimum_required() 和 add_library() 命令添加到构建脚本中:
使用 add_library() 向 CMake 构建脚本添加源文件或库时,还需要将 include_directories() 命令添加到 CMake 构建脚本中并指定头文件的路径:
提示:就像VS要指定的include一样,在这里指定了IDE和编译器才能找到#include<…>尖括号里面的东西
CMake 使用以下规范来为库文件命名:
lib+库名称+.so
例如,如果在构建脚本中指定“native-lib”作为共享库的名称,CMake 将创建一个名称为 libnative-lib.so 的文件。不过,在 Java 代码中加载此库时,请使用在 CMake 构建脚本中指定的名称:
Android Studio 会自动将源文件和标头添加到 Project 窗格的 cpp 组中。使用多个 add_library() 命令,可以为 CMake 定义要从其他源文件构建的更多库。
预构建的 NDK 库已经存在于 Android 平台上,因此,无需再构建或将其封装到 APK 中。由于 NDK 库已经是 CMake 搜索路径的一部分,甚至不需要在本地 NDK 安装中指定库的位置 - 只需要向 CMake 提供希望使用的库的名称,并将其关联到自己的原生库。
将 find_library() 命令添加到 CMake 构建脚本中以定位 NDK 库,并将其路径存储为一个变量。可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例可以定位 Android 特定的日志支持库并将其路径存储在 log-lib 中:
为了确保原生库可以在 log 库中调用函数,需要使用 CMake 构建脚本中的 target_link_libraries() 命令关联库:
NDK 还以源代码的形式包含一些库,在构建和关联到原生库时需要使用这些代码。可以使用 CMake 构建脚本中的 add_library() 命令,将源代码编译到原生库中。要提供本地 NDK 库的路径,可以使用 ANDROID_NDK 路径变量,Android Studio 会自动定义此变量。
以下命令可以指示 CMake 构建 android_native_app_glue.c,后者会将 NativeActivity 生命周期事件和触摸输入置于静态库中并将静态库关联到 native-lib:
然后,你需要使用 set_target_properties() 命令指定库的路径,如下所示。
某些库为特定的 CPU 架构(或应用二进制接口 (ABI))提供了单独的软件包,(这里ABI指的是 mip64等等这些so库的文件夹),并将其组织到单独的目录中。此方法既有助于库充分利用特定的 CPU 架构,又能让你仅使用所需的库版本。要向 CMake 构建脚本中添加库的多个 ABI 版本,而不必为库的每个版本编写多个命令,可以使用 ANDROID_ABI 路径变量。此变量使用 NDK 支持的一组默认 ABI。例如:
为了确保 CMake 可以在编写代码时#include头文件,需要使用 include_directories() 命令,并包含标头文件的路径:
然后将构件库链接到自己的原生库,以便在自己写的C代码中使用这些C/C++库,请将其添加到 CMake 构建脚本的 target_link_libraries() 命令中:
从 IDE 左侧打开 Project 窗格并选择 Android 视图。
右键点击想要关联到原生库的模块(例如 app 模块),并从菜单中选择 Link C++ Project with Gradle。你应看到一个如图 4 所示的对话框。
从下拉菜单中,选择 CMake 或 ndk-build。
如果选择 CMake,请使用 Project Path 旁的字段为外部 CMake 项目指定 CMakeLists.txt 脚本文件。
如果选择 ndk-build,请使用 Project Path 旁的字段为外部 ndk-build 项目指定 Android.mk 脚本文件。如果 Application.mk 文件与 Android.mk 文件位于相同目录下,Android Studio 也会包含此文件。
图 4.使用 Android Studio 对话框关联外部 C++ 项目。
点击 OK。
如果要手动配置 Gradle 以关联到原生库,你需要将 externalNativeBuild {} 块添加到模块级 build.gradle 文件中,并使用 cmake {} 或 ndkBuild {} 对其进行配置:
一、背景知识
什么是CMake?
CMake是一个跨平台的编译辅助工具(构建工具),可以用简单的语句(CmakeList.txt)来描述所有平台的安装(编译过程)为什么需要CMake这样的构建工具?
但是当你的程序包含很多个源文件时,如果直接在控制台使用编译器命令(gcc等)逐个去编译时,会发现十分混乱而且工作量超大。编译工具包可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件(里面就包含了调用编译器的命令)来进行编译和链接的。而这个makefile文件是通过CmakeList.txt、 Android.mk文件生成的。CmakeList.txt、 Android.mk就是你要写的东西。具体就是指定一些目录啊、版本啊等等,具体的活儿都不需要你来做了。做个不太贴切的类比:CmakeList.txt、 Android.mk的作用就好像是build.gradle。
CMake是专门用来辅助C/C++等原生代码的编译。它们会根据CmakeList.txt、 Android.mk操作编译器把.cpp、.h、.hpp这样的源文件编译成Android能看得懂的.so文件。
.so文件是什么?
.so文件是Linux中的动态链接库文件,等价于Windows下的.dll。所谓动态链接,就是说函数的函数体是在运行时确定的。函数的可执行代码存放在.dll(.so) 文件中,.dll(.so)包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
使用动态链接库可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。例如,一个大型网络游戏,如果把整个数百MB甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,更新起来也不方便,而如果把不同功能的代码分别放在数个动态链接库中,无需重新生成或安装整个程序就可以应用更新。
二、综述
想要正确的配置C/C++库首先要有一个大致上的概念,知道为什么这么做才能够真正理解并记忆下来。我们在Android中使用原生代码都是根据.so文件的,而CMake是为了操作编译器把.c文件编译成为.so。换句话说其实如果你直接有.so,就不需要使用源代码了。
一般我们首先会在JAVA代码中使用native方法,然后通过javah命令去生成头文件。然后在C代码中包含这个头文件,并对函数体提供定义。如果我们简单的需要C去运算一些密码等等这就够了。但是如果我们需要去调用类似opencv这样的C代码库,则就还需要一些步骤。因为系统是不知道你的C库在哪里,有哪些函数的,所以需要进行配置。
使用第三方库需要三方面准备:
1.将第三方库编译好的.so文件放入工程的jni库目录(如果没有要配置gradle)
2.添加每一个.so为单独的library(动态链接库,告诉系统如果需要函数,就执行我里面的函数体)
3.指定第三方C库的头文件目录(.so是函数体,头文件用来告诉编译器函数签名)
4.链接到你自己的原生库。(系统知道了第三方库的函数签名和函数定义不行,还要告诉系统你的库想要用哪些东西,所以需要链接)
这些和VS里面使用C/C++库非常类似
三、CMake在Android Studio使用
在Android Studio 2.2以上的版本中,你就可以直接使用CMake编译源代码文件,Android Studio会使用Gradle自动把CMake生成的文件打包到你的apk中(其实编译步骤也是自动的,Android Studio能够自动的读取CMakeList.txt然后调用CMake进行编译)。Android Studio2.2以上版本构建原生库的默认工具是 CMake。但为了兼容性Android Studio 仍支持 ndk-build(后文会提到)。如果在创建新的原生库,则应使用 CMake。
如果执意使用ndk-build,那么需要在build.properties里面加上这一行
android.useDeprecatedNdk = true
下载 NDK 和构建工具
Android 原生开发工具包 (NDK):这套工具集允许你为 Android 使用 C 和 C++ 代码,并提供众多平台库,你可以管理原生 Activity 和访问物理设备组件,例如传感器和触摸输入。里面包含ndk-build和一些库,虽然说ndk-build被cmake代替了,但是其他库还是要的,所以这个还需要装CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果只计划使用 ndk-build,则不需要此组件。
LLDB:一种调试程序,Android Studio 使用它来调试原生代码。
可以使用 SDK 管理器(目前Android Studio已经内置)安装这些组件:
在打开的项目中,从菜单栏选择 Tools > Android > SDK Manager。
点击 SDK Tools 标签。
选中 LLDB、CMake 和 NDK 旁的复选框,如图 1 所示。
图 1.从 SDK 管理器中安装 LLDB、CMake 和 NDK。
点击 Apply,然后在弹出式对话框中点击 OK。
安装完成后,点击 Finish,然后点击 OK。
创建支持 C/C++ 的新项目
创建支持原生代码的项目与创建任何其他 Android Studio 项目类似,不过还需额外几个步骤:在向导的 Configure your new project 部分,选中 Include C++ Support 复选框。
点击 Next。
正常填写所有其他字段并完成向导接下来的几个部分。
在向导的 Customize C++ Support 部分,可以使用下列选项自定义项目:
C++ Standard:使用下拉列表选择使用的 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
Exceptions Support:如果希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果希望支持 RTTI(运行时类型信息),请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
点击 Finish。
在 Android Studio 完成新项目的创建后,请从 IDE 左侧打开 Project 窗格并选择 Android 视图。如图 2 中所示,Android Studio 将添加 cpp 和 External Build Files 组:
图 2.原生源文件。
在 cpp 组中,你可以找到属于项目的所有原生源文件、标头和预构建库。对于新项目,Android Studio 会创建一个示例 C++ 源文件 native-lib.cpp,并将其置于应用模块的 src/main/cpp/ 目录中。本示例代码提供了一个简单的 C++ 函数 stringFromJNI(),此函数可以返回字符串“Hello from C++”。
在 External Build Files 组中,你可以找到 CMake 或 ndk-build 的构建脚本。与 build.gradle 文件指示 Gradle 如何构建应用一样,CMake 和 ndk-build 需要一个构建脚本来了解如何构建原生库。对于新项目,Android Studio 会创建一个 CMake 构建脚本 CMakeLists.txt,并将其置于模块的根目录中。(后文会介绍如何编写 CMakeLists.txt 和 Android.mk)
构建和运行示例应用
点击 Run 从菜单栏运行应用 后,Android Studio 将在 Android 设备或者模拟器上构建并启动一个显示文字“Hello from C++”的应用。下面的概览介绍了构建和运行示例应用时会发生的事件:Gradle 调用外部构建脚本 CMakeLists.txt。
CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其封装到 APK 中。
运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。
注:使用原生代码,Instant Run就不能用了,Android Studio 会自动停用此功能。
如果想要验证 Gradle 是否已将原生库封装到 APK 中,可以使用 APK 分析器:
选择 Build > Analyze APK。
从 app/build/outputs/apk/ 目录中选择 APK 并点击 OK。
如图 3 中所示,可以在 APK 分析器窗口的 lib/……/ 下看到 libnative-lib.so。
图 3.使用 APK 分析器定位原生库。
向现有项目添加 C/C++ 代码
如果想向现有项目添加原生代码,请执行以下步骤:创建新的原生源文件并将其添加到 Android Studio 项目中。
如果已经拥有原生代码或想要导入预构建的原生库,则可以跳过此步骤。
创建 CMake 构建脚本,将原生源代码构建到库中。如果导入和关联预构建库或平台库,你也需要此构建脚本。
如果现有原生库已经拥有 CMakeLists.txt 构建脚本或者使用 ndk-build 并包含 Android.mk 构建脚本,则可以跳过此步骤。
提供一个指向 CMake 或 ndk-build 脚本文件的路径,将 Gradle 关联到原生库。Gradle 使用构建脚本将源代码导入 Android Studio 项目并将原生库(SO 文件)封装到 APK 中。
配置完项目后,可以使用 JNI 框架从 Java 代码中访问原生函数。要构建和运行应用,只需点击 Run 从菜单栏运行应用。Gradle 会以依赖项的形式添加外部原生构建流程,用于编译、构建原生库并将其随 APK 一起封装。
创建新的原生源文件
要在应用模块的主源代码集中创建一个包含新建原生源文件的 cpp/ 目录,请按以下步骤操作:从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
导航到moudle > src,右键点击 main 目录,然后选择 New > Directory。
为目录输入一个名称(例如 cpp)并点击 OK。
右键点击刚刚创建的目录,然后选择 New > C/C++ Source File。
为源文件输入一个名称,例如 native-lib。
从 Type 下拉菜单中,为源文件选择文件扩展名,例如 .cpp。
点击 Edit File Types ,可以向下拉菜单中添加其他文件类型,例如 .cxx 或 .hxx。在弹出的 C/C++ 对话框中,从 Source Extension 和 Header Extension 下拉菜单中选择另一个文件扩展名,然后点击 OK。
如果还希望创建一个标头文件,请选中 Create an associated header 复选框。
点击 OK。
创建 CMake 构建脚本
如果原生源文件还没有 CMake 构建脚本,则你需要自行创建一个并包含适当的 CMake 命令。CMake 构建脚本是一个纯文本文件,你必须将其命名为 CMakeLists.txt。本部分介绍了包含到构建脚本中的一些基本命令,用于在创建原生库时指示 CMake 应使用哪些源文件。注:如果项目使用 ndk-build,则不需要创建 CMake 构建脚本。提供一个指向 Android.mk 文件的路径,将 Gradle 关联到原生库。
要创建一个可以用作 CMake 构建脚本的纯文本文件,请按以下步骤操作:
从 IDE 的左侧打开 Project 窗格并从下拉菜单中选择 Project 视图。
右键点击moudle的根目录并选择 New > File。
输入“CMakeLists.txt”作为文件名并点击 OK。
现在,你可以添加 CMake 命令,对构建脚本进行配置。要指示 CMake 从原生源代码创建一个原生库,请将 cmake_minimum_required() 和 add_library() 命令添加到构建脚本中:
# 用于指定项目需要的cmake最低版本. # cmake通过这个选项来确定能够使用那些特性 cmake_minimum_required(VERSION 3.4.1) # 指派原生库名称、模式以及源码目录 add_library( # 库名称 native-lib # 模式 SHARED # 源码目录 src/main/cpp/native-lib.cpp )
使用 add_library() 向 CMake 构建脚本添加源文件或库时,还需要将 include_directories() 命令添加到 CMake 构建脚本中并指定头文件的路径:
提示:就像VS要指定的include一样,在这里指定了IDE和编译器才能找到#include<…>尖括号里面的东西
# 指定头文件文件夹 include_directories(src/main/cpp/include/)
CMake 使用以下规范来为库文件命名:
lib+库名称+.so
例如,如果在构建脚本中指定“native-lib”作为共享库的名称,CMake 将创建一个名称为 libnative-lib.so 的文件。不过,在 Java 代码中加载此库时,请使用在 CMake 构建脚本中指定的名称:
static { System.loadLibrary(“native-lib”); }
Android Studio 会自动将源文件和标头添加到 Project 窗格的 cpp 组中。使用多个 add_library() 命令,可以为 CMake 定义要从其他源文件构建的更多库。
添加 NDK API
Android NDK 提供了一套实用的原生 API 和库。通过将 NDK 库包含到项目的 CMakeLists.txt 脚本文件中,可以使用这些 API 中的任意一种。预构建的 NDK 库已经存在于 Android 平台上,因此,无需再构建或将其封装到 APK 中。由于 NDK 库已经是 CMake 搜索路径的一部分,甚至不需要在本地 NDK 安装中指定库的位置 - 只需要向 CMake 提供希望使用的库的名称,并将其关联到自己的原生库。
将 find_library() 命令添加到 CMake 构建脚本中以定位 NDK 库,并将其路径存储为一个变量。可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例可以定位 Android 特定的日志支持库并将其路径存储在 log-lib 中:
find_library( # ndklib的位置 log-lib # ndklib的名称 log )
为了确保原生库可以在 log 库中调用函数,需要使用 CMake 构建脚本中的 target_link_libraries() 命令关联库:
# 将原生库和你的库连接起来(这里可以一行链接多个库) target_link_libraries( # 目标库 native-lib # 要链接的库 ${log-lib} )
NDK 还以源代码的形式包含一些库,在构建和关联到原生库时需要使用这些代码。可以使用 CMake 构建脚本中的 add_library() 命令,将源代码编译到原生库中。要提供本地 NDK 库的路径,可以使用 ANDROID_NDK 路径变量,Android Studio 会自动定义此变量。
以下命令可以指示 CMake 构建 android_native_app_glue.c,后者会将 NativeActivity 生命周期事件和触摸输入置于静态库中并将静态库关联到 native-lib:
add_library( app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c ) # 链接库 target_link_libraries( native-lib app-glue ${log-lib} )
添加其他预构建库(OpenCv就是预构建库)
添加预构建库与为 CMake 指定要构建的另一个原生库类似。不过,由于库已经预先构建,需要使用 IMPORTED 标志告知 CMake 你只希望将库导入到项目中:#很重要:我发现IMPORTED的set_target_properties()中只能写一个.so文件的目录,如果有多个.so则需要每个都建立一个library,然后最后一起链接 add_library( imported-lib SHARED IMPORTED )
然后,你需要使用 set_target_properties() 命令指定库的路径,如下所示。
某些库为特定的 CPU 架构(或应用二进制接口 (ABI))提供了单独的软件包,(这里ABI指的是 mip64等等这些so库的文件夹),并将其组织到单独的目录中。此方法既有助于库充分利用特定的 CPU 架构,又能让你仅使用所需的库版本。要向 CMake 构建脚本中添加库的多个 ABI 版本,而不必为库的每个版本编写多个命令,可以使用 ANDROID_ABI 路径变量。此变量使用 NDK 支持的一组默认 ABI。例如:
add_library(...) set_target_properties( # Specifies the target library. imported-lib # Specifies the parameter you want to define. PROPERTIES IMPORTED_LOCATION # Provides the path to the library you want to import. imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
为了确保 CMake 可以在编写代码时#include头文件,需要使用 include_directories() 命令,并包含标头文件的路径:
include_directories( imported-lib/include/ )
然后将构件库链接到自己的原生库,以便在自己写的C代码中使用这些C/C++库,请将其添加到 CMake 构建脚本的 target_link_libraries() 命令中:
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
使用Android Studio将 Gradle 关联到原生库
可以使用 Android Studio UI 将 Gradle 关联到外部 CMake 或 ndk-build 项目:从 IDE 左侧打开 Project 窗格并选择 Android 视图。
右键点击想要关联到原生库的模块(例如 app 模块),并从菜单中选择 Link C++ Project with Gradle。你应看到一个如图 4 所示的对话框。
从下拉菜单中,选择 CMake 或 ndk-build。
如果选择 CMake,请使用 Project Path 旁的字段为外部 CMake 项目指定 CMakeLists.txt 脚本文件。
如果选择 ndk-build,请使用 Project Path 旁的字段为外部 ndk-build 项目指定 Android.mk 脚本文件。如果 Application.mk 文件与 Android.mk 文件位于相同目录下,Android Studio 也会包含此文件。
图 4.使用 Android Studio 对话框关联外部 C++ 项目。
点击 OK。
如果要手动配置 Gradle 以关联到原生库,你需要将 externalNativeBuild {} 块添加到模块级 build.gradle 文件中,并使用 cmake {} 或 ndkBuild {} 对其进行配置:
android { ... defaultConfig {...} buildTypes {...} externalNativeBuild { cmake{ path "CMakeLists.txt" } } }
相关文章推荐
- Android studio2.2配置opencv for android(CMake方式)
- MyEclipse Android2.2 开发环境搭建、配置(基于Windows 7操作系统、MyEclipse8.5、Android2.2)
- opencv配置详解(含windows和linux两种平台)
- Android自动化打包部署及配置文档(基于Jenkins平台)
- Webrtc入门——基于阿里云ubuntu 最新webrtc Android平台编译详细说明
- MAC平台下Xcode配置使用OpenCV的具体方法 (2016最新)
- 基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 4.0 最新发布版本 -下载使用说明
- opencv配置详解(含windows和linux两种平台)
- Opencv基于windows平台在vs2013下的安装配置
- Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解
- Android平台下OpenCV移植与使用---基于C/C++
- Android2.2 sdk开发环境和模拟器 配置图解版 (详解)
- 基于AgileEAS.NET SOA 平台SAAS架构技术的开源分销ERP系统-SmartERP.NET下载配置说明
- Android平台基于Pull方式对XML文件解析与写入方法详解
- MyEclipse Android2.2 开发环境搭建、配置(基于Windows 7操作系统、MyEclipse8.5、Android2.2)
- opencv 2.2在android平台移植
- 在Intel Android设备中安装和配置基于OpenCV的项目开发
- Android平台下OpenCV移植与使用---基于C/C++
- Android Studio 2.2 让你5分钟配置好 OpenCV for Android(java层和native层都可以使用)