您的位置:首页 > 移动开发 > Android开发

[置顶] 脱离AS在windows下使用CMake交叉编译for Android

2017-09-06 14:33 441 查看

脱离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是英文啊,全英文的,头疼.一怒之下想辞职走人(试用期).但是,我是那样的人吗?当然不是,我就不信凭我自己的能力,就不能把它搞出来…..于是,就有了下文.

  

准备 + 编译

下载所需材料

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



确认下载完成并配置相关的环境变量

  下载完成后,进入到SDK根目录下,看到上图中的SDK location了吗?我的就在这个目录下,然后进去你会看到多了一个文件夹cmake,之前应该是没有的(我猜的).一路点击这个文件夹,直到你能直视到cmake.exe,ninja.exe,这两个我能确认是一定能用到的,还有其他的几个,瞅一瞅 

  


  

  接下来配置cmake和ninja的环境变量.看到上图中那个耀眼的路径了吗,没错,就是它,将这个路径复制下来(如果有中文路径,那么我觉得你是被程序员耽误了的一个伟大的文员),然后 桌面 → 计算机 → 鼠标右键属性 → 高级系统设置 → 高级 → 环境变量,找到系统变量中的Path变量,点击编辑,将光标移到变量值的尾部,先瞅一瞅尾部有没有分号,没有的话追加一个英文分号,然后将上面复制的那个路径粘贴到分号之后,一路点击确定.

  验证环境变量
4000
是否配置正确,打开CMD窗口,输入cmake,如果提示如下图,那说明cmake的环境变量配置正确了,按理说ninja的也好了,输入ninja也可以验证,如下图.

  


  

  cmake以及ninja配置好后,打开Android NDK的存放路径,从build文件下进入,找到cmake目录,看该目录下有没有android.toolchain.cmake这个文件(由于我的ndk是我单独下载的,没有使用AS下载,所以我的ndk就和sdk路径分开了,如果是用AS下载的话,自己找找^_^),如果没有,怎么办呢?没有就不要往下阅读了,因为下面的操作需要有这个.

准备源码(这里以一个生成静态库的简单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;
}


在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)


在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


再罗嗦一下,看到脚本内容了吗?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这么几个.

运行脚本生成静态库

运行之前先看下的当前的目录结构:









打开命令窗口

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: