12-Swift混编(上)

1,883 阅读5分钟

一.swiftmodule目录文件

我们知道 oc调用swift 以及swift调用oc的流程如下 Xnip2022-01-28_19-52-46.jpg

但是我们创建swiftframework的时候 那么我就会有下面的一些疑问

  • 1.swift没有头文件,只有.swiftmodule
  • 2.swift Framework不能使用 .Bridging-Header.h
  • 3.swift涉及到的编译参数
  1. swift没有头文件的概念,那么我们外界要是使用siwift中的public修饰的类和函数该怎么办?
  2. swift库中引入了一个全新的文件.swiftmodule

1.用swift语言编译生成的framework的目录结构 我们都知道swift是没有头文件的 而swiftmodule里面相当于就是头文件

Xnip2022-01-28_19-47-03.jpg

文件包含如下

  • .swiftmodule 包含序列化过的AST(抽象语法树),(Abstract Syntax Tree) 也包含SIL(swift中间语言,Swift Intermediate Language)
  • .swiftdoc: 用户文档

我们研究一下 x86_64-apple-macos.swiftmodule 这里面包含我们声明的结构体的信息

需要用到Swift REPL: swift解释器 永来运行调试Swift代码

1.swift -> repl -> swiftmodule

 xcrun -show-sdk-path 

 -frontend:使用Swift前端工具

 -repl:进入解释器

 -sdk:环境使用的SDK

 -F:framework所在的路径

 -I:library所在的路径

 :print_module :打印module声

 /Volumes/Tino/swift-source/build/Ninja-RelWithDebInfoAssert+stdlib-DebugAssert/swift-macosx-x86_64/bin/swift -frontend  -repl -sdk /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -F /Users/Desktop/Swift/Swift混编/Framework/Products

显示.swiftmodule里面的内容

Xnip2022-01-29_10-47-33.jpg

二.Module Stability

Module Stability 是解决模块间编译器版本兼容的问题 这意味着使用不同版本编译器构建的Swift模块可以在同一个应用程序中一起使用

三.Library Evolution

从swift5开始,库能够声明稳定的ABI,允许库二进制文件替换为更新版本,而无需重新编译客户端程序

举个例子 在framework里面声明变量age = 2

Xnip2022-01-29_16-03-11.jpg 直接运行 相当于编译framework 同时运行demo Xnip2022-01-29_16-00-03.jpg

当我们恢复name字段 只编译framework

Xnip2022-01-29_16-04-55.jpg

运行如下 Run Without Building 运行已经编译好的产物 不重新编译

Xnip2022-01-29_16-05-19.jpg

得到结果如下

Xnip2022-01-29_16-05-50.jpg

为什么打印的age的值是1 为什么打印的是name的值 是因为swift是静态语言 编译的时候已经确定了内存结构 按内存结构找到了第一个就是name的值 怎么解决呢 看下面截图

Xnip2022-01-29_16-13-03.jpg

我们设置一个BUILD_LIBRARY_FOR_DISTRIBUTION = YES 在按上面的流程操作一下 得到正确结果

Xnip2022-01-29_16-17-39.jpg

相当于给代码推到runtime时 这样会导致性能下降 这个时候我们就会有个关键字@frozen 添加这个字段就是不推到运行时 不添加的话就推到运行时 拿上面的例子举例 如果添加这个关键字得到的结果age = 1 代表上面结论就正确了

1.全部运行

Xnip2022-01-29_16-21-52.jpg 2.编译framework 运行 Run Without Building

Xnip2022-01-29_16-23-42.jpg

这个关键字的应用场景 我的库swift组件1.0 -》 升级到2.0 我的app代码功能不需要重新编译就可以了

四.xcconfig编写指南

1.我们先添加一个脚本 Xnip2022-01-28_20-17-48.jpg

  • 第一步删除Products下生成的Framework
  • 第二步从BUILT_PRODUCTS_DIR(framework产物所在的目录)拷贝到 Products

Xnip2022-01-28_20-25-04.jpg Xcode -> shell -> clang/swiftc ->build setting 在界面可以设置

Xnip2022-01-28_20-21-55.jpg

build setting 里面没有设置的参数 相当于给shell变量添加参数 或者在build setting里面设置比较麻烦 我们可以通过配置Config文件去配置build setting里面的参数

1.先创建一个Config文件

Xnip2022-01-28_20-29-59.jpg

2.文件里面包含一个介绍参数配置的地址 help.apple.com/xcode/#/dev…

Xnip2022-01-28_20-31-14.jpg

3.这个config文件如何生效 在这里面设置 对应Debug 和 release 分别设置

Xnip2022-01-28_20-34-25.jpg

4.例子(一)

我们设置一下 Other Linker Flags Xnip2022-01-28_20-40-55.jpg

在config里面添加配置 以Declaration为key Xnip2022-01-28_20-41-41.jpg

在 Other Linker Flags 就会显示 Xnip2022-01-28_20-48-57.jpg

5.例子(二)

如果手动配置 先改为这个 发现和 config里面就不显示 Xnip2022-01-28_20-54-35.jpg

在里面配置添加$(inherited) config里面的配置继承过来就会显示 Xnip2022-01-28_20-58-09.jpg

6.例子(三)

添加config2

Xnip2022-01-28_21-09-22.jpg

在config 里面引入 config2

Xnip2022-01-28_21-11-05.jpg

在build setting 里面不显示

Xnip2022-01-28_21-12-32.jpg

通过脚本打印参数

Xnip2022-01-28_21-13-01.jpg

发现都有加入

Xnip2022-01-28_21-08-06.jpg

7.例子(四)

如果在debug 和release 都设置config

Xnip2022-01-28_21-15-57.jpg

但是config只在Debug下生效

Xnip2022-01-28_21-16-47.jpg

显示结果release下不显示

Xnip2022-01-28_21-19-48.jpg

五.module(管理一组头文件)

1.我们先创建一个module.modulemap文件 倒入LGTest.h

Xnip2022-01-29_20-44-41.jpg

2.找到设置module.modulemap文件的key

Xnip2022-01-29_20-34-44.jpg

3.通过config文件 导入module.modulemap

Xnip2022-01-29_20-45-48.jpg

4.编译 报错

Xnip2022-01-29_20-47-40.jpg

5.因为LGTest.h 里面倒入了Foundation

Xnip2022-01-29_20-48-38.jpg

6.需要在module.module.map里面添加 export Foundation 或者 export * 编译成功

Xnip2022-01-29_20-50-55.jpg

7.我们不能这么倒入 因为framework专属 编译报错

Xnip2022-01-29_20-53-34.jpg

8.如果我们倒入多个文件不可能写一堆header 这个时候就用到了 umbrella 这个关键字管理一组文件

Xnip2022-01-29_21-00-32.jpg

9.在 LGTest-Header-Umbrella.h文件 通过一个伞头文件 映射到其它多个文件

Xnip2022-01-29_21-00-40.jpg

10.如果我们把module 变成 framework module 编译报错 找不到伞头文件

Xnip2022-01-29_21-04-41.jpg

11.因为framework 的文件结构是 Header+.a+签名+资源文件+Modules 头文件放到Headers文件夹里面 我们试一下 编译成功

Xnip2022-01-29_21-08-56.jpg

12.如果我们添加头文件的方式改为framework的方式添加

Xnip2022-01-29_21-29-29.jpg

13.如果我们想已这种方式引入头文件 在module.modulemap文件声明子module就OK了

Xnip2022-01-29_21-32-28.jpg

Xnip2022-01-29_21-34-14.jpg

14.把伞文件里面的文件导出编译也是OK的

Xnip2022-01-29_21-37-06.jpg

15.添加explicit 只有添加显示的子module才会添加 子模块

Xnip2022-01-29_21-40-28.jpg

Xnip2022-01-29_21-42-31.jpg

16.requires objc 使用子module源码文件必须是一个OC文件

1.错误

Xnip2022-01-29_21-50-14.jpg

2.正确

Xnip2022-01-29_21-50-25.jpg

17.子module也可以这么定义

Xnip2022-01-29_21-55-27.jpg