设为首页 加入收藏

TOP

CMake个人理解和使用(三)
2023-07-23 13:27:43 】 浏览:88
Tags:CMake 解和使
ake命令的时候,需要使用 -G "Unix Makefiles"来改变这一行为。但这还不够,因为CMake编译是需要指定编译器的。而Android上的C,C++编译器通常以NDK的方式提供,所以,我们需要下载好NDK。在NDK中,会同时为我们提供两种工具,一种就是编译器,另一种就是android.toolchain.cmake,这也是CMake命令构成的文件,里面为我们交叉编译指定了很多预设值,能大大减轻我们的工作。

编写编译脚本

前面说了,交叉编译就是改变CMake预设值,而改变这预设值的方式有两种,我们要结合起来使用。一种是通过NDK提供的android.toolchain.cmake文件。 android.toolchain.cmake中以设置了绝大部分的值,但是这些配置也是很灵活的,还有很大的配置空间。因此,根据用户的需求不同,我们还需要在执行CMake命令时动态传递一些值,以使CMake能正确完成工作。这就是另一种方式——选项。传递选项会以-D开头,后面跟着某个CMake的预定义变量由于选项很多,而且大多比较复杂,所以,最好还是通过脚本文件来记录并且修改。以下就是Windows平台上编译Android代码需要指定的几个选项,我将逐个介绍这些必要的配置。

  • -DCMAKE_SYSTEM_NAME=Android这个配置是告诉CMake需要生成Android平台的库,也就是执行交叉编译。
  • -DANDROID_ABI=x86这个配置是告诉CMake生成库适用的架构平台。熟悉Android开发的读者应该不会陌生,支持的值会根据NDK的变化而有所变化,如早期的armeabi已经在 NDK r17中移除了,现在主流的还有四种armeabi-v7aarm64-v8ax86x86_64.根据需要把值替换就行。
  • -DANDROID_PLATFORM=android-28,这个值其实不是特别必要,因为有预设值,但是为了可控,还是需要指定一个。它是用来确定库支持的最低系统版本的。
  • -DCMAKE_TOOLCHAIN_FILE=C:/Users/Leroene/AppData/Local/Android/Sdk/ndk/21.0.6113669/build/cmake/android.toolchain.cmake,这是上面提到的预设文件。需要注意的是,NDK中有多个以这个名字命名的文件,假如指定错误,可能会导致CMake出错,所以我的经验就是,更改版本号(C:/Users/Leroene/AppData/Local/Android/Sdk/ndk/21.0.6113669)及前面的路径,后面的保持不变。
  • -DCMAKE_MAKE_PROGRAM=C:/Users/Leroene/AppData/Local/Android/Sdk/ndk/21.0.6113669/prebuilt/windows-x86_64/bin/make最后一个参数是指定make程序的路径,由于我们指定生成了make项目的代码,而Windows通常没有make可执行文件,所以我们需要让CMake找到make文件以完成编译。这里我的经验也是保持后面的不变,修改前面的,并保持版本一致以避免BUG。
  • -DCMAKE_BUILD_TYPE=Release,指定构建类型,这应该很常见了。

至此Windows交叉编译Android库的所有配置都讲解完了。让我们来看看它完整的例子

@echo off
rd /s /q build
mkdir build
cd build
cmake -G "Unix Makefiles" ^
-DCMAKE_TOOLCHAIN_FILE=C:/Users/Leroene/AppData/Local/Android/Sdk/ndk/21.0.6113669/build/cmake/android.toolchain.cmake ^
-DCMAKE_MAKE_PROGRAM=C:/Users/Leroene/AppData/Local/Android/Sdk/ndk/21.0.6113669/prebuilt/windows-x86_64/bin/make ^
-DANDROID_PLATFORM=android-28 ^
-DCMAKE_SYSTEM_NAME=Android ^
-DANDROID_ABI=x86 ^
-DCMAKE_BUILD_TYPE=Release ^
../3rd
cmake --build .

从上面可以看到,这些选项后面都跟着一个^符号,这不是cmake的一部分,只是为了我们阅读方便,特意书写成这样的,这是在Windows平台上批处理使用的命令换行符,它的作用就是告诉命令解析器,这个命令还没有结束,接着往下面解析,该功能在Linux,MacOS上对应于\。现在有了这些配置之后,该怎么使用呢?其实也很简单,只需要将这些命令存储在android.bat文件中,在CMD中切换到当前目录,执行这个文件就能在build目录中找到以libsum.a命名的静态库文件了。下一步,我们试着用这个库文件运行在模拟器中。

在Android项目中使用CMake

在Android平台中,也使用CMake来管理jni的项目,配合Gradle一起完成构建工作。这和普通的CMake项目最大的不同是,我们通常需要引用多个Android相关的库,如log,android等.这些库通常是由NDK提供的,我们仿照默认生成的CMakeLists.txt文件编写就可。

目录结构

接下来,为了描述方便,我们先来看一下现在的目录结构(为了避免混乱,这里只列出比较有代表性的文件)

CMakeProject
│  android.bat
│  CMakeLists.txt
│  main.cpp
│  
├─3rd
│      CMakeLists.txt
│      lib.cpp
│      lib.h
│      
└─Android
    │  build.gradle
    │       
    ├─app
    │  │  build.gradle
    │  │                   
    │  ├─libs
    │  └─src                     
    │      ├─main
    │      │  │  AndroidManifest.xml
    │      │  │  
    │      │  ├─cpp
    │      │  │      CMakeLists.txt
    │      │  │      native-lib.cpp
    │      │  │      
    │      │  ├─java
    │      │  │  └─me
    │      │  │      └─hongui
    │      │  │          └─cmakesum
    │      │  │                  MainActivity.kt
    │      │  │                  
    │      │  ├─jniLibs
    │      │  │  └─x86
    │      │  │          libsum.a

在原来的目录根目录下新建了Android子目录,该目录是一个Android C++工程,所以相比其他普通Android工程,它多了个cpp目录,后面我们主要的修改都是发生在该目录下。

原来的根目录,为了不增加复杂度,我们只作为生成静态库的功能存在,所以和上面的示例相比,没有任何修改。

构建静态库

首先,我们回到根目录。使用根目录下的android.bat批处理生成Android上可用的静态库,也可以修改android.bat文件中的-DANDROID_ABI选项的值,生成其他架构的静态库,但这需要和jniLibs目录下的目录要一一对应,否则可能链接失败。如我生成的libsum.a

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++基础知识总结 下一篇驱动开发:内核ShellCode线程注入

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目