You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建含多组件的Swift包(SPM)并实现独立版本化?

单仓多Swift组件的版本与结构解决方案

一、目录结构规范

根据是否需要组件独立版本,推荐两种清晰的目录结构:

方案1:单Package多产品(版本统一)

适合接受整个仓库共用一个版本号,仅需多个独立library供外部依赖的场景:

newskit-themes/
├── .gitignore
├── Package.swift
├── Newskit/
│   ├── Sources/
│   │   └── Newskit/          # 存放Newskit的所有.swift源码
│   └── Tests/
│       └── NewskitTests/     # 存放Newskit的测试代码
└── TheSun/
    ├── Sources/
    │   └── TheSun/           # 存放TheSun的所有.swift源码
    └── Tests/
        └── TheSunTests/      # 存放TheSun的测试代码

方案2:单仓多独立Package(组件单独版本)

适合需要每个组件拥有独立版本号的场景:

newskit-themes/
├── .gitignore
├── Newskit/
│   ├── Package.swift         # Newskit专属的包配置文件
│   ├── Sources/
│   │   └── Newskit/
│   └── Tests/
│       └── NewskitTests/
└── TheSun/
    ├── Package.swift         # TheSun专属的包配置文件
    ├── Sources/
    │   └── TheSun/
    └── Tests/
        └── TheSunTests/

二、对应的Package.swift写法

方案1:单Package多产品的配置

优化原有代码,添加测试target并指定路径,确保SwiftPM正确识别源码位置:

// swift-tools-version:5.7
import PackageDescription

let package = Package(
    name: "newskit-themes",
    platforms: [.iOS(.v12)],
    products: [
        // 定义两个独立的library产品
        .library(name: "Newskit", targets: ["Newskit"]),
        .library(name: "TheSun", targets: ["TheSun"])
    ],
    targets: [
        // Newskit主target
        .target(
            name: "Newskit",
            path: "Newskit/Sources/Newskit"
        ),
        // Newskit测试target
        .testTarget(
            name: "NewskitTests",
            dependencies: ["Newskit"],
            path: "Newskit/Tests/NewskitTests"
        ),
        // TheSun主target
        .target(
            name: "TheSun",
            path: "TheSun/Sources/TheSun"
        ),
        // TheSun测试target
        .testTarget(
            name: "TheSunTests",
            dependencies: ["TheSun"],
            path: "TheSun/Tests/TheSunTests"
        )
    ]
)

这种方式下,给整个仓库打统一git tag(如1.0.0)即可,外部项目可单独依赖某个library:

// 外部项目的Package.swift
dependencies: [
    .package(url: "https://github.com/你的用户名/newskit-themes.git", from: "1.0.0")
],
targets: [
    .target(
        name: "你的项目",
        dependencies: ["Newskit"] // 仅依赖Newskit
    )
]

方案2:多独立Package的配置

每个组件的Package.swift完全独立,以Newskit为例:

// Newskit/Package.swift
// swift-tools-version:5.7
import PackageDescription

let package = Package(
    name: "Newskit",
    platforms: [.iOS(.v12)],
    products: [
        .library(name: "Newskit", targets: ["Newskit"])
    ],
    targets: [
        .target(name: "Newskit"),
        .testTarget(name: "NewskitTests", dependencies: ["Newskit"])
    ]
)

TheSun的Package.swift只需把name和target名替换为TheSun即可。

这种方式下,需为每个组件单独打git tag(建议前缀区分,如newskit-2.1.0、thesun-1.3.0),外部项目可单独依赖指定版本的组件:

// 外部项目的Package.swift
dependencies: [
    .package(url: "https://github.com/你的用户名/newskit-themes.git", path: "Newskit", from: "2.1.0"),
    .package(url: "https://github.com/你的用户名/newskit-themes.git", path: "TheSun", from: "1.3.0")
]

三、关键注意事项

  • 命名习惯:Swift包和target名建议用大驼峰格式(如Newskit而非newskit),符合社区通用规范。
  • 版本管理:单Package方案版本统一,更新任意组件都需升级仓库版本;多独立Package方案版本独立,需注意tag命名清晰避免混淆。
  • 测试隔离:每个组件都应配置专属的测试target,保证测试代码和业务代码分离,便于维护。

内容的提问来源于stack exchange,提问作者Marco Vanali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:35:27