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

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

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

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

一、编译独立工具链

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

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

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

  • –arch=<name> 指定目标cpu架构
  • –platform=<name> 指定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 <jni.h>
#include <android/log.h>
/* Header for class com_jni_JTest */
#ifndef _Included_com_jni_JTest
#define _Included_com_jni_JTest
#ifdef __cplusplus
extern "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 以上需要在此处设置 PIE
set(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

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在Linux使用CMake进行交叉编译的步骤如下: 1. 首先,需要编写一个适用于目标平台的工具文件。这个文件可以指定交叉编译工具的路径、系统名称等信息。例如,可以在工具文件设置CMAKE_SYSTEM_NAME为Linux,指定交叉编译工具的路径为TOOLCHAIN_PATH。 2. 在执行CMake命令开始构建时,可以使用参数--toolchain或者-DCMAKE_TOOLCHAIN_FILE=指定工具文件的路径。这样,CMake就会使用指定的工具文件进行交叉编译。 举个例子,假设工具文件的路径为/path/to/toolchain-file.cmake,可以使用以下命令进行交叉编译cmake ... --toolchain=/path/to/toolchain-file.cmake 或者 cmake ... -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain-file.cmake 这样,CMake就会根据工具文件的设置进行交叉编译,生成适用于目标平台的库文件或可执行文件。 引用内容: [1] 交叉编译笔者在工作经常会遇到。笔者开发使用的宿主机一般都是Linux(Ubuntu),交叉编译的目的基本都是为了将程序代码编译成目标嵌入式平台的库文件,然后再在目标系统上调用集成,一般都是ARM系列的CPU。而对于不同操作系统(Windows、Linux、MacOS)之间的交叉编译,则主要是为了编译示例程序,方便在不同操作系统上进行展示或者调试。 [2] toolchain.cmake set(CMAKE_SYSTEM_NAME Linux) #这里以Linux为例 set(TOOLCHAIN_PATH /home/test/src/func/build) 这里指定toolchain的目录 set(TOOLCHAIN_PATH ${tools}/usr/local/arm/gcc-linaro-6.5.0-2018.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc) 这里指定交叉编译工具的路径 set(TOOLCHAIN_PATH ${tools}/usr/local/arm/gcc-linaro-6.5.0-2018.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g ) 这里指定交叉编译工具的路径 [3] 在需要进行交叉编译的时候,先编写一个适用于目标平台的工具文件,然后在执行cmake命令开始构建时,可以使用参数--toolchain或者-DCMAKE_TOOLCHAIN_FILE=指定工具文件的路径即可: cmake...--toolchain<path/to/toolchain-file> #or cmake...-DCMAKE_TOOLCHAIN_FILE=<path/to/toolchain-file>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值