modulemap

我们在构建Framework或者使用Cocoapods的时候应该都会接触到ModuleMap, 那它到底是个什么?有什么作用?本文基于Xcode 12完成。

直接使用module.modulemap

在XCode的build setting内,Packaging内有以下设置module map的选项

  1. Defines Module (DEFINES_MODULE) :如果设置为YES,会认为项目自定义自己的组件,允许项目通过组件的方式引入>2. Module Map File (MODULEMAP_FILE)用来管理LLVM的module map,定义编译器组件结构.如果defines module为YES的时候,如果Module Map File没填,会自动生成。
Bridging Header缺点:
  1. 把需要的东西全部赤裸裸的摆在了外面容易造成方法重名等问题
  2. 模块间的关系也变得不清不楚的
  3. 如果Swift项目是Framework则无法采用Bridging Header方式
modulemap好处:
  1. 语义上完整描述了一个框架的作用
  2. 提高编译时可扩展性,只编译或 include 一次。避免头文件多次引用,只解析一次头文件甚至不需要解析(类似预编译头文件)
  3. 减少碎片化,每个 module 只处理一次,环境的变化不会导致不一致
  4. 对工具友好,工具(语言编译器)可以获取更多关于 module 的信息,比如链接库,比如语言是 C++ 还是 C等等

modulemap编译

module中C和OC要分开编译, C++可以和C一起编译, C++也可以和OC一起编译。
当OC 和C 一起需要添加requires objc

module OCTest {
        requires objc
        header "OCTest.h"
        export *

        umbrella "Subs/OCSubs" // 单独把 Subs 中的 OC 文件, 单独列出来, 否则会编译失败
        module * { export * }
    }

由于Swift不能直接调用C++代码, 所以一般会导出C和OC文件。

Swift中不能直接调用C++代码,但是可以调用c代码, 通过void*生成c++对象, 通过c来调用C++

umbrella作用

https://stackoverflow.com/questions/31238761/what-is-an-umbrella-header
它是框架的“主”头文件,没有的时候需要这样写:

#import 
#import 
#import 
#import 

现在只需要#import , 另外umbrella + 目录, 可以递归导出子目录下的所有.h。

module * { export * } 和 export * 的区别

umbrella "Subs"
export *

import OtherFile.CTest
import OtherFile.OCTest

//
//  CPlusSubs.hpp
//  ModulemapDemo
//
//  Created by SRS on 2020/11/2.
//

public var CPLUSSUBS: Int32 { get }

对比:

umbrella "Subs"
module * { export * }

import OtherFile.CPlusSubs
import OtherFile.CPlusSubs2
import OtherFile.CTest
import OtherFile.OCTest

可以发现module * { export * } 会直接把所有 .h 中的方法, 直接导入到当前的 module 中。 另外只有umbrella才可以使用module * { export * }

system和extern_c

system属性指定模块是系统模块。当重建系统的所有模块的头时,将认为该模块的所有标头被取消。这相当于将#pragma GCC system_header放在每个模块的头中。属性的形式在下面的属性一节中描述。

extern_c属性指定模块包含可以在C ++中使用的C代码。 当构建此类模块供C ++代码使用时,该模块的所有标头都将被视为包含在隐式extern“ C”块中。


Swift Freamwork中使用module.modulemap

操作步骤就不详细写了,基于https://www.jianshu.com/p/b4f88651f069完成,主要讲下权限配置:

image.png

如果头文件在Public对应Freamwork中Headers;Private对应Freamwork中PrivateHeaders;Project里面 没有在Freamwork中看见,理论可以通过这个配置隐藏头文件。

注意framework module 中无法使用 umbrella

本实例Demo

参考:
https://zhuanlan.zhihu.com/p/51194169
https://www.jianshu.com/p/12a9565241e8
https://www.jianshu.com/p/ce49d8f32f77
https://www.jianshu.com/p/b4f88651f069
https://clang.llvm.org/docs/Modules.html#requires-declaration

你可能感兴趣的:(modulemap)