概述
——
前文《百度App Objective-C/Swift 组件化混编之路(二)- 工程化》已经介绍了百度App 组件内 Objective-C/Swift 混编、单测、以及组件间依赖、二进制发布、集成的工程化过程。下面重点介绍百度App 组件化 Objective-C/Swift 组件化混编改造实践,希望能对大家有所启发和帮助。
组件化混编改造
——
百度App 经过组件化和二进制化改造后,组件的编译产物主要是 static_framework (.framework) 和 static_library(.a)两种类型,因此百度App 混编主要是围绕 static_framework 和 static_library 进行。
Swift 5.0 ABI(Application Binary Interface)稳定后,操作系统统一了 ABI 标准,编译出的二进制产物能在不同的 runtime 下运行。但 ABI 稳定是使用二进制发布框架(binary frameworks)的必要非充分条件。随后的 Swift 5.1 又推出了 Module Stability 特性,使不同版本的 Swift 编译器生成的二进制可以在同一个应用程序中使用,这才扫除二进制广泛高效使用的障碍。
丨1 static_library 的问题
在 Xcode 中, static_framework 的 Build Settings 设置 BUILD_LIBRARY_FOR_DISTRIBUTION(见图1)为 YES,就开启了 Module Stability。
而在 static_library 中, BUILD_LIBRARY_FOR_DISTRIBUTION 设置为 YES 后编译组件,会产生using bridging headers with module interfaces is unsupported
错误。可见 bridging header 与 Swift 的二进制接口文件(.swiftinterface)无法兼容,无法做到 Module Stability。
由于在 static_library 内混编会导致不同 Swift 编译器版本上生成的二进制不兼容,所以 static_library 要支持组件内混编和二进制兼容性发布必须做 Framework 化(static_framework)改造,下面详细说明改造过程。
丨2 组件 Framework 化改造
将 static_library 改成 static_framework,百度App 借助 EasyBox 可以快速完成,例如:
# 在 Boxfile 文件内,将 target 从 :static_library 修改为 :static_framework# 然后 box install 就完成转化box 'BBAUserSetting', '2.2.6', :target => :static_framework
修改相关头文件引用方式,例如:
// static_library 引用头文件方式 #import "ComponentA.h"// static_framework 引用头文件方式 #import
丨3 去预编译头文件 和 规范公开头文件
百度App 部分 static_library 含有预编译头文件(pre-compiled header),主要作用是加快编译速度。将公开头文件放入预编译头文件中,组件内的头文件和源文件不用再逐一显式引用,但 pch 的使用有两个问题:
不能作为二进制形态组件的一部分。
当 static_library 改造成 static_framework(支持 module 可以提升编译速度)后,会导致组件内头文件缺少公用头文件的引用,造成组件编译错误。
基于以上原因,需要删除预编译头文件,规范组件公开的头文件,明确组件内头文件的引用,尽量减少公开头文件和接口的数量。
丨4 组件 Module 化
LLVM Module 改变了传统 C-Based 语言的头文件机制,被 Swift 采用,如果组件没有 Module 化,Swift 就无法调用该组件,如何 Module 化 见 《百度App Objective-C/Swift 组件化混编之路(二)- 工程化》。
组件 module 化编译产物的目录结构如下:
├── xxx ├── Headers │ ├── xxxSettingProtocol.h │ ├── xxx-Swift.h ├── Info.plist ├── Modules │ ├── xxx.swiftmodule │ │ ├── Project │ │ │ ├── x86_64-apple-ios-simulator.swiftsourceinfo │ │ │ └── x86_64.swiftsourceinfo │ │ ├── x86_64-apple-ios-simulator.swiftdoc │ │ ├── x86_64-apple-ios-simulator.swiftinterface │ │ ├── x86_64-apple-ios-simulator.swiftmodule │ │ ├── x86_64.swiftdoc │