脱离AS在windows下使用CMake交叉编译for Android

脱离AS在windows下使用CMake交叉编译for Android

  • 前言

      可能有Android开发经验并搞过jni的撸友知道,使用Android ndk 中的ndk-build 结合Android.mk+Application.mk就可以直接在AndroidStudio中生成所需要的动态库.so,甚至是静态库.a,当然,好像也可以脱离AndroidStudio生成.a或者.so,但是在androidStudio2.2+使用了另一种并且默认的CMake方式来开发JNI了,教程网上很多,我就不罗嗦了.
      
      可是,换了新工作,领导一来就让我脱离AndroidStudio在windows下生成native静态库,刚开始我是懵逼的,也是拒绝的,因为我一个Android码农,搞那玩意干嘛,你给我.a我自己用好了,我并不care他是怎么生成的(ps:主要是我也不会啊),网上搜了一整天,也尝试了一整天,什么鸟结果也没有,即使有,教程也是模模糊糊,加了好多之前大神的QQ发了多少邮件,但是大神总是很忙的,更没义务手把手教我,没办法,只有看CMake官网了,但是,那TM是英文啊,全英文的,头疼.一怒之下想辞职走人(试用期).但是,我是那样的人吗?当然不是,我就不信凭我自己的能力,就不能把它搞出来…..于是,就有了下文.
      

  • 准备 + 编译

    1. 下载所需材料
        利用AndroidStudio下载所需要的Android SDK,NDK,CMake.快捷键ctrl+alt+s 打开AS的Settings,选中Android SDK选项的SDK Tools标签,下载如图标记的东西,其中LLDB可用来调试native代码,所以LLDB用于源码就在AS中的情况(我是这么理解的).
      下载CMake

    2. 确认下载完成并配置相关的环境变量
        下载完成后,进入到SDK根目录下,看到上图中的SDK location了吗?我的就在这个目录下,然后进去你会看到多了一个文件夹cmake,之前应该是没有的(我猜的).一路点击这个文件夹,直到你能直视到cmake.exe,ninja.exe,这两个我能确认是一定能用到的,还有其他的几个,瞅一瞅 
        这里写图片描述
        
        接下来配置cmake和ninja的环境变量.看到上图中那个耀眼的路径了吗,没错,就是它,将这个路径复制下来(如果有中文路径,那么我觉得你是被程序员耽误了的一个伟大的文员),然后 桌面 → 计算机 → 鼠标右键属性 → 高级系统设置 → 高级 → 环境变量,找到系统变量中的Path变量,点击编辑,将光标移到变量值的尾部,先瞅一瞅尾部有没有分号,没有的话追加一个英文分号,然后将上面复制的那个路径粘贴到分号之后,一路点击确定.
        验证环境变量是否配置正确,打开CMD窗口,输入cmake,如果提示如下图,那说明cmake的环境变量配置正确了,按理说ninja的也好了,输入ninja也可以验证,如下图.
        这里写图片描述
        
        cmake以及ninja配置好后,打开Android NDK的存放路径,从build文件下进入,找到cmake目录,看该目录下有没有android.toolchain.cmake这个文件(由于我的ndk是我单独下载的,没有使用AS下载,所以我的ndk就和sdk路径分开了,如果是用AS下载的话,自己找找^_^),如果没有,怎么办呢?没有就不要往下阅读了,因为下面的操作需要有这个.

    3. 准备源码(这里以一个生成静态库的简单demo为例).为了方便演示,我就直接在桌面进行了.

      • 在桌面新建一个cmakeText文件夹
      • 在该文件夹下新建一个include文件夹和src文件夹,其中include文件夹用来存放c++头文件,src文件夹用来存放cpp文件,这些个文件夹可根据自己爱好来取名,等熟悉了这些都可以自己随便更改.
      • 在include文件下新建一个文本文件,里面的内容如下,之后将这个文本文件命名为Add.h

        int add(int a,int b);
      • 在src文件下新建一个文本文件,内容如下,之后将设个文件命名为Add.cpp

        
        #include "../include/Add.h"
        
        int add(int a,int b){
                return a + b;
        }
    4. 在cmakeText文件夹下新建一个名为CMakeLists.txt的文本文件,这个文件是cmake管理工程以及编译的脚本,名就是这么个名,不能改.其中就当前的这个demo来说,CMakeLists.txt的内容如下,想要了解更多CMake语法,请访问CMake官网

      cmake_minimum_required(VERSION 3.6)
      file(GLOB native_srcs "${CMAKE_SOURCE_DIR}/src/*.cpp")
      include_directories(${CMAKE_SOURCE_DIR}/include)
      
      #STATIC表示编译结果为静态库.a,如果想为动态库.so,可改为SHARED
      
      add_library(Add STATIC ${native_srcs}) 
      target_link_libraries(Add)
    5. 在cmakeText文件加下新建一个build文件夹,在文件加下新建一个windows批处理脚本build.bat,用记事本编辑该脚本,内容如下:

      set toolchain=E:/Android/ndk/android-ndk-r13b-windows-x86_64/android-ndk-r13b/build/cmake/android.toolchain.cmake
      set android_ndk=E:/Android/ndk/android-ndk-r13b-windows-x86_64/android-ndk-r13b
      set build_type=Release
      set gernerator="Ninja"
      if not exist %1 md %1
      cd %1
      cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="%1" -DCMAKE_GENERATOR=%gernerator%
      ninja
    6. 再罗嗦一下,看到脚本内容了吗?cmake ../..就是使用cmake来交叉编译当前工程,其中
      -DCMAKE_GENERATOR=”Ninja”是我看到google的AS工程中的[.externalNativeBuild]文件夹下面的内容后摸索出来的,下图是as自动生成的内容
      这里写图片描述
      开始我本不知道使用Ninja来编译,我就在AS的项目下找啊找啊找,最后看到上图中的build.ninja以及rules.ninja,刚开始我并不知道这是怎么来的,我百度+google得知是ninja.exe生成的,然后我就莫名其妙的将-DCMAKE_GENERATO的值设置为”Ninja”,于是,之前的千百次失败之后,终于成功了.脚本中的set build_type=Release 以及set gernerator=”Ninja”为新建变量,变量的值为等号=后的值,-DCMAKE_TOOLCHAIN_FILE=%toolchain%就是引用变量toolchain的值来给-DCMAKE_TOOLCHAIN_FILE赋值, %1%表示运行这个脚本的时候传进来的参数,这里我传进来的是Android的ABI名称,Android的ABI有:arm64-v8a,armeabi armeabi-v7a mips,mips64,x86,x86_64这么几个.

    7. 运行脚本生成静态库

      • 运行之前先看下的当前的目录结构:
        这里写图片描述

        这里写图片描述
        这里写图片描述
        这里写图片描述

      • 打开命令窗口
      • cd 到build文件目录下,输入build.bat armeabi 回车等待编译完毕
        这里写图片描述
        这里写图片描述

      • 再看build目录下,多了一个armeabi文件夹,文件夹的内容如下,怎么样,是不是跟google爹的一样,其中的libAdd.a就是我们需要的静态库.
        这里写图片描述

  • 后续

      以上批处理一次只能生成一种架构的库,我想了想,搞了一个粗暴的,一次生成全部的,只是编译过程很慢有点慢.生成全部的脚本如下:
      
    set toolchain=E:/Android/ndk/android-ndk-r13b-windows-x86_64/android-ndk-r13b/build/cmake/android.toolchain.cmake
    set android_ndk=E:/Android/ndk/android-ndk-r13b-windows-x86_64/android-ndk-r13b
    set build_type=Release
    set gernerator="Ninja"
    if not exist armeabi md armeabi
    cd armeabi
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="armeabi" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist armeabi-v7a md armeabi-v7a
    cd armeabi-v7a
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="armeabi-v7a" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist arm64-v8a md arm64-v8a
    cd arm64-v8a
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="arm64-v8a" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist mips md mips
    cd mips
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="mips" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist mips64 md mips64
    cd mips64
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="mips64" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist x86 md x86
    cd x86
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="x86" -DCMAKE_GENERATOR=%gernerator%
    ninja
    cd ..
    if not exist x86_64 md x86_64
    cd x86_64
    cmake ../.. -DCMAKE_TOOLCHAIN_FILE=%toolchain% -DANDROID_NDK=%android_ndk% -DCMAKE_BUILD_TYPE=%build_type% -DANDROID_ABI="x86_64" -DCMAKE_GENERATOR=%gernerator%
    ninja
      

      代码太乱,我上截图吧:
      这里写图片描述
      以上就是在windows下用cmake交叉编译的过程.自己不懂,走了很多弯路,用了差不多4天的时间,主要是看英文文档看的我翻皮水.因为在windows下用cmake+ninja交叉编译生成Android库的文章,我目前没有看到,所以记录下来,希望后来如果有需要的少走弯路,如果在linux下,这一切就太简单了.生成如windows的,linux的,以及ios平台下的库,网上有很多教程,其中我试了windows的,很简单,也能生成.

参考文档以及其他的连接:
Cmake关于交叉编译for Android的官网教程:
https://cmake.org/cmake/help/v3.9/manual/cmake-toolchains.7.html#cross-compiling-for-android
Github上android.toolchain.cmake地址,有多少人因为NDK中没有android.toolchain.cmake这个而放弃看这篇文章的.哈哈
https://github.com/taka-no-me/android-cmake
google爹的cmake(梯子)
https://developer.android.com/ndk/guides/cmake.html
Cmake的参数,可根据自己的需求来:
https://cmake.org/cmake/help/v3.9/manual/cmake-variables.7.html#variables-that-control-the-build

备注
这是我写csdn文章写得最好的一次,欢迎转载,转载注明出处.
技术+英文水平有限,有问题欢迎提出并留言或邮件给我:lijiayan_mail@163.com

没有更多推荐了,返回首页