Swift 關(guān)于 module.modulemap 使用

2020-7-12 更新:為什么在 swift framework 中使用了自定義module.modulemap, build 出來的 framework 會報(bào) Missing required module
@Ulquiorra_04 的提醒硝桩,開始測試并寫了這篇文章《Swift Framework 自定義 Module》,介紹了如何實(shí)現(xiàn)在 swift framework 中使用自定義 module匣缘。

Swift 中最簡單最優(yōu)雅的引用 occ 方式澄成。
首先建一個(gè) group, 就是你要 import 的亭敢,如圖文件名叫 OtherFile滚婉,所以在哪里要使用這個(gè)module的文件,就直接 import OtherFile帅刀。

// like this
import UIKit
import OtherFile

class ViewController: UIViewController {
    override func viewDidLoad() {
        ...
    }
}

module.modulemap 文件

// module.modulemap 文件
module OtherFile {
    // headers.h 和 module.modulemap  必須在同一group下让腹,否則需要配置 `header "/??/headers.h"`
    header "headers.h"
    export *
}

headers.h文件

//  headers.h文件
// 在 headers.h 中引用需要暴露的文件

// for c++
#include "file.h"
// for c
#include "file_c.h"

//#ifdef __OBJC__
// for oc
#import "Test.h"
#import "Test2.h"
//#endif

注意, 同時(shí)存在 occ 文件 需要分開處理, 需要把 oc 文件單獨(dú)加上 requires objc, 所以建議使用 umbrella, 并且把 coc 分開多個(gè) module.
requires 列表

module OtherFile {
    // c file
    header "file.h"
    header "filea.h"
    header "filebbb.h"
    
    export *
    umbrella "Subs"
    module * { export * }
    
    // oc file
    module Test {
        requires objc
        header "Test3.h"
        header "Test2.h"
        header "Test.h"
        export *
        
        export *
        umbrella "Subs/OCSubs" // 單獨(dú)把 Subs 中的 oc 文件, 單獨(dú)列出來, 否則會編譯失敗
        module * { export * }
    }
}

The std module can be extended to also include C++ and C++11 headers using a requires-declaration:

module std {
   // C standard library...

   module vector {
     requires cplusplus
     header "vector"
   }

   module type_traits {
     requires cplusplus11
     header "type_traits"
   }
 }

同時(shí)需要配置如圖


import paths 通過語義就是 可以 import 的远剩,即 import OtherFile
可以直接拖拽 group 直接到目錄下, 需要配置 $SRCROOT/, 絕對路徑骇窍。
之后就可以在這個(gè)文件夾下放你隨便的 c瓜晤, oc 文件,舒服的使用腹纳。

umbrella.h文件
什么是umbrella header?

倒入子目錄.h

umbrella + 目錄, 可以遞歸導(dǎo)出子目錄下的所有.h

module OtherFile {
    header "headers.h"
    export *
    // 倒入 Subs 文件夾下所有的.h
    umbrella "Subs"
    module * { export * }
}

代碼實(shí)例
三個(gè)方法分別對應(yīng)不同目錄下的文件

run()
subRun()
subSubRun()

// 打印
// run
// sub run
// sub sub run

所以, 我們可以通過 umbrella 更簡單的實(shí)現(xiàn)導(dǎo)出, 只需要把文件都放到子目錄下, 并導(dǎo)出就可以了, 同時(shí)支持 coc.

module * { export * } 和 export * 的區(qū)別

如下兩個(gè) modules 分別用 module * { export * }export * 來實(shí)現(xiàn)的

module OtherFile {
    // c file
    module CFile {
        header "file.h"
        header "filea.h"
        header "filebbb.h"
        export *
    }
    
    umbrella "Subs"
    module * { export * }
    
    // oc file
    module Test {
        requires objc
        header "Test3.h"
        header "Test2.h"
        header "Test.h"
        export *
        
        umbrella "Subs/OCSubs"
        module * { export * }
    }
}

上面 OtherFile module 編譯產(chǎn)生:

import OtherFile.CFile
import OtherFile.Sub
import OtherFile.SubSubs
import OtherFile.Test

上面的 module 使用 module * { export * } 產(chǎn)生了四個(gè)子 module

module OtherFile {
    // c file
    module CFile {
        header "file.h"
        header "filea.h"
        header "filebbb.h"
        export *
    }
    
    // subs 文件夾
    umbrella "Subs"
    export * 
    
    // oc file
    module Test {
        requires objc
        header "Test3.h"
        header "Test2.h"
        header "Test.h"
        export *
        
        umbrella "Subs/OCSubs"
        module * { export * }
    }
}

上面 OtherFile module 編譯產(chǎn)生:

import OtherFile.CFile
import OtherFile.Test

//
//  Subsubs.h
//  ModuleTest
//
//  Created by Yan Hu on 2019/10/14.
//  Copyright ? 2019 yan. All rights reserved.
//

public func subSubRun()
//
//  Sub.h
//  ModuleTest
//
//  Created by Yan Hu on 2019/10/14.
//  Copyright ? 2019 yan. All rights reserved.
//

public func subRun()

上面的 module 使用 export * 產(chǎn)生了2個(gè)子 module 和兩個(gè)方法, 這兩個(gè)方法分別屬于 Subsubs.hSub.h

目錄關(guān)系

你會發(fā)現(xiàn), 使用

umbrella "Subs"
module * { export * }

進(jìn)行導(dǎo)出, 把 subs 文件夾下所有的 .h 文件單獨(dú)生成了一個(gè) subModule (子 module)
使用

umbrella "Subs"
export *

進(jìn)行導(dǎo)出, 會直接把所有 .h 中的方法, 直接導(dǎo)入到當(dāng)前的 module 中, 所以在使用的時(shí)候, 可以跟進(jìn)需求來使用.

參數(shù) system 和 的介紹
// 參數(shù)使用
module OtherFile [system] [extern_c] {

}

The system attribute specifies that the module is a system module. When a system module is rebuilt, all of the module’s headers will be considered system headers, which suppresses warnings. This is equivalent to placing #pragma GCC system_header in each of the module’s headers. The form of attributes is described in the section Attributes, below.

The extern_c attribute specifies that the module contains C code that can be used from within C++. When such a module is built for use in C++ code, all of the module’s headers will be treated as if they were contained within an implicit extern "C" block. An import for a module with this attribute can appear within an extern "C" block. No other restrictions are lifted, however: the module currently cannot be imported within an extern "C" block in a namespace.

關(guān)于 import 的使用 sub modules

以上面產(chǎn)生四個(gè)sub modules 為例, 當(dāng)我在代碼中直接 import OtherFile.Test, 按照正常邏輯是, 只導(dǎo)入了 Test 這個(gè)子模塊, 所以我可以使用這個(gè)子模塊的代碼, 但不是這樣的, 即使你只導(dǎo)入了這個(gè)子模塊, 其他的子模塊的代碼依舊可以訪問到, 這個(gè)可能是 swift 5.0 說的Modules 不穩(wěn)定的地方?

那么怎么實(shí)現(xiàn)只導(dǎo)入部分代碼來進(jìn)行使用?
可以通過 import class OtherFile.Test.Test 來導(dǎo)入 Test 這個(gè)類,
同時(shí)這里還可以簡寫為 import class OtherFile.Test, 這樣會從模塊 OtherFile 和它的子模塊中需找到 Test 這個(gè)類, 并且導(dǎo)入.
當(dāng)你使用import class OtherFile.Test.TestSubSub 來導(dǎo)入 TestSubSub 這個(gè)類的時(shí)候, 發(fā)現(xiàn)竟然依然可以導(dǎo)入, TestSubSub類明明在 TestSubSub 模塊下, 但OtherFile.Test.TestSubSub依舊可以導(dǎo)入, 這也是 swift 5.0 說的Modules 不穩(wěn)定的地方?

反正就是可以導(dǎo)入單個(gè) typealias, struct, class, enum, protocol, var, func, 導(dǎo)入的方式只需要替換上面 import class OtherFile.Test.Test 中的 class 就可以了.

使用就是:
import struct SomeModule.WantToImportStruct
import class SomeModule.WantToImportClass
import enum SomeModule.WantToImportEnum
...

源碼: 文中源碼, 包含 c++ 使用方法
reference: https://clang.llvm.org/docs/Modules.html#includes-as-imports
reference: sub modules 的使用
reference: c++ 使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末痢掠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嘲恍,更是在濱河造成了極大的恐慌足画,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佃牛,死亡現(xiàn)場離奇詭異淹辞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)俘侠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門象缀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兼贡,你說我怎么就攤上這事攻冷。” “怎么了遍希?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵等曼,是天一觀的道長。 經(jīng)常有香客問我凿蒜,道長禁谦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任废封,我火速辦了婚禮州泊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘漂洋。我一直安慰自己遥皂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布刽漂。 她就那樣靜靜地躺著演训,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贝咙。 梳的紋絲不亂的頭發(fā)上样悟,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼窟她。 笑死陈症,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的震糖。 我是一名探鬼主播录肯,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吊说!你這毒婦竟也來了嘁信?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤疏叨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后穿剖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚤蔓,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年糊余,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秀又。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贬芥,死狀恐怖吐辙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蘸劈,我是刑警寧澤昏苏,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站威沫,受9級特大地震影響贤惯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棒掠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一孵构、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧烟很,春花似錦颈墅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谜酒,卻和暖如春叹俏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背僻族。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工粘驰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屡谐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓蝌数,卻偏偏與公主長得像愕掏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子顶伞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 開發(fā)的過程當(dāng)中饵撑,導(dǎo)入第三方庫(framework/.a)或者下載使用別人的demo會經(jīng)常會遇到一些關(guān)于庫的導(dǎo)入的問...
    lhg_serven閱讀 3,803評論 0 8
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,090評論 1 32
  • Distutils可以用來在Python環(huán)境中構(gòu)建和安裝額外的模塊。新的模塊可以是純Python的唆貌,也可以...
    MiracleJQ閱讀 3,058評論 0 1
  • 頭文件引用一般都會隨著項(xiàng)目規(guī)模變大而可讀性變差滑潘。當(dāng)大部分精力花費(fèi)在業(yè)務(wù)上往往容易忽視頭文件的使用和規(guī)范。整理下常見...
    Mr_GaoYu閱讀 12,284評論 5 14
  • 陳總深夜來電锨咙、留言:搞掂了语卤。 東海校長清晨留言,白天來電酪刀,關(guān)心進(jìn)展粹舵。 主管后勤的楊老師多處求索,惦記品質(zhì)骂倘。 津津老...
    尚生耕本閱讀 575評論 0 2