iOS | 交叉编译 工欲善其事,必先利其器

前言


在iOS设备上进行音视频的处理,往往要使用市面上比较流行的音视频相关库,比如音频编码的Lame,处理视频的FFmpeg,处理图片的OpenCv等.

而要能够运行这些库,我们必须将它们编译为能够在iOS设备上运行的文件.这就需要我们进行交叉编译.交叉编译是iOS通向音视频处理的第一道拦路虎,非常容易出错.本文最后以编译Lame库为例,介绍交叉编译的完整流程.

1 交叉编译

1.1 CPU的类型和指令集

对于一台电脑或者手机来说,核心部件是中央处理器CPU,所有指令的执行,最终都是依靠CPU来完成的.

指令集,是CPU能够执行的指令的集合,每种类型CPU都有自己的指令集,或者架构.

如果是不同系列CPU,指令集是互不兼容的,在指令集为A的CpuA上运行的代码,不能在指令集为B的CpuB上执行.
如果是相同系列的CPU,指令集向下兼容,低版本指令集A1的CpuA1上运行的代码,也可以在高版本指令集为A2的CpuA2上运行,但是不能够充分发挥CpuA2的性能.

1.2 iOS设备架构列表

iOS设备都虽然都是ARM系列的CPU,但是有不同的指令集:
armv6:iPhone,iPhone2,iPhone 3G
armv7:iPhone 4,iPhone 4S
armv7s:iPhone 5,iPhone 5S
arm64:iPhone6(P),iPhone7(P)
arm64e:iPhone XS
i386:32位模拟器
x64:64位模拟器

1.3 什么是交叉编译

编译型语言的源代码,比如C源代码,要能在PC上运行,需要经过编译,链接,成为PC可执行的二进制文件,然后才能在PC上运行.

同理,如果要在其他机器上运行,就必须编译,链接成为可以在其他机器上运行的代码.

源代码在机器A上的编译链接得到机器B上运行的代码.
如果机器B==机器A,那么就是本机编译.
如果机器B!=机器A,就是交叉编译.

比如,机器A是Mac,机器B是iPhone,那么就是在Mac上交叉编译生成iPhone的代码.

那么为什么不直接在iPhone上本机编译呢,因为iPhone上没有成熟的编译工具,以及足够的硬件条件去编译源代码.

1.4 iOS关于架构的设置

iOS中,有3个关于架构的设置:
BuildSettings|Architectures|Architectures
指定工程被编译成可支持哪些指令集类型,而支持的指令集越多,就会编译出包含多个指令集代码的数据包,对应生成二进制包就越大,也就是ipa包会变大。

BuildSettings|Architectures|Valid Architectures
限制可能被支持的指令集的范围,也就是Xcode编译出来的二进制包类型最终从这些类型产生,而编译出哪种指令集的包,将由Architectures与Valid Architectures(因此这个不能为空)的交集来确定.

BuildSettings|Architectures|Build Active Architecture Only
是否只生成支持当前连接设备的指令集的包.
一般Debug模式下设置为YES,加快编译速度;而Release模式下设置为NO,更好地适配各种机型.

一般情况下,我们编译armv7s和arm64的包就可以适配大部分机型了.

2 交叉编译Lame库

2.1 Lame库

Lame是一款效果很好的开源Mp3编码器,是在iOS设备上将音频编码为Mp3的最佳选择.
本章用最新版本3.100进行编译.

2.2 configure命令

这里先提一个文件,configure文件:



每一个符合GNU标准的软件包都会包含该命令.

交叉编译的整个流程,做了很多事情,我也不是很清楚具体都做了什么.我们需要关心的是,我们需要做什么:
我们需要通过以合适的方式运行configure命令,改名令执行的结果会生成合适的Makefile文件.
然后利用make和make install命令编译和安装整个库.

所以,我们在交叉编译中需要做的重点,就是用合适的参数去运行configure命令.

2.2 configure命令常用参数

我们输入命令./configure -h可以查看configure的帮助文档,会显示当前软件包的全部可选项配置.
下面介绍几个主要的配置:

  • 指定执行编译任务的主机的架构
    --build={Build}
    build: 执行代码编译的主机的架构,正常的话就是你的主机系统。
    这个参数一般由config.guess来猜就可以。当然自己指定也可以。

  • 指定输出位置
    --prefix={PREFIX}, 指定编译好的库放在哪个目录下,这是GNU大部分库的标准配置.

  • 指定要运行库的架构
    --host={HOST},指定要交叉编译出来的库,最终运行的平台,不同的架构CPU有不同的值:
    arm64:
    arm-apple-darwin
    armv7:
    arm-apple-darwin
    i386:
    i386-apple-darwin
    x86_64:
    x86_64-apple-darwin

  • 工具链的路径
    CC,交叉编译工具链的路径,其实就是gcc编译器的路径.不同架构的CPU有不同的值:
    x86_64:
    xcrun -sdk iphonesimulator clang -arch x86_64
    i386:
    xcrun -sdk iphonesimulator clang -arch i386
    arm64:
    xcrun -sdk iphoneos clang -arch arm64
    armv7s:
    xcrun -sdk iphoneos clang -arch armv7s

  • 编译参数
    CFLAGS,编译时需要带的参数,不同架构的CPU有不同的值:
    x86_64:
    -arch x86_64 -fembed-bitcode -miphoneos-version-min=7.0
    i386:
    -arch i386 -fembed-bitcode -miphoneos-version-min=7.0
    arm64:
    -arch arm64 -fembed-bitcode -miphoneos-version-min=7.0
    armv7s:
    -arch armv7s -fembed-bitcode -miphoneos-version-min=7.0
    其中,-fembed-bitcode表示该静态库使用了bitcode,关于bitcode,请参考后面的bitcode一节.

  • 链接参数
    LDFLAGS,链接时的参数,和CFLAGS保持一致.

  • 指定关闭动态链接
    --disable-shared:关闭动态链接,以便工具可以单独使用.

  • 指定不编译可执行文件.
    --disable-frontend,指定不编译LAME的可执行文件.

  • 指定创建静态库
    --enable-static,创建静态库,默认为YES.

软件工程师的职责之一,就是要把重复性的东西做成工具,让工作变得简单,从而创造快乐和价值.在本文末尾,会给出一个编译脚本.利用该脚本,可以方便地编译出i386,x86_64,armv7s,arm64架构的库.

2.3 查看编译成果物

每一个指令集的包中,有lib,include,share3个目录:



lib目录,存放的是我们的静态库文件,libmp3lame.a
include目录,是工程中需要使用的头文件,每个指令集对应的目录下的头文件是一样的.
share目录,包含了使用手册.

2.4 合并静态库

如果我们多个指令集的静态库,需要把他们合并才能使用.
如果这几个静态库的文件路径是libPath1,libPath2
使用以下命令合并:

$ lipo -create libPath1 libPath2 -output outputFilePath

合并后的库文件的目录为outputFilePath

验证是否合并成功,可使用file命令或者lipo -info命令:

$ file libmp3lame.a 
libmp3lame.a: Mach-O universal binary with 4 architectures: [i386:current ar archive random library] [arm64]
libmp3lame.a (for architecture i386):   current ar archive random library
libmp3lame.a (for architecture armv7s): current ar archive random library
libmp3lame.a (for architecture x86_64): current ar archive random library
libmp3lame.a (for architecture arm64):  current ar archive random library

或者:
$ lipo -info libmp3lame.a 
Architectures in the fat file: libmp3lame.a are: i386 armv7s x86_64 arm64 

2.5 bitcode

如果开启了bitcode
1,Xcode会将程序编译为一个中间表现形式(bitcode)
2,AppStore会将该中间形式的代码进行优化
总体来说,开启bitcode可以优化app的性能;

一个项目要使用bitcode,必须满足该项目中所有使用的第三方静态库都在编译时打开了bitcode.否则,只能关闭bitcode,从而得不到性能上的优化.

3 编译脚本的使用

编译脚本是一个sh文件,使用时先将脚本放到LAME库文件的根目录下.
然后在命令行中,切换到LAME库文件的目录下,然后执行:
sh ./LameBuilderForiOS.sh
该脚本会编译i386 x86_64 arm64 armv7s四个平台的库文件,输出在{LAME库目录}/thin文件夹中,然后将这四个库文件合并起来,输出在{LAME库目录}/fat文件夹中.

编译脚本地址和编译好的Lame库地址:
https://github.com/GikkiAres/LameBuilder

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容