cmake使用独立工具链交叉编译可在android中运行的so包

在在命令行下用CMake交叉编译可在android中运行的so包一文中说了一下使用NDK自带的工具链来编译so包,当时讲到还有另一种方法来编译so包,即使用独立工具链来编译,现在就来讲一讲这种方式。主要包含以下两个步骤:

  • 编译独立工具链
  • 使用独立工具链编译so包

一、编译独立工具链

编译独立工具链是利用$NDK/tools下的 make-standalone-toolchain.sh 脚本来生成独立的交叉编译工具链,先用 –help 参数来看一下具体用法,我的ndk位置放在/home/hm/android_ndk_r15c

参数不多,有几个还是不再使用的,主要的只有以下几个:

  • –toolchain= 指定toolchain,在 $NDK/toolchains 目录下可以看到所有支持的编译链工具,根据目标cpu架构进行选择。

  • –arch= 指定目标cpu架构
  • –platform= 指定android平台,默认是[android-14]

好,现在来指定一下这几个参数,

  • –toolchain=arm-linux-androideabi-4.9
  • –arch=arm
  • –platform=android-15

然后运行这个脚本,稍等片刻就能看到如下的结果:

接下来我们根据输出的提示进入/tmp/ndk-hm目录下看看有些什么东西

嗯,只有一个压缩包和一个tmp目录,显然tmp目录是个临时目录,可以删除它,然后解压arm-linux-androideabi.tar.bz2,解压出来是这样子的:

这样独立工具链就编译好了,接下来看看怎么使用它。

二、编译so包

新建一个jni工程,目录如下:

内容都非常简单,其中JTest.java文件的内容如下,就一个带native修饰的方法:

package com.jni;public class JTest{    public native String getStringFromC();}

CTest.c文件的内容如下,它是根据JTest.java文件的头文件来编写的,实现了JTest.java中的native方法,打印了一句日志,返回了一个字符串:

 /* DO NOT EDIT THIS FILE - it is machine generated */#include #include /* Header for class com_jni_JTest */#ifndef _Included_com_jni_JTest#define _Included_com_jni_JTest#ifdef __cplusplusextern "C" {#endif/* * Class:     com_jni_JTest * Method:    getStringFromC * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_jni_JTest_getStringFromC  (JNIEnv * env, jobject obj){__android_log_print(ANDROID_LOG_DEBUG,"CTest.c","Hello World C!\n");    return (*env)->NewStringUTF(env, "I am from CTest.c");    }#ifdef __cplusplus}#endif#endif

CMakeLists.txt中的内容就是重点了,这里面指定了刚刚编译好的独立工具链,内容如下:

cmake_minimum_required(VERSION 3.4.1)set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")# Android 5.0 以上需要在此处设置 PIEset(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")# 配置使用 NDK Standalone Toolchain 编译set(NDK_STANDALONE_TOOLCHAIN /tmp/ndk-hm/arm-linux-androideabi)set(CMAKE_SYSTEM_NAME Android)set(CMAKE_SYSTEM_VERSION 21)set(CMAKE_C_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/clang)set(CMAKE_CXX_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/clang++)set(CMAKE_FIND_ROOT_PATH ${NDK_STANDALONE_TOOLCHAIN})# 使用 NDK 提供的头文件add_definitions("--sysroot=${NDK_STANDALONE_TOOLCHAIN}/sysroot")add_library(myso SHARED CTest.c)set_target_properties(myso                      PROPERTIES                      LIBRARY_OUTPUT_DIRECTORY                      "${CMAKE_CURRENT_SOURCE_DIR}/lib")include_directories(/home/hm/JDK/jdk1.8.0_151/include /home/hm/JDK/jdk1.8.0_151/include/linux)target_link_libraries(myso                     log)

进入build目录,执行一下:

~/cmake_sample/cross_for_android/build$ cmake ../c/

~/cmake_sample/cross_for_android/build$ make

进入c/lib目录看一下结果:

嗯,so包已经出来了,接下来建个工程验证一下,看看这个so包能不能用。


三、验证

跟之前一样,建个测试工程,将编译好的so包及JTest.java文件拷到工程中,具体步骤就不多说了,很简单,最后建好的工程目录如下:

在MainActivity.java中调用native方法:

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        String str = new JTest().getStringFromC();        System.out.println(str);        ((TextView)findViewById(R.id.tvHello)).setText(str);    }}

跑一下工程,看看有没有输出日志:

没问题,返回值没错,在CTest.c中输出的日志也打出来了,说明这个so包是可用的。

最后,上源码:

demo源码:https://github.com/MingHuang1024/CrossCompileForAndroid

测试工程的源码就不上了,需要的可以联系我。



由于水平有限,如果文中存在错误之处,请大家批评指正,欢迎大家一起来分享、探讨!

博客:http://blog.csdn.net/MingHuang2017

GitHub:https://github.com/MingHuang1024

Email:MingHuang1024@foxmail.com

微信:724360018

更多相关文章

  1. Android应用程序访问linux驱动第四步:实现android应用程序
  2. 【android开发】10款实用的Android(安卓)UI工具,非常有用!
  3. ubuntu中adb安装与使用,android真机调试进入data/data目录
  4. Android(安卓)API Guides---Data Storage
  5. java.lang.TypeNotPresentException: Type com.sht.entity.Store
  6. Android(安卓)可视化性能监控和辅助小工具合集
  7. 9.5.3 Android(安卓)Apk 反编译 & 9.5.4 Android(安卓)Apk 加密
  8. 为什么Android应用用Java开发,为什么Android大型游戏要用数据包?这
  9. 【Android学习总结】之eclipse工程目录结构说明及使用

随机推荐

  1. HBase重磅 | ApsaraDB HBase数据存储与分
  2. 快速掌握 10 个 HTML5 必备技巧
  3. HBase解读 | 阿里云HBase SQL(Phoenix)服
  4. Python爬取小说
  5. dns查询2:ResolveDns
  6. 盘点2019年晋升为Apache TLP以及进去Apac
  7. dns查询1:DomainNameResolve.java
  8. 网站为什么要使用CDN加速?这5点你要明白
  9. Ulysses 22 发布功能加强,允许自定义分组
  10. coremail导出用户草稿箱中的邮件并打包