如何以编程方式加载 Swift 包配置?

How can I load a Swift package configuration programmatically?

我正在尝试使用 SwiftPM 来分析本地 Package.swift 文件。我找不到任何关于如何这样做的文档。理想情况下,我会调用

import PackageDescription

let package = try Package(at: "pathToFile/Package.swift")
print(package.dependencies) ...

我试过使用

 let package = try PackageBuilder.loadPackage(
            packagePath: .init(absolutePath),
            swiftCompiler: .init("/usr/bin/swift"),
            swiftCompilerFlags: [],
            diagnostics: .init())

但这失败了 error: no such module \'PackageDescription\'\nimport PackageDescription\n ^", diagnosticFile: nil),因为我的 Package.swift 文件按预期以 import PackageDescription 开头。

也许有什么事发生 here

你让我很好奇,我快速浏览了一下。

也许您会在 swift-package-manager 存储库中找到更多信息: https://github.com/apple/swift-package-manager

我会考虑这些选项,以便实施:

  • 寻找 'Package.swift',如果提供了文件夹,请使用其他路径。
  • 您需要将文件加载到解释器中,以便访问 let package 定义。
  • 实施的另一个解决方案可能是将 swift 文件解析为结构实例,存储库可能会告诉。

通过这些你可以访问整个包定义, 我建议调查: https://github.com/apple/swift-package-manager/tree/main/Sources/PackageLoading

希望这对某些方面有所帮助。

编辑:.
找到一个更完整的示例来使用您已经引用的链接。

检查:https://github.com/apple/swift-package-manager/blob/main/Examples/package-info/Sources/package-info/main.swift

它解释了如何使用最小配置来加载包文件。

您应该使用 swiftCompiler 参数提供编译器的完整路径以避免您的问题,例如:

import PackageModel
import PackageLoading
import PackageGraph
import Workspace

let swiftCompiler: AbsolutePath = {
    let string: String
#if os(macOS)
    string = try! Process.checkNonZeroExit(args: "xcrun", "--sdk", "macosx", "-f", "swiftc").spm_chomp()
#else
    string = try! Process.checkNonZeroExit(args: "which", "swiftc").spm_chomp()
#endif
    return AbsolutePath(string)
}()

let package = AbsolutePath(".../swift-package-manager")
let diagnostics = DiagnosticsEngine()

do {
    let manifest = try ManifestLoader.loadManifest(packagePath: package, swiftCompiler: swiftCompiler, packageKind: .local)
    let loadedPackage = try PackageBuilder.loadPackage(packagePath: package, swiftCompiler: swiftCompiler, diagnostics: diagnostics)
    let graph = try Workspace.loadGraph(packagePath: package, swiftCompiler: swiftCompiler, diagnostics: diagnostics)
    
    // Manifest
    let products = manifest.products.map({ [=10=].name }).joined(separator: ", ")
    print("Products:", products)
    let targets = manifest.targets.map({ [=10=].name }).joined(separator: ", ")
    print("Targets:", targets)
    
    // Package
    let executables = loadedPackage.targets.filter({ [=10=].type == .executable }).map({ [=10=].name })
    print("Executable targets:", executables)
    
    // PackageGraph
    let numberOfFiles = graph.reachableTargets.reduce(0, { [=10=] + .sources.paths.count })
    print("Total number of source files (including dependencies):", numberOfFiles)
}
catch {
    print(error)
}

输出:

Products: SwiftPM, SwiftPM-auto, PackageDescription
Targets: PackageDescription, LLBuildManifest, SourceControl, SPMLLBuild, PackageModel, PackageLoading, PackageGraph, Build, Xcodeproj, Workspace, Commands, swift-package, swift-build, swift-test, swift-run, swiftpm-xctest-helper, SPMTestSupport, BuildTests, CommandsTests, WorkspaceTests, FunctionalTests, FunctionalPerformanceTests, PackageDescription4Tests, PackageLoadingTests, PackageLoadingPerformanceTests, PackageModelTests, PackageGraphTests, PackageGraphPerformanceTests, SourceControlTests, XcodeprojTests
Executable targets: ["swift-run", "swift-build", "swift-package", "swiftpm-xctest-helper", "swift-test"]
Total number of source files (including dependencies): 344