编译Android平台libRTMP库

操作系统: Mac OSX
NDK: android-ndk-r10e-darwin-x86_64
编译目标: librtmp.a librtmp.so

简介

Android 官方提供了三种编译方式,分别是 prebuild 工具,standalone toolchain 工具,ndk-build 工具。

prebuild 工具,是官方提供的预编译好的工具,使用时需要手动指定系统头文件和链接库文件;
standalone toolchain 工具,已经内置了系统头文件和链接库文件,并且提供一些高级用法;
ndk-build 工具,依赖于 GNU Make 的编译系统,使用时需要 Android.mk Application.mk 配合;

由于 librtmp 官方已经在源码中提供了 Makefile 编译脚本,替换脚本中的 GCC AR LD 变量是很方便的,因此我们选择使用 standalone toolchain 工具的方式来编译 librtmp 库。

简单的操作步骤如下:
安装NDK;
制作Standalone Toolchain;
编译librtmp库;

安装NDK

Android 官网提供的下载地址 Android NDK r10e (已失效)
百度云盘提供的下载镜像包 Android NDK r10e

如果是zip包,解压到任意位置即可;
如果是bin包,需要授予可执行权限,运行安装;

chmod a+x android-ndk-r10e-darwin-x86_64.bin
./android-ndk-r10e-darwin-x86_64.bin

制作Standalone Toolchain

关于如何使用 Standalone Toolchain 官网已经给出了详细的文档 Standalone Toolchain
注: 如果你觉得英文比较难懂,可以查看我的中文翻译 Standalone Toolchain(中文翻译)

制作支持 arm, arm64, mips, mips64, x86, x86_64 六种架构的 Standalone Toolchain 工具,下面提供简单的一键生成脚本:build-toolchain.sh
注: 使用脚本前需要定义 $ANDROID_NDK 系统环境变量,指向上一步安装的NDK根目录。

#! /bin/sh

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/arm
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=arm --platform=android-21 --toolchain=arm-linux-androideabi-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/arm

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/arm64
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=arm64 --platform=android-21 --toolchain=aarch64-linux-android-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/arm64

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/mips
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=mips --platform=android-21 --toolchain=mipsel-linux-android-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/mips

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/mips64
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=mips64 --platform=android-21 --toolchain=mips64el-linux-android-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/mips64

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/x86_64
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=x86_64 --platform=android-21 --toolchain=x86_64-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/x86_64

mkdir -p $HOME/Documents/app/Android-NDK-Toolchain/x86
$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --arch=x86 --platform=android-21 --toolchain=x86-4.9 --system=darwin-x86_64 --install-dir=$HOME/Documents/app/Android-NDK-Toolchain/x86

echo ------------
echo now ndk toolchain at: $HOME/Documents/app/Android-NDK-Toolchain
echo ------------

运行脚本后,默认生成的工具位于 $HOME/Documents/app/Android-NDK-Toolchain。

编译librtmp库

在开始之前,我们需要了解几个概念,编译librtmp库需要使用哪些编译工具,需要兼容哪些CPU架构,如何选择合适的ABI?

需要使用哪些编译工具?

C/C++编译器 CC;
静态库打包工具 AR;
动态库链接工具 LD;

需要兼容哪些CPU架构?

注: 这里挖了一个坑,等待有人来填~

如何选择合适的ABI?

关于 Android 系统支持的 ABI 列表,官方已经给出了说明,Supported ABIs,这里我们只摘取其中有用的部分进行讲讲解:

ABI的定义主要是为了照顾不同指令集的兼容性,详细的对应关系如下:

armeabi 兼容 ARMV5TE,更高版本ARMV5,Thumb-1 指令集,不支持硬件 float 运算;
armeabi-v7a 兼容 armeabi,Thumb-2,VFPv3-D16,其他可选指令集,不兼容 ARMv5, ARMv6 设备;
arm64-v8a 兼容 AArch-64 指令集;
x86 兼容 x86 (IA-32),MMX,SSE,SSE2,SSE3,SSSE3 指令集,不支持 MOVBE,SSE4 指令集;
x86_64 兼容 x86-64,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1, SSE4.2,POPCNT 指令集;
mips 兼容 MIPS32r1,更高版本MIPS32 指令集,使用硬件float并指定CPU:FPU时钟比为2:1;不支持 micromips,MIPS16 指令集;
mips64 兼容 MIPS64r6 指令集;

弄清楚了上面这些内容后,我们开始配置相应的GCC选项来适配不同的CPU架构和指令集;
GNU GCC 官方提供的ARM架构可用选项 ARM Options
GNU GCC 官方提供的x86架构可用选项 x86 Options
GNU GCC 官方提供的MIPS架构可用选项 MIPS Options

整理后,
armeabi 选项 -march=armv5te -msoft-float
armeabi-v7a 选项 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb
arm64-v8a 选项 -march=armv8-a
x86 选项 -mtune=intel -m32 -mmmx -msse2 -msse3 -mssse3
x86_64 选项 -mtune=intel -m64 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt
mips 选项 -march=mips32 -mfp32 -msoft-float -mno-micromips
mips64 选项 -march=mips64r6

注: 由于MIPS未找到同时使用硬件float并指定CPU:FPU时钟比为2:1的设置方法,因此使用软件float代替。

改造Makefile

下面改造librtmp库自带的Makefile脚本来适配产生不同兼容性的库,
注释掉CC AR LD 改为使用系统环境变量,注释 CRYPTO 来禁用 SSL,为 CFLAGS 增加系统环境变量 $(ARCH_CFLAGS) 输入,

#CC=$(CROSS_COMPILE)gcc
#LD=$(CROSS_COMPILE)ld
#AR=$(CROSS_COMPILE)ar

#CRYPTO=OPENSSL

CFLAGS=-Wall $(ARCH_CFLAGS) $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF)

改造完成之后,就可以使用下面的命令来生成librtmp库了,

## armeabi-v7a
export CC=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-ar
export ARCH_CFLAGS=-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -mthumb
make all

## armeabi
export CC=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/arm/bin/arm-linux-androideabi-ar
export ARCH_CFLAGS=-march=armv5te -msoft-float
make all

## arm64-v8a
export CC=$HOME/Documents/app/Android-NDK-Toolchain/arm64/bin/aarch64-linux-android-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/arm64/bin/aarch64-linux-android-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/arm64/bin/aarch64-linux-android-ar
export ARCH_CFLAGS=-march=armv8-a
make all

## x86
export CC=$HOME/Documents/app/Android-NDK-Toolchain/x86/bin/i686-linux-android-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/x86/bin/i686-linux-android-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/x86/bin/i686-linux-android-ar
export ARCH_CFLAGS=-march=i686 -mtune=i686 -m32 -mmmx -msse2 -msse3 -mssse3
make all

## x86_64
export CC=$HOME/Documents/app/Android-NDK-Toolchain/x86_64/bin/x86_64-linux-android-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/x86_64/bin/x86_64-linux-android-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/x86_64/bin/x86_64-linux-android-ar
export ARCH_CFLAGS=-march=core-avx-i -mtune=core-avx-i -mx32 -mmmx -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mpopcnt
make all

## mips
export CC=$HOME/Documents/app/Android-NDK-Toolchain/mips/bin/mipsel-linux-android-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/mips/bin/mipsel-linux-android-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/mips/bin/mipsel-linux-android-ar
export ARCH_CFLAGS=-march=mips32 -mfp32 -msoft-float
make all

## mips64
export CC=$HOME/Documents/app/Android-NDK-Toolchain/mips64/bin/mips64el-linux-android-gcc
export LD=$HOME/Documents/app/Android-NDK-Toolchain/mips64/bin/mips64el-linux-android-ld
export AR=$HOME/Documents/app/Android-NDK-Toolchain/mips64/bin/mips64el-linux-android-ar
export ARCH_CFLAGS=-march=mips64r6
make all

librtmp库适用范围

librtmp.a适用范围

Android 项目中,其他 so 动态链接库可以引入librtmp头文件,并链接librtmp.a;

librtmp.so适用范围

Android 项目中,其他 so 动态链接库可以链接librtmp.so;

注: 由于这种编译方法并未引入 jni.h 头文件,也未定义 java native method 方法,因此并不能在 JAVA 层直接调用;

参考

Standalone Toolchain
Standalone Toolchain(中文翻译)
Supported ABIs
GNU GCC ARM Options
GNU GCC x86 Options
GNU GCC MIPS Options
List of CPU architectures
ARM Thumb Thumb-2指令集