概述
Swift Package Manager(簡稱SPM),是Apple官方提供的軟件包管理器,類比如Ruby的RubyGems, Python的pip。開源框架裡知名度較高的SwiftyJSON、SQLite.swift等都已支持SPM集成。
WWDC18專門開了一個Session介紹了SPM的內部結構、基本使用及設計理念,並介紹了之後即將支持的一些新特性。
為什麼要使用SPM
最重要的一點:官方支持
官方支持,保證了所有Swift軟件包的可信來源和通用標準。同時,SPM作為Swift項目的一部分,Apple在Swift工具鏈中提供了更強大的原生支持。
跨平臺構建
SPM是一個跨平臺方案,SPM提供了完整的構建環境,能在不同平臺上來構建和分發Swift軟件包。
和Swift更緊密的關係
SPM採用Swift編寫,可以使用Swift自身的強大特性,並且與Swift的核心庫緊密聯繫。
SPM有更先進的設計
這個我們在後面章節展開。
SPM的社區影響範圍日益增長
作為Swift開源項目的一部分,社區的熱度不斷升溫,CocoaPods的眾多核心成員也參與架構設計,影響力越來越大。
SPM基本用法
SPM的基本概念可參見官網描述。
常用命令
- swift build: 編譯Package。
- swift run: 編譯Package裡的可執行文件並運行。
- swift test: 運行Package裡的單元測試。
- swift package: 這個命令的用法很多,Package的初始化、修改、更新、resolve檢查、編譯選項指定等。
內部結構
對於一個Package來說,主要分為三部分,Target、Products、Dependencies
Products
Products可以理解為Package輸出的形態。對比與Cocoapods只能以靜態庫/動態庫形式,SPM還可以輸出為可執行文件。
Target
Target理解為包含多個文件的一個模塊,target之間是可以有依賴關係,同時,輸出的Products也會依賴一個或多個target。
Dependencies
Dependencies描述了當前的package需要依賴其他package。
一個典型的Package目錄如下:
其中Package.swift的定義:
Sources目錄下的文件不需要顯示聲明,SPM會自動導入,Dependencies依賴了兩個外部Package, 其中Target的依賴既有Package內部Target的依賴也有外部Target的依賴。
Package.resolved被放在頂層包的一個文件中,類似於許多軟件管理器lock的實現,swift使用該文件來做依賴關係解析。在執行swift build swift test swift package generate-xcodeproj命令時,默認會隱式調用swift package resolve檢查依賴版本是否正確。
Package.resolved的詳細設計思路可以參考提案。
SPM的設計思想
SPM的設計思想也遵循了Swift的一些設計思想:
安全: SPM的編譯環境是在一個獨立的沙盒裡,無法任意執行命令和腳本。
快速: 得益於新的llbuild構建系統,SPM可以支持數百萬節點的關係依賴圖。
表現力: 採用Swift作為SPM的配置描述語言。
下圖描述了Apple對SPM的大體思想
Configuration
相對於Cocoapods等笨重囉嗦的DSL語法,SPM採用了Swift來作為SPM的配置描述語言,大大降低了開發人員的學習成本同時保留的Swift強大的語言特性,並可以得到 Swift相關工具的支持。
Dependencies
SPM使用git tag來做版本依賴,格式上遵循Semantic Versioning.
Semantic Versioning(Semver): 是為了解決軟件包管理器中著名的Dependency hell問題而設計的一套簡單的規則和條件來約束版本號配置的解決方案。
Semver規定格式裡分為:主版本號.次版本號.修訂號,版本號遞增規則如下:
1. 主版本號:當你做了不兼容的 API 修改。
2. 次版本號:當你做了向下兼容的功能性新增。
3. 修訂號 :當你做了向下兼容的問題修正。
Semver同時支持語義化關鍵字來實現版本控制,需要對Semver更深入瞭解的讀者可參考官網介紹。下圖就是一個採用Semver版本控制的Package依賴樹結構。
Building
SPM採用了swift-llbuild ,一個並行、高效、增量編譯的構建系統作為其構建引擎。目前Xcode9也已集成,用作對LLVM、Clang及Swift的構建。同時,因為獨立沙盒的構建環境,SPM提供了很強的安全性。
Workflow Features
如果你的某個軟件包還處於開發模式下,tag的集成方式很不方便,類似於Cocoapods的做法,SPM也會提供分支依賴和本地依賴做法。
Tools Evolution
和Cocoapods一樣,當我們的軟件包需要依賴特定的swift版本,需要在配置描述裡顯示聲明。聲明的枚舉類型如下
例如指定版本為4.0
SPM的未來新特性
- 與其他工具的更好的集成
- 使用libSwiftPM和libSyntax對SPM做更靈活的擴展實現。
- 發佈和部署
- 目前的發佈流程依賴於手動建立git tag, git push origin [tag name] 的做法,之後會有更自動化的工具實現。
- 支持複雜的Packages
- 對資源文件的支持,更復雜的編譯設置,和擴展的編譯工具等
- 更好的管理Package生態
- 跨平臺的沙盒隔離、更安全的校驗方案,支持fork操作和搜索索引等。
預見到等到合適的時機,SPM成為Swift Package的標準管理工具是大勢所趨。
參考:
https://developer.apple.com/videos/play/wwdc2018/411/
https://swift.org/blog/swift-package-manager-manifest-api-redesign/
https://medium.com/xcblog/apple-swift-package-manager-a-deep-dive-ebe6909a5284
閱讀更多 今日頭條技術團隊 的文章