了解Swift Package Manager

概述

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

瞭解Swift Package Manager

Products

Products可以理解為Package輸出的形態。對比與Cocoapods只能以靜態庫/動態庫形式,SPM還可以輸出為可執行文件。

Target

Target理解為包含多個文件的一個模塊,target之間是可以有依賴關係,同時,輸出的Products也會依賴一個或多個target。

Dependencies

Dependencies描述了當前的package需要依賴其他package。

一個典型的Package目錄如下:

瞭解Swift Package Manager

其中Package.swift的定義:

瞭解Swift Package Manager

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的大體思想

瞭解Swift Package Manager

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依賴樹結構。

瞭解Swift Package Manager

Building

SPM採用了swift-llbuild ,一個並行、高效、增量編譯的構建系統作為其構建引擎。目前Xcode9也已集成,用作對LLVM、Clang及Swift的構建。同時,因為獨立沙盒的構建環境,SPM提供了很強的安全性。

Workflow Features

如果你的某個軟件包還處於開發模式下,tag的集成方式很不方便,類似於Cocoapods的做法,SPM也會提供分支依賴和本地依賴做法。

Tools Evolution

和Cocoapods一樣,當我們的軟件包需要依賴特定的swift版本,需要在配置描述裡顯示聲明。聲明的枚舉類型如下

瞭解Swift Package Manager

例如指定版本為4.0

瞭解Swift Package Manager

SPM的未來新特性

  • 與其他工具的更好的集成
  • 使用libSwiftPMlibSyntax對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


分享到:


相關文章: