前言

咱们知道 android设备可以直接运行 apk,或者使用 dalvikvm指令运行 dex文件中的程序, 但是这两者本质上使用的语言都是 java或者 smali,

如果需要执行C语言程序,我们通常需要借助 NDK编译成 so库, 那有没有不使用 NDK而直接编译c原生程序然后在安卓设备中运行的方式呢?

交叉编译

C语言是一门跨平台的语言,语言跨平台,但是程序不跨平台

也就是说在 windows平台下编译的程序只能在 windows平台上执行,linux亦是如此, 为什么会出现这种情况呢?

除了操作系统导致的文件格式不一致之外,本质上是因为不同平台 cpu使用的架构不一致导致

目前主流的三大 cpu架构 x86,ARM,MIPS ,每个架构都对应着属于自己的一套汇编指令集, 我们编写的程序,最终都会解码成汇编指令被 cpu所执行,

那么在 windows平台上进行本机编译的C语言代码,会根据当前平台的 cpu架构和操作系统生成只能在当前平台运行的程序

如果我想在 windows平台编译出能在 linux系统或者在 ARM设备中运行的程序, 那该怎么办呢?

这个时候我们就要使用交叉编译工具, 那这种编译的模式就不叫本机编译了,而叫做交叉编译

为什么需要交叉编译

场景:

  • 你正在编译一款 linux应用,但你手上只有一台 windows电脑,这个时候交叉编译能帮上大忙

  • 目标设备环境不允许,比如单片机, 内存和性能无法支持程序的编译

  • 一款配备新硬件的机器问世, 需要借助交叉编译来编译它的系统和编译器等

交叉编译工具

目前主流的交叉编译工具有 GCCClang, 接下来主要介绍 GCC的使用方法:

首先

交叉编译工具链的命名规则为:arch [-vendor] [-os] [-(gnu)eabi]

  • arch – 体系架构,如 ARMMIPS

  • vendor – 工具链提供商

  • os – 目标操作系统

  • eabi – 嵌入式应用二进制接口(Embedded Application Binary Interface)

根据对操作系统的支持与否, ARM GCC可分为支持和不支持操作系统

示例

  • arm-none-eabi :这个是没有操作系统的,适用于 ARM架构裸机,工具链提供商未知,嵌入式应用二进制接口,这个工具不支持那些跟操作系统关系密切的函数,比如fork(2)。他使用的是 newlib这个专用于嵌入式系统的C库。

  • arm-none-linux-eabi :用于 Linux的,ARM架构,使用 Glibc

    如果是裸机编译,由于没有操作系统进行文件识别翻译,因此编译出来的大部分是面向cpu内核的机器码文件单片机编译后的文件就是如此

回到主题

我需要用C语言编写一个能在安卓设备上运行的程序, 首先安卓设备大多采用的是 ARM架构 cpu, 系统采用的是 linux系统,

如果我们想在安卓设备中进行本机编译的话,实现起来比较困难, 那么咱们可以借助交叉编译工具,实现在 windows平台上编译出能够在 ARM+Linux平台上的可执行程序

这里我们使用 arm-none-linux-gnueabi-gcc 这款交叉编译工具

工具下载:

各个平台arm-none-linux-gnueabi交叉编译工具下载

或者

linux平台arm-none-linux-gnueabi工具直链下载

第一步 源码编写

新建 test.c文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21


#include <stdio.h>  





int main()  


{  


    printf("Hello world!\n");  


    return 0;  


}

第二步 源码编译

在命令窗口执行bin包下的 arm-none-linux-gnueabi-gcc指令

1
2
3


arm-none-linux-gnueabi-gcc test.c -o test -static

因为 Android 的 Linux 内核没有标准IO库函数,因此我们采用静态编译的方式进行编译 末尾 -static必须要有

第三步 将编译后的可执行文件传至安卓设备

1
2
3


adb push test /data/

第四步 执行文件

直接在控制台输入文件名即可执行

1
2
3


./test

如果提示权限拒绝,那么执行以下指令:

1
2
3


chmod 777 test

至此 程序正常运行 控台输出 Hello world!