Swift:module、modulemap、调用OC代码、静态库合并、与OC相互映射

一、module与modulemap的作用

1、 module
  • Module(模块)-最小的代码单元。
    一个Module是机器代码和数据的最小单位,可以独立于其他代码单位进行链接。通常,Module是通过编译单个源文件生成的目标文件。例如,当前的test.m被编译成目标文件test.o时,当前的目标文件就代表了一个Module。但是,有一个问题,Module在调用的时候会产生开销,比如我们在使用一个静态库的时候,可以这样使用。
//  -fmodules:允许使用module语言来表示头文件
//  -fmodule-map-file:module map的路径。如不指明默认module.modulemap
//  -fmodules-cache-path:编译后的module缓存路径
clang  -fmodules -fmodule-map-file=Cat.modulemap -fmodules-cache-path=../prebuilt -c use.c -o use.o
2、modulemap
  • modulemap定义:用来描述头文件与module之间映射的关系的文件。
//  AFNetworking的module.modulemap文件
// framework module 名称 AFNetworking
framework module AFNetworking {
  // umbrella <目录> 伞柄  <目录>/.h
  // AFNetworking-umbrella.h 伞柄 AFNetworking-umbrella.h/.h 伞骨
  umbrella header "AFNetworking-umbrella.h"

  // 重新导出
  export *
  // module: 子module*
  module * { export * }
}
/*
  module:定义一个module
  export:导出当前代表的头文件使用的头文件
  export * :匹配目录下所有的头文件
  module * :目录下所有的头文件都当作一个子module
  explicit :显式声明一个子module的名称
*/
3、module实操

默认开启module之后,在引入头文件时使用include""、 import<>、@import ;这三种写法,最终都会被转化成@import。

  • @import TestStaticFramework;
    这个静态库中可能包含了许多的.o文件。岂不是要导入很多的Module。并不需要。在静态链接的时候,也就是静态库链接到主项目或者动态库时,最后生成可执行文件或者动态库时。静态链接器可以把多个Module链接优化成一个,来减少本来多个Module直接调用的问题。

  • 每次包含标头时,编译器都必须可传递地预处理和解析该标头及其包含的每个标头中的文本。必须对应用程序中的每个翻译单元重复此过程,这涉及大量的冗余工作。

  • 在具有N个翻译单元和每个翻译单元中包含M个标头的项目中,即使M个标头中的大多数在多个翻译单元之间共享,编译器仍在执行M x N个工作。

  • include伪指令被预处理程序视为文本包含,因此在包含时必须接受任何活动的宏定义。如果任何活动宏定义碰巧与库中的名称冲突,则可能会破坏库API或导致库头本身的编译失败。

  • 此外,导入模块时将自动提供使用该模块所需的任何链接器标志

  • std.io模块仅编译一次,并且将模块导入转换单元是恒定时间操作(与模块系统无关)。因此,每个软件库的API仅解析一次,从而将M x N编译问题减少为M + N问题。

  • 每个模块都被解析为一个独立的实体,因此它具有一致的预处理器环境。

  • 此外,在遇到导入声明时,当前的预处理器定义将被忽略,

  • @import上面的声明导入std模块的全部内容(其中将包含例如整个C或C ++标准库),并在当前翻译单元中提供其API。要仅导入模块的一部分,可以使用点语法来特定特定的子模块

  • 模块会自动将#include指令转换为相应的模块导入
    APINotes官方链接:https://clang.llvm.org/docs/APINotes.html
    Modules官方链接:https://clang.llvm.org/docs/Modules.html#export-declaration


二、Swift库使用OC代码

Swift库使用OC代码:不能使用桥接文件
以下方式就可以使用了:1. oc的头文件放到modulemap下;2. oc的头文件放到私有的modulemap下; 3. oc语言特性 协议 -》swift-〉协议(暴露) -》 OC

  • 创建是私有的modulemap文件命令中必须含有 private 比如:LGSwiftFramework.private.modulemap。并且在该文件内部LGSwiftFramework后面必须加上_Private,其中 P 必须大写。这些都是规则。
  • private.modulemap文件并不是真正意义上的让外部文件不能使用期私有的module,而是仅仅做了一个标识,来区分与.modulemap文件的不同而已。

三、Swift头文件

  • 在 Xcode 9 之后,Swift 开始⽀持静态库。
    Swift 没有头⽂件的概念,那么我们外界要使⽤Swift中⽤public修饰的类和函数怎么办?
    Swift库中引⼊了⼀个全新的⽂件.swiftmodule。
    .swiftmodule 包含序列化过的 AST(抽象语法树,Abstract Syntax Tree),也包含 SIL(Swift 中间语⾔,Swift Intermediate Language)。

四、Swift静态库合并

  • cp -Rv -- "${BUILT_PRODUCTS_DIR}/" "${SOURCE_ROOT}/../Products"
    复制命令:cp(复制) -R(单独复制文件)-v(使cp冗长,显示文件的原样)
    $(BUILT_PRODUCTS_DIR):build成功后的,最终产品路径可以在Build Settings参数的Per-configuration Build Products Path项里设置
    $(TARGET_NAME):目标工程名称
    $(SRCROOT):工程文件(比如Nuno.xcodeproj)的路径
    $(CURRENT_PROJECT_VERSION):当前工程版本号
    ${SOURCE_ROOT}:项目根目录(如果和项目根目录平级或更高,就$(SOURCE_ROOT)/../../IBAForms/headers)

  • libtool -staticlibtool -static LGSwiftA LGSwiftB -o libLGSwiftC.a -o libLGSwiftC.a
    将 LGSwiftA 和 LGSwiftB 合并为libLGSwiftC.a文件
    报出的警告:合并的内容中LGSwiftTeacher.o文件重复,这里只是报警告,不会报错。libtool 合并静态库本身,合并时会提示存在相同的文件,且不进行合并。


    警告
  • ar -t libLGSwiftC.a 列出libLGSwiftC.a文件里面包含的文件。


    列出静态库文件内容
  • 合并 Swift 静态库难题:静态库合并后还有 .swiftmodule文件没有合并,所以将用到的头文件和Swift头文件和modulemap文件通过目录的形式放到一起。如下图:


    header

    swiftmodule
  • Swift 合并的静态库文件应用,进行配置
    OC要用合并的静态库:clang: other c flags :-fmodule-map-file <modulemap path>
    Swift要用合并的静态库 : SwiftC :other swift flags 显式告诉SwiftC <modulemap dir>

HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/LGSwiftC/Public/LGSwiftA.framework/Headers" "${SRCROOT}/LGSwiftC/Public/LGSwiftB.framework/Headers"
// OTHER_CFLAGS:传递给用来编译C或者OC的编译器,当前就是clang
OTHER_CFLAGS="-fmodule-map-file=${SRCROOT}/LGSwiftC/Public/LGSwiftA.framework/module.modulemap" "-fmodule-map-file=${SRCROOT}/LGSwiftC/Public/LGSwiftB.framework/module.modulemap"

// SWIFT_INCLUDE_PATHS: 传递给SwiftC编译器,告诉他去下面的路径中查找module.file
SWIFT_INCLUDE_PATHS="${SRCROOT}/LGSwiftC/Public/LGSwiftB.framework"  "${SRCROOT}/LGSwiftC/Public/LGSwiftA.framework"

五、Swift与OC相互映射

  • OC映射到Swift方式:1. 宏;2. <工程名称>.apinotes。
  • 宏配置的缺点:如果一个 SDK 使用 OC 来写的,现在需要适配 Swift。这样就需要给每一个方法或属性添加宏来适配,这样就会导致有大量工作要做,费时费力。并且要修改原有代码。
  • .apinotes:文件以.apinotes结尾,且该文件一定要放在 SDK 的目录里。该文件是采用yaml格式书写。官方地址:https://clang.llvm.org/docs/APINotes.html
---
Name: OCFramework
Classes:
- Name: LGToSwift
  SwiftName: ToSwift
  Methods:
  - Selector: "changeTeacherName:"
    Parameters:
    - Position: 0
      Nullability: O
    MethodKind: Instance
    SwiftPrivate: true
    Availability: nonswift
    AvailabilityMsg: "这个不能用"
  - Selector: "initWithName:"
    MethodKind: Instance
    DesignatedInit: true
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容