Android NDK 12 交叉编译

2018-07-24  本文已影响171人  seraphzxz

前言

简单地说,交叉编译就是程序的编译的环境和它的运行的环境不一样,即在一个平台上生成另一个平台上的可执行代码。需要使用交叉编译的主要原因是由于目标环境中各种资源都相对有限,所以很难直接进行本地编译。

一、交叉编译工具链

1.1、什么是交叉编译工具链

交叉工具链是指可以生成目标环境可运行代码的工具集。在 Linux 系统中的编译工具链包括以下一些工具,编译器 gcc,链接器 ld,归档工具 ar 等,如果在 Linux 环境中交叉编译 Android 系统环境可运行的代码,是不能直接使用 Linux 下的编译工具的,而应该使用 Android NDK 里的工具链,它们对应的名子为 arm-linux-android-gcc,arm-linux-android-ld 等。

1.2、交叉编译工具的命名规则

交叉编译工具的命名形式如下所示:

arch-[vendor]-kernel-system-toolname

它由五部分组成,下面分别解释一下每部分的含义:

  1. arch,指的是 CPU 架构,一般包括如下几种架构:
  1. verdor,一般指的是生产厂商,如果没有生产厂商可以为空。
  2. kernel,指的目标环境使用的 kernel,以 android 为例,它使用的是 linux 内核,所以在这部分会填写为 linux。
  3. system,指的是哪个系统,如:
  1. toolname: 指的是 gcc,ld,ar 等。

所以可以看到 android 的编译工具的名子会写成 arm-linux-andirod-gcc。

1.3、交叉编译常用变量说明

在做交叉编译时,常会在脚本中定义一些环境变量以方便我们命名用,常用的环境变量如下:

二、如何进行交叉编译

通过设置 configure 参数来生成交叉编译的 Makefile 文件:

例子:

以 ffmpeg 的交叉编译为例,来看一下如何生成交叉编译的 Makefile:

./configure --target-os=linux --arch=arm --enable-cross-compile --cross-prefix=arm-linux-androideabi-
--sysroot=~Library/Android/sdk/ndk-bundle/platforms/android-9/arch-arm

执行后的结果如下:

install prefix            /usr/local
source path               .
C compiler                arm-linux-androideabi-gcc
C library                 bionic
host C compiler           gcc
host C library
ARCH                      arm (armv5te)

三、使用 ndk-build 编译 NDK 程序

Google 提供了一系列脚本工具,以方便大家做 Android NDK 方面的开发,其中最重要的是 ndk-build 脚本。有了这些脚本,开发者就不必再定义各种环境变量,只需要提供两个 Makefile 片段指明要编译哪些 C/C++文件,生成哪个目标环境的程序就好了。ndk-build 脚本工具会自动检测各种环境变量、目标环境编译器等,最终完成交叉编译。

3.1 NDK-BUILD 的工作

先来看一下 ndk-build,通过查看 ndk-build 源码可以看到,它执行的是类似于

$GNUMAKE -f <ndk>/build/core/build-local.mk <parameters> 

这样的命令,实际就是自动检测并设置环境变量。执行 ndk-build NDK_LOG=1 命令,会看到下面的信息:

Android NDK: NDK installation path auto-detected:
Android NDK: GNU Make version 3.81 detected
Android NDK: Host OS was auto-detected: darwin
Android NDK: Host operating system detected: darwin
Android NDK: Host CPU was auto-detected: x86
Android NDK: HOST_TAG set to darwin-x86
Android NDK: Host tools prebuilt directory:
#这里检测到编译器地址
~/Library/Android/sdk/ndk-bundle/prebuilt/darwin-x86_64/bin
Android NDK: Found platform root directory:
#这里检测到 platforms 目录地址
~/Library/Android/sdk/ndk-bundle/platforms
#下面列出了所有支持的 platform
Android NDK: Found supported platforms: android-12 android-13 android-14 android-15 android-16 android-17
android-18 android-19 android-21 android-22 android-23 android-24 android-26 android-9
#列出支持的目标环境
Android NDK: PLATFORM android-12 supports: arm mips x86
......
#下面是每个目标环境的的环境树
Android NDK:   ABI arm sysroot is: /Users/lichao/Library/Android/sdk/ndk-bundle/platforms/android-12/arch-arm
Android NDK:   ABI mips sysroot is: /Users/lichao/Library/Android/sdk/ndk-bundle/platforms/android-12/arch-mips
Android NDK:   ABI x86 sysroot is: /Users/lichao/Library/Android/sdk/ndk-bundle/platforms/android-12/arch-x86

通过上面的分析就应该清楚 ndk-build 主要作什么事情了。既然 Google 已经给我们提供了这么方便的交叉编译工具,那作为开发者还需要做下面两件事儿:

  1. 编写 C/C++ 代码

  2. 编写 Android.mk 和 Application.mk 两个 Makefile 片段

3.2、Android.mk 与 Application.mk

下面就来看一下两个 Makefile 片段 Android.mk 和 Application.mk 是做什么用的。

3.2.1、Android.mk

先来看一下 Android.mk 的例子:

LOCAL_PATH       :=  $(call my-dir)
include              $(CLEAR_VARS)
LOCAL_MODULE     :=  hello_jni
LOCAL_SRC_FILES  :=  hello_jni.c
include              $(BUILD_SHARED_LIBRARY)

每行语句的作用如下:

请注意,它不会清除 LOCAL_PATH。此变量必须保留其值,因为系统在单一 GNU Make 执行环境(其中所有变量都是全局的)中解析所有构建控制文件。在描述每个模块之前,必须声明(重新声明)此变量。

3.2.2、Application.mk

再来看一下 Application.mk 的例子:

APP_PLATFORM := android-9
APP_STL := gnustl_static
APP_CFLAGS := -Wno-error=format-security
APP_ABI := armeabi armeabi-v7a arm64-v8a
APP_OPTION := release

每行的作用如下:

此变量包含目标 Android 平台的名称。NDK API 级别与 Android 版本对照表如下:

NDK 支持的 API 级别 Android 版本
9 2.3 到 3.0.x
12 3.1.x
13 3.2
14 4.0 到 4.0.2
15 4.0.3 和 4.0.4
16 4.1 和 4.1.1
17 4.2 和 4.2.2
18 4.3
19 4.4
21 4.4W 和 5.0

通过上面的分析,我们可以知道 Google 为了开发者更容易的开发 NDK 程序,给我们提供了一套交叉编译的工具,大大降低了开发 NDK 程序的难度。

原文连接:Linux/Mac 交叉编译 Android 程序 & 深入理解使用ndk-build编译NDK程序

上一篇下一篇

猜你喜欢

热点阅读