Swift编译慢?请看这里,全套开源

知识小集

共 2689字,需浏览 6分钟

 ·

2021-05-09 03:45

作者 | 苏良锦,美柚 iOS 工程师,2019 年加入美柚。 
来源 | 掘金,点击阅读原文查看作者更多文章

一、概述

距离上一篇iOS二进制编译方案(iOS如何提高10倍以上编译速度)已经快过去半年了,期间收到了很多来着小伙伴们的支持。cocoapods-imy-bin这套系统也在我司(美柚)跑满了上万条的打包记录,目前表现依然是很稳定。

鉴于目前市场上,Swift及Swift-OC混编项目流行,且Swift的编译项目过慢的问题,在业务繁忙之瑕,做了对Swift、Swift-OC项目的二进制组件化的支持。希望能给小伙伴们在iOS编译的问题上,提供帮助。

二、项目效果

我们Cocoapods-imy-bin项目,同时支持对纯Swift、纯Object-C、Swift-OC混编的二进制化。
直接上图看效果,多余的话就不多说了。本文实验Swift-OC-Demo地址,感兴趣的小伙伴们可以自行下载验证效果。

图一、Build tasks对比

图二、Build time对比

图一、编译任务数,在未使用\使用二进制时,编译tasks是532\113个、113个tasks是除了Pods库外的一些其他文件、link、copy文件、sign等tasks,减少了80%的tasks

图二、编译时间,在未使用\使用二进制时,编译时间是35.9s\17.8s个、17.8s是除了Pods库外的一些其他文件、link、copy文件、sign等时间,效率提升了2倍。

图三、美柚App 编译时间对比

总体效率上,编译速度的提升是非常可观的,项目越大、性能提升越明显,在我司美柚APP项目上,编译提速可达13倍以上。(全量编译)

三、Cocoapods-imy-bin项目功能

自动化支持iOS项目组件二进制化:

  • 无入侵、无感知、不影响现有业务,不影响现有代码框架、完全绿色产品~

  • 轻量级,只要项目能编译通过就能使用,无视组件化、无视耦合

  • 完全自动化,一键使用、无需手动操作

  • 支持 使用与不使用 use_frameworks!

  • 提供几个特色服务

  • 少数支持swift项目二进制化编译的开源项目之一

四、Swift二进制化实现简介

目前Demo是Swift-OC 混编,同时支持纯Swift项目。OC-Demo在这,具体原理及详情请移步到 iOS如何提高10倍以上编译速度。

Swift二进制化原理其实也就那么回事,在pod的时候,全部自动转换成Framework

图四

图五、自动转换依赖二进制化组件

五、Swift二进制化遇到的问题

1、Module compiled with Swift 5.1.3 cannot be imported by the Swift 5.2.2 compiler

解决:

1、配置Framework的Build Setting将“Build Libraries for Distribution”选项设置为 YES,否则Swift编译器不会生成必要的".swiftinterface文件,这是将来编译器能够加载旧库的关键。

2、如果机器不多的话,可以把xcode更新到统一的版本号

2、转换后的工程,在{Development Pods}下,OC引用Swift文件,找不到对应的类

解决:(建议壳工程化,可以避免此问题)

这个文件是混编时,系统生成的Swift文件对应的Objective-C的头文件,具体可以在Targets-->Build Settings-->Swift Compiler - General-->Objective-C Generated Interface Header Name进行配置,默认文件名是工程名-Swift.h,一般不做改动。

3、Podfile引用 use_frameworks! 与不引用 use_frameworks!的编译问题

找不到对应的头文件,这个头文件是xcode编译时自动生成的,在Products/Debug-iphonesimulator/lottie-ios/lottie-ios.framework/Headers 中,去掉use_frameworks!后就找不到了

解决:在Header Search Paths 添加对应的文件引用

4、Command PhaseScriptExecution failed with a nonzero exit code

解决:cocopods1.8.4会出现此问题,升到1.9.1后就正常了

5、Masonry, which do not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set use_modular_headers! globally in your Podfile, or specify :modular_headers => true for particular dependencies.

pod bin auto 的时候出现了

解决:修改cocoapods插件相关代码,或者使用cocopods-imy-bin v0.3.11版本即可解决。

# setting modular_headers_for
if(target_definition && target_definition.use_modular_headers_hash.values.any?)
target_definition.use_modular_headers_hash.values.each do |f|
f.each { | pod_name| self.set_use_modular_headers_for_pod(pod_name, true) }
end
end

欢迎大家的加入,一起学习与探讨

浏览 50
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报