Swift

[ WWDC2018 ] - 了解Swift Package M

2018-06-19  本文已影响0人  字节跳动技术团队

Getting to Know Swift Package Manager

概述

Swift Package Manager(简称SPM),是Apple官方提供的软件包管理器,类比如Ruby的RubyGems, Python的pip。开源框架里知名度较高的SwiftyJSONSQLite.swift等都已支持SPM集成。

WWDC18专门开了一个Session介绍了SPM的内部结构、基本使用及设计理念,并介绍了之后即将支持的一些新特性。

为什么要使用SPM

SPM基本用法

SPM的基本概念可参见官网描述

常用命令

内部结构

对于一个Package来说,主要分为三部分,Target、Products、Dependencies.

package.png

一个典型的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的一些设计思想:

下图描述了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的未来新特性

预见到等到合适的时机,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

上一篇下一篇

猜你喜欢

热点阅读