module - ShenYj/ShenYj.github.io GitHub Wiki
一个 module
是机器代码和数据的最小单位,可以独立于其他代码单位进行连接。
Module
是clang
提供的一种处理头文件的解析格式
通常 module
是通过编译单个源文件生成的目标文件。例如,当前 test.m
被编译成目标文件 test.o
时,目标文件就代表了一个 module
, 但是有一个问题, module
在调用的时候会产生开销,比如我们在使用一个静态库的时候。
以 Object-C
为例,默认情况下,在 .m
中会进行 import
头文件,也就代表着头文件要参与编译,一次次的编译注定会影响到编译的时长
默认
Frameowrk
开发不会给自动创建.modulemap
文件,再试在编译后会自动生成,我可以可以在编写framework
的时候就直接自己创建,并在build setting - Module Map File
中配置路径
.
├── prebuild
└── test
├── A.h
├── B.h
├── module.modulemap
└── use.c
prebuild
是一个空文件夹,存放生成物
-
A.h
/* A.h */ #ifdef ENABLE_A void a() {} #endif
-
B.h
B.h
中导入了A.h
/* B.h */ #import "A.h"
-
Use.c
Use.c
中导入了B.h
/* use.c */ #import "B.h" void use() { #ifdef ENABLE_A a(); #endif }
-
module.modulemap
/* module.modulemap */ module A { header "A.h" } module B { header "B.h" export A }
描述头文件与
module
之间的关系,Module A
代表A.h
将在B
中将A
暴露,重新导入导出,一般使用export *
通配
通过 clang
编译链接成 .o
文件,同时生成 module
clang -fmodules -fmodule-map-file=module.modulemap -fmodules-cache-path=../prebuilt -c use.c -o use.o
-
-fmodules
:允许使用module语言来表示头文件 -
-fmodule-map-file
:module map的路径。如不指明默认module.modulemap -
-fmodules-cache-path
:编译后的module缓存路径
在 prebuild
中的产物
.
├── 1B079OJNMTTUL
│ ├── A-1TFUZYW6I2HVV.pcm
│ ├── B-1TFUZYW6I2HVV.pcm
│ └── modules.idx
└── modules.timestamp
.pcm
就是头文件预先编译后的产物
通过Module
会先.h
头文件预先编译成二进制,在系统目录下缓存
在所有.m
中再次使用的时候,直接取二进制来用即可
-
AFN
framework module AFNetworking { umbrella header "AFNetworking-umbrella.h" export * module * { export * } }
-
framework module AFNetworking
: 声明一个framework module
, 名称是AFNetworking
-
umbrella header "AFNetworking-umbrella.h"
: 指定文件AFNetworking-umbrella.h
代表伞柄,文件中的所有头文件作为伞骨-
umbrella <目录>
: 伞柄, 目录下面所有的.h
文件作为伞骨 -
header
: 指定一个文件
-
-
export *
: 重新导出 -
module * { export * }
: 创建了一个子module
->Module *
,再重新导出 ->{ export * }
- 如果需要显示指明子
module
名称,使用关键字explicit
,通配就是头文件叫啥,子模块就叫啥- e.g.:
explicit module XXXXXX
- e.g.:
- 使用了子
module
,在配合@import
的时候就可以通过module.submodule
来导入使用了
- 如果需要显示指明子
-
-
#include
传统的#include
的方式: 一个头文件被多少个代码文件导入,那么就会参与多少次的编译 -
#import
在#include
的基础上做了重复引用处理 -
@import
配合Module
使用, 在引入的时候还可以显式的指定引用模块中的某个子模块, 比如@import UIKit.UIWindow
Module
功能默认开启,在开启Module
功能后,三种写法都是可以的
通过 Module
可以很方便的来导入我们所依赖的库模块及子模块,默认情况下所有的模块和子模块均是对外暴露的, Module
也考虑到了这一点, 提供了一种暴露方式控制的配置方法