Package Generator

⚠️这是 Beta 版本

Package Generator 是一个 Swift Package Manager 插件,用于简单且一致地更新你的 Package.swift 文件。对于高度模块化或使用 TCA 并因此依赖于干净且更新的 Package.swift 的项目来说,这是一个很棒的工具。

Package Generator 将从源代码文件中读取的 imports 添加到 Package.swift 中的目标 (target) 中。 这将有助于减少 SwiftUI Preview 的编译问题。

首次启动

安装它之后,你将能够运行它,但为了使其正常工作,它需要被配置。 默认情况下,它将以 dry-run 设置为 true 运行,这将创建一个文件 Package_generated.swift 以允许你预览将要发生的事情。 在正确配置并测试 Package_generated.swift 生成了正确的内容之后,你将需要在配置中将 dry-run 设置为 false,以写入真实的 Package.swift 文件。

每次你需要添加模块时,请记住将其添加到配置文件中。

它是如何工作的?

Package Generator 会进入配置中设置的所有文件夹,然后读取所有 Swift 文件,以查找所有 imports,从而创建一个目标 (target) 添加到 Package.swift 中。

代码分析部分是使用 swift-syntax 完成的,因为我找不到将其链接到插件的方法,所以我必须将其打包在 CLI 中,该 CLI 用于执行解析部分。

安装

添加到你的依赖项中: .package(url: "https://github.com/mackoj/PackageGeneratorPlugin.git", from: "0.5.0"),

基本用法

插件将在 Xcode Report navigator 中显示消息和错误。

步骤 描述 图片
0 要运行它,请右键单击要运行它的 package。 Capture d’écran 2022-11-07 à 11 04 05
1 它将建议你运行它,你可以在参数窗格中提供一个可选参数 (--confFile newName.json),这将允许你更改配置文件的名称。 一旦更改,新的配置文件名将被存储 Capture d’écran 2022-11-07 à 11 05 28
2 首次启动时,它将请求写入项目目录的权限,为了使其工作,你必须选择 “允许命令更改文件”。 Capture d’écran 2022-12-14 à 15 38 34

默认情况下,为了防止任何意外,它将执行 dry-run(不修改你的 Package.swift,而是创建一个 Package_generated.swift),以便你有时间在使用它之前进行审查。

配置

要使用它,你必须在项目的根目录中设置一个名为 packageGenerator.json 的配置文件。 此文件包含以下键:

{
  "packageDirectories": [
    "Sources/App/Clients/Analytics",
    "Sources/App/Clients/AnalyticsLive",
    "Sources/App/Daemons/Notification",
    "Sources/App/Helpers/Foundation"
  ],
  "headerFileURL": "header.swift",
  "targetsParameters": {
    "Analytics": ["exclude: [\"__Snapshots__\"]", "resources: [.copy(\"Fonts/\")]"],
    "target2": ["resources: [.copy(\"Dictionaries/\")]"]
  },
  "verbose": false,
  "pragmaMark": false,
  "spaces": 2,
  "dryRun": true,
  "mappers": {
    "targets": {
      "Sources/App/Helpers/Foundation/": "FoundationHelpers",
    },
    "imports": {
      "ComposableArchitecture": ".product(name: \"ComposableArchitecture\", package: \"swift-composable-architecture\")"
    }
  },
  "exclusions": {
    "apple": [
      "ARKit",
      "AVFoundation"
    ],
    "imports": [
      "PurchasesCoreSwift"
    ],
    "targets": [
      "ParserCLI"
    ]
  }
}

如果使用了新的配置文件名(如 #basic-usage 步骤 1 中所述)。 它将被保存,以便你无需在每次启动时都输入配置文件名。

Header File (头部文件)

来自配置的 headerFileURL 的内容将被添加到生成的 Package.swift 的顶部。

我建议添加所有必需的 dependenciesTest Targets(测试目标), System Librarys(系统库), Executable Targets(可执行目标) 和 Binary Targets(二进制目标)(#8)。

// swift-tools-version:5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import Foundation
import PackageDescription

var package = Package(
  name: "project",
  defaultLocalization: "en",
  platforms: [
    .macOS(.v12),
    .iOS("15.0")
  ],
  products: [
    .executable(name: "server", targets: ["server"]),
    .executable(name: "parse", targets: ["ParserRunner"]),
  ],
  dependencies: [
    .package(url: "https://github.com/mackoj/PackageGeneratorPlugin.git", from: "0.3.0"),
    .package(url: "https://github.com/mackoj/SchemeGeneratorPlugin.git", from: "0.5.5"),
    .package(url: "https://github.com/pointfreeco/swift-composable-architecture.git", from: "0.45.0"),
  ],
  targets: [
    // MARK: -
    // MARK: Test Targets
    .testTarget(
      name: "MyProjectTests",
      dependencies: [
        "MyProject",
      ]
    ),
    
    // MARK: -
    // MARK: Executables
      .executableTarget(
        name: "server",
        path: "Sources/Backend/Sources/Run"
      ),
    .executableTarget(
      name: "ParserRunner",
      path: "Sources/App/Parsers/Runner"
    ),
  ]
)

CI

你可以在 CI 中使用它来自动生成你的 Package.swift

swift package plugin --allow-writing-to-package-directory package-generator

FAQ

为什么在 Xcode 中看不到该插件?

如果你右键单击你的项目 package,并且仅当 Resolves Packages 没有问题时,插件才能工作。

为什么插件有可执行依赖项?

因为我们无法在 SPM 插件中导入其他 package,并且我们需要 swift-syntax 来解析代码并提取 imports。

它总是创建一个无效的 Package.swift 文件。

查看 Xcode 中的 Report Navigator,这可能是由于不存在的 imports 或需要使用 mappers-imports 导致的。

为什么它不使用像 .packageGenerator 这样的隐藏文件来配置工具?

因为它在 Xcode 中不可见,并且此文件可能需要经常编辑。 但是,如果你想这样做,可以在使用该工具时提供 --confFile 参数来更改此设置