头文件映射与模块映射
摘要: 自身target中头文件的检索使用hmap,对于库文件的头文件检索使用clang module,或许是在编译过程中的一个较优解。
头文件映射
Apple在头文件检索方面做了优化,在编译源文件之前,已经把头文件的路径写入hmap文件中;
PS: 日志中复制源文件的编译指令到终端 + -v;可查看编译详情
定位非系统文件:
- ""导入的头文件从hmap中查找
- <>导入的头文件先去target-hmap中,如果没找到再去对应库文件路径中查找
定位系统头文件:
具体分析可查看美团团队的分享:从预编译的角度理解Swift与Objective-C及混编机制
我们常用cocoapod管理三方库; 但是对于依赖的第三方库头文件的检索并不会命中hmap,而是从Pods-xxx.debug.xcconfig配置的路径查找的,里面都列举了对应导入的第三方库,<>从framework/library 查找,“”从Header Search Paths查找;
另外对照分析主工程hmap文件,也可以发现没有对应的三方库头文件;
总结,主工程中hmap只能命中当前自身的.h头文件;
同样方式检查pod中的第三方库,可以命中自身的.h头文件,但是发现<>也没有命中其依赖的第三方库, ""反而可以;
在Pods_xxx-all-target-headers.hmap 里面其实已经包含了所有的路径,但是没有使用到,使用的反而是Pods_xxx-all-non-framework-target-headers.hmap,跟apple在wwdc上演示的不一致。
.a和.framework一样都是这种情况。
framework库:
主工程:
- “...”search starts here:
xxx-generated-files.hmap
xxx-project-headers.hmap
仅命中自身.h文件,没有第三方库的头文件;
- <...> search starts here:
xxx-own-target-headers.hmap
xxx-all-non-framework-target-headers.hmap
同样没有第三方库的头文件
pods:
- “...”search starts here:
xxx-generated-files.hmap
xxx-project-headers.hmap
能找到""引用的头文件的路径,如下所示;
UIView+WebCache.h -> SDWebImage/UIView+WebCache.h
UIView+WebCacheOperation.h -> SDWebImage/UIView+WebCacheOperation.h
YYClassInfo.h -> YYModel/YYClassInfo.h
YYModel-prefix.pch -> /Users/sunjiale583/Desktop/temp/tempCom/Pods/Target Support Files/YYModel/YYModel-prefix.pch
YYModel-umbrella.h -> YYModel/YYModel-umbrella.h
YYModel.h -> YYModel/YYModel.h
- <...> search starts here:指定的是
xxx-own-target-headers.hmap
xxx-all-non-framework-target-headers.hmap;
同样没有第三方库的头文件;
apple WWDC中分享的是下面2个:
xxx-own-target-headers.hmap
xxx-all-target-headers.hmap (包含pods所有)
模块映射 clang module
xcode工程对于依赖库头文件的检索不使用hmap或许正是出于clang module考虑;
.framework有clang module功能,.a静态库没有
clang module 的优点:
- 一次加载和处理头文件
- 缓存符号信息
- 复用
- 大型项目更快的构建实践
对于自己创建的framework,通过构建虚拟文件系统(VFS),方便clang创建模块,里面描述了文件结构信息(yaml文件),但是抽象框架只能映射到目录文件
在cocoapod中,所有的pods共用一个all-product-headers.yaml;
使用framework静态库的module功能,在主工程中导入<>的时候,预编译情况如下:
综上所述,在主工程中,使用hmap优化""头文件检索,使用framework的module优化三方库<>头文件导入,对于编译的优化,有较大的提升。