概念
交叉编译:某个平台上,编译另一种平台的可执行程序,就是交叉编译,比如在 x86 平台上,编译 arm 平台的可执行程序。拿到我们实际中来说,就是用Mac系统编译出iOS系统或者Android系统能使用的文件库。
交叉编译链:在交叉编译时,由于主机与目标的体系架构、环境不同,所以交叉编译比本地编译复杂很多,需要一些工具来解决主机与目标不同特性的问题,这些工具构成的工具集就叫做交叉编译链。
交叉编译的基础是Shell编程。本章的重点会以LAME和FFmpeg为核心,讲解如何进行交叉编译,等音视频章节再详细讲解FFmpeg的交叉编译。
工具(专业术语)
无论是自行安装PC上的编译器,还是下载其他平台(Android或者 iOS)的交叉工具编译链,它们都会提供以下几个工具:CC、AS、 AR、LD、NM、GDB。
·CC:编译器,对C源文件进行编译处理,生成汇编文件。
·AS:将汇编文件生成目标文件(汇编文件使用的是指令助记符,AS将它翻译成机器码)。
·AR:打包器,用于库操作,可以通过该工具从一个库中删除或者
增加目标代码模块。
·LD:链接器,为前面生成的目标代码分配地址空间,将多个目标 文件链接成一个库或者是可执行文件。
·GDB:调试工具,可以对运行过程中的程序进行代码调试工作。
·STRIP:以最终生成的可执行文件或者库文件作为输入,然后消除
掉其中的源码。
·NM:查看静态库文件中的符号表。
·Objdump:查看静态库或者动态库的方法签名。
举个例子
正常编译一个程序的过程如下:
编译:gcc-c main.cpp./libmad/mad_decoder.cpp-I./libmad/include
打包:ar cr../prebuilt/libmedia.a mad_decoder.o
链接:g++-o main main.o-L../prebuilt-l mdedia
在这个过程中,gcc、ar、g++是我们用到的三个编译工具,在这里 没有用到的ranlib、gdb、nm、strip等都会包含在PC的编译器中,同样其 他平台提供的交叉工具编译链中也会包含这些命令行工具,比如 Android提供的NDK,其交叉工具编译链中的prebuilt/darwin-x86_64/bin 中,就包含了对应的gcc、ar、g++、gdb、strip、nm、ranlib等工具。
LAME的交叉编译
SourceForge下载最新的LAME版本,访问链接如下:
https://sourceforge.net/projects/lame/files/lame/3.99/
脚本
./configure \
--disable-shared \
--disable-frontend \
--host=arm-apple-darwin \
--prefix="./thin/armv7" \
CC="xcrun -sdk iphoneos clang -arch armv7" \
CFLAGS="-arch armv7 -fembed-bitcode -miphoneos-version-min=7.0" \
LDFLAGS="-arch armv7 -fembed-bitcode -miphoneos-version-min=7.0" make clean
make -j8 make install
下面分别解释一下这几个命令以及选项的意义。configure是符合 GNU标准的软件包发布所必备的命令,所以这里是通过configure的方式 来生成Makefile文件,然后使用make和make install编译和安装整个库。 可使用configure-h命令来查看一下configure的帮助文档,了解LAME的 可选配置项,具体如下。
·--disable-shared:通常是GNU标准中关闭动态链接库的选项,一般 是在编译出命令行工具的时候,期望命令行工具可以单独使用而不需要 动态链接库的配置。
·--disable-frontend:不编译出LAME的可执行文件。
·--host:指定最终库要运行的平台。
·--prefix:指定将编译好的库放到哪个目录下,这是GNU大部分库 的标准配置。
·CC:指定交叉工具编译链的路径,其实这里就是指定gcc的路径。
·CFLAGS:指定编译时所带的参数。Shell脚本中指定-march是 armv7平台,代表编译的库运行的目标平台是armv7平台;
·LDFLAGS:指定链接过程中的参数,同样也要带上bitcode的选项 以及开发者期望App支持的最低iOS版本的选项参数。
推荐已有的脚本
- 官网下载LAME源码,目前版本为3.100:https://sourceforge.net/projects/lame/files/lame/3.100/
- 下载外国大神的编译lame的shell脚本https://github.com/kewlbear/lame-ios-build
- 将shell脚本和lame文件夹拖入同一个文件夹,打开终端,
执行命令:
1、chmod 777 build-lame.sh 修改build-lame的读写权限
2、./build-lame.sh 执行脚本
我们来简单分析下build-lame.sh,如下图:
image.png
开始编译,执行完脚本后,生成fat-lame目录和thin-lame目录,分别存放合并所有指令集的静态库,以及各指令集的静态库。目录下会有bin、lib、include、share四个目录:
bin:由于在配置的时候裁剪掉了可执行文件,所以bin目录下不会有内容;
lib:链接过程中需要链接的libmp3lame.a静态库文件;
include:编译过程中需要引入的头文件lame.h;
share:不用管。
image.png
合并指令集
include里面的头文件都是一样的,不同指令集的静态库文件可以使用lipo命令合成一个静态库。在thin-lame目录下执行lipo命令:
lipo -create ./armv7/lib/libmp3lame.a ./arm64/lib/libmp3lame.a -output libmp3lame.a
附录:iOS指令集
arm64e: a12处理器 iPhone Xs Max|iPhone XS
arm64/armv8:iPhone8|iPhone X|iphone7|iphone7s|iphone7 plus|iPhone6s | iphone6s plus|iPhone6| iPhone6 plus|iPhone5S | iPad Air| iPad mini2(iPad mini with Retina Display)
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4
模拟器32位处理器测试需要i386架构
模拟器64位处理器测试需要x86_64架构
真机32位处理器需要armv7,或者armv7s架构
真机64位处理器需要arm64架构
附录:Android CPU 架构
ARMv5:第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢(只支持armeabi)
ARMv7:第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能(支持 armeabi 和 armeabi-v7a,目前大部分手机都是这个架构)
ARMv8:第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit(支持 armeabi-v7a、armeabi 和 arm64-v8a)
x86 :intel 32位,一般用于平板(支持 armeabi(性能有所损耗) 和 x86
x86_64: intel 64位,一般用于平板(支持 x86 和 x86_64)
MIPS:基本没见过(支持 mips)
MIPS64 : 基本没见过(支持 mips 和 mips_64)
网友评论