[ WWDC2018 ] - 了解Swift Package Manager Getting to Know Swift Package Manager

Getting to Know Swift Package Manager

概述

Swift Package Manager(简称SPM),是Apple官方提供的软件包管理器,类比如Ruby的RubyGems, Python的pip。开源框架里知名度较高的SwiftyJSONSQLite.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.

package.png

  • Products
    Products可以理解为Package输出的形态。对比与Cocoapods只能以静态库/动态库形式,SPM还可以输出为可执行文件。

  • Target
    Target理解为包含多个文件的一个模块,target之间是可以有依赖关系,同时,输出的Products也会依赖一个或多个target。

  • Dependencies
    Dependencies描述了当前的package需要依赖其他package。

一个典型的Package目录如下:

example-package-playingcard
├── Sources
│   └── DeckOfPlayingCards
│       ├── DeckOfPlayingCards.swift
│       ├── Rank.swift
│       └── Suit.swift
└── Package.swift

其中Package.swift的定义:

let package = Package(
    name: "DeckOfPlayingCards",
    products: [
        .library(name: "DeckOfPlayingCards", targets: ["DeckOfPlayingCards"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/example-package-fisheryates.git", from: "2.0.0"),
        .package(url: "https://github.com/apple/example-package-playingcard.git", from: "3.0.0"),
    ],
    targets: [
        .target(
            name: "DeckOfPlayingCards",
            dependencies: ["FisherYates", "PlayingCard"]),
        .testTarget(
            name: "DeckOfPlayingCardsTests",
            dependencies: ["DeckOfPlayingCards"]),
    ])

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


1 (2).png

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更深入了解的读者可参考[官网介绍](Semantic Versioning)。下图就是一个采用Semver版本控制的Package依赖树结构。

semfer.png

Building

SPM采用了swift-llbuild ,一个并行、高效、增量编译的构建系统作为其构建引擎。目前Xcode9也已集成,用作对LLVM、Clang及Swift的构建。同时,因为独立沙盒的构建环境,SPM提供了很强的安全性。

Workflow Features

如果你的某个软件包还处于开发模式下,tag的集成方式很不方便,类似于Cocoapods的做法,SPM也会提供分支依赖本地依赖做法。

Tools Evolution

和Cocoapods一样,当我们的软件包需要依赖特定的swift版本,需要在配置描述里显示声明。声明的枚举类型如下

/// Represents the version of the Swift language that should be used for
/// compiling Swift sources in the package.
public enum SwiftVersion {
    case v3
    case v4
    case v4_2

    /// User-defined value of Swift version.
    ///
    /// The value is passed as-is to Swift compiler's `-swift-version` flag.
    case version(String)
}

例如指定版本为4.0

// swift-tools-version:4.2

import PackageDescription

let package = Package(
    name: "HTTPClient",
    ...
    swiftLanguageVersions: [.v4, .v4_2]
)

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容