1. .swiftmodule目录文件
.swiftmodule: 包含序列化过的AST(抽象语法树,Abstract SyntaxTree),也包含SlL(Swit中间语言,Swift IntermediateLanguage)
.swiftinterface: Module stability
.swiftdoc: 用户文档
1.1 .swiftmodule 文件中存储了什么?
.swiftmodule是如何将模块代码暴露给外界的? 外界又是如何通过.swiftmodule来访问模块代码的?
例:
import Foundation
public struct Teacher {
public init() {}
public var Kody = 1
public var Cat = "工程化实战班"
}
经过swift编译器分析,读取生成的.swiftmodule文件:
.swiftmodule文件是编译器对代码分析之后,将可暴露的方法或者模写在其中,其他swift类通过它来对其进行访问。
1.2 xcconfig配置文件
新建xcconfig配置文件:
右键 -> new File -> 搜索config
选中Project->info->Configurations 可以给某个project设置配置文件,也可以给某个target设置配置文件。
如何查看Build Settings中的配置的对应的名字
这个名字就是可以在xcconfig中可以使用的配置选项
1.3 xcconfig配置语法
// key -> build setting
// value -> build setting -> 值
// Debug
OTHER_LDFLAGS[config=Debug] = $(inherited) -framework "Foundation"
1.4 xcconfig配置与BuildSettings的优先级
如果xcconfig的配置与BuildSettings手动配置的不一样,那么在BuildSettings的第一行增加$(inherited)继承,可以使用两边的配置。具体规则
1.5 有多个xcconfig配置文件的情况
可以把一个xcconfig导入另一个xcconfig
#include "Framework/host_url.xcconfig"
导入完在BuildSettings中不一定会体现出来,可以跑一下Script看一下成功没
有些配置没有显性的给到
例如 SWIFT_EXEC 这个配置用于修改swift编译器
//修改修改swift编译器
SWIFT_EXEC=/Volumes/Tino/swift-source/build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/swift-macosx-x86_64/bin/swiftc
//修改编译基于哪个Macos版本
//这个 SDKROOT 对应到 BuildSettings 中就是 Architectures->Base SDK
SDKROOT = /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk
2. Module Stability
从 Swit5.1 开始,支持 Module Stability,解决模块间编译器版本兼容的问题。
这意味着使用不同版本编译器构建的Swift模块可以在同一个应用程序中一起使用。
解释:优化头文件的稳定性。
这个 Module Stability 功能,在编译之后生成两个文件,.swiftmodule 和 .swiftinterface
2.1 .swiftinterface 文件中存储了什么?
.swiftmodule和.swiftinterface的内容可以理解为是差不多的,.swiftmodule值存储了当前编译器版本,你项目编译器一更新,模块与项目就不兼容了。
例如,项目的编译器是5.5.1,模块是又swift5.2.4编译成的,当没有.swiftinterface文件的时候,项目就发编译通过,这个现象叫模块不稳定。
-
.swiftinterface相当于多了一个版本兼容性,在模块与项目的swift编译器版本不兼容的时候,也能使用。 -
.swiftmodule的编译速度要比.swiftinterface快,所以当swift编译器版本相同的时候,用的是.swiftmodule。
3. Library Evolution
从Swit5开始,库能够声明稳定的ABl,允许库能够声明稳定的ABI,允许库二进制文件替换为更新版本,而无需重新编译客户端程序。
由于swift是静态语言,所以代码结构等是在编译时就确定了。
而 Library Evolution 功能可以使一部分代码由编译时就确定,推到了运行时才确定。(Swift运行时)
功能开启:
Build Libraries for Distribution
但是Library Evolution 有个缺陷,就是会让swift性能下降,原来刻意设计的静态语言就是要编译时确定好,运行的时候只要把代码加载到虚拟内存的指定空间,直接跑就行了,Library Evolution这么一整又回到运行时那一套,效率就低了。
3.1 @frozen 关键字
所以有个折中的办法,@frozen 关键字。
在 Build Libraries for Distribution 打开的情况下,被 @frozen 修饰的方法,不推到运行时,没 @frozen 修饰的方法,都推到运行时。
@frozen
public struct Teacher {
public init() {}
public var Kody = "11111112312312"
public var Cat = 2
}
4. module
是用来管理一组头文件的。
创建: 右键 New Files -> Empty -> 名字.modulemap
module LGCat { //module名
header "Headers/LGCat.h" //代表当前Module里包含了哪些头文件
export Foundation //代表LGCat.h中包含的其他模块,要在这里一起导出
export LGDog
export * // *通配符,表示LGCat.h中包含的其他模块全部导出
}
要告诉当前的编译器去使用这个 module:
创建一个config文件,然后写入:
OTHER_CFLAGS = "-fmodule-map-file=${SRCROOT}/LGApp/LGCat.framework/module.modulemap"
//OTHER_CFLAGS = "-fmodule-map-file=moudle的路径
其他类导入LGCat时:
//原来:
#import "LGCat.h"
//使用module:
@import LGCat.h
此外:#import <LGCat/LGCat.h> 这种导入方式在module中是不对的,这种导入方式是framework专属。
4.1 umbrella
但是当文件多的时候,把每一个文件都写成一句 header "xxx/xxxxx.h" 在module中,会显得很冗长,所以有了 umbrella 关键字。
首先新建一个头文件:LGCat-umbrella.h
将想暴露的文件导入LGCat-umbrella.h文件中:
import "LGCat.h"
在module文件中:
通过 LGCat-umbrella.h 文件去映射其他文件。
module LGCat { //module名
umbrella header "LGCat-umbrella.h"
export *
}
如果在 module 前加上 framework:
会报错,原因是 framework 本质上是一个文件夹,它有自己的文件夹格式要遵守,如下:
所以 framework module 是一个特殊的 module,它必须按照framework的格式来进行。
由于framework所有的头文件都是放在 Headers 目录下,所以创建一个Headers文件夹,然后把 umbrella 文件和 LGCat 文件拖进去。
然后编译成功。
那既然是个framework结构,在使用的时候是不是可以不要用@import LGCat; 使用#import "LGCat/LGCat-umbrella.h"
会发现报错,原因是对于 clang 编译器来说,识别一个framework必须通过 .framework 后缀,所以说 改个名字:
这么一改,使用#import "LGCat/LGCat-umbrella.h"写法便不会报错。【会在link时报错】
4.2 explicit关键字
如果,外界使用,希望通过这种方式:@import Cat.LGCat;
那么需要 module 需要这么改:
在module前增加 explicit 关键字, explicit关键字代表当引入Cat模块时,不会引入子模块LGCat。除非显示使用Cat.LGCat
framework module Cat {
umbrella header "LGCat-umbrella.h"
export *
explicit module LGCat {
header "LGCat.h"
export *
}
}
4.3 requires关键字
如果再一个 module 的尾部 加上 requires objc ,意味着:使用方必须是一个OC文件,才能够引入。
module Framework.Swift{
header "Framework-Swift.h"
requires objc
}
同样的,还可以是requires cpluscplus
- xcconfig编写指南
- 使用Swift库注意事项