Swift 包管理器:如何将本地共享库添加为多个可执行文件的依赖项?

Swift Package Manager: How to add local shared library as dependency to multiple executables?

我有一个简单的 gRPC 应用程序、一个客户端和一个服务器。两者都依赖于生成的 swift-grpc 绑定。 为简单起见,当我将共享文件一次复制到客户端文件夹并第二次复制到服务器文件夹时,swift 构建并运行两者。出于显而易见的原因,我想将共享文件分成共享库、服务器库和客户端库,目的是仅将共享库和客户端特定库导入客户端。

从我的共享库 DmxLib 开始,我无法理解 Package.swift 文件。 本质上,文档说,创建一个库,将其添加为依赖项,然后就可以了。当我这样做时,Swift 构建失败,说导入的文件不存在。当我将 DmXLib 文件夹中的本地文件添加到产品依赖项时,它告诉我找不到该文件。

编辑器是 VSCode,平台是 Ubuntu 20.04 和 Swift 5.3,没有 XCode。

我如何正确地声明一个共享的本地库,它可以被导入并实际用于客户端和服务器?

我的源代码树是这样的

还有我的 Package.swift 文件

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

        import PackageDescription

        let package = Package(
            name: "dmx-db",
            products: [
                .executable(name: "DmxServer", targets: ["DmxServer"]),
                .executable(name: "DmxClient", targets: ["DmxClient"]),
                // This lib will be imported into both, client and server. 
                .library(name: "DmxLib", targets: ["DmxLib"]),
            ],  
            dependencies: [
                .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.21"),
                .package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "1.0.0"),
                .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "1.0.0-alpha.5"),
                // Why do I have to declare local files as dependencies???
                .package(path: "../Sources/DmxLib/datasource.grpc.swift")
                ],
            //
            targets: [
                .target(name: "DmxLib", dependencies: [
                    "datasource.grpc.swift" 
                ] ),

                .target(name: "DmxServer", dependencies: [
                    "DmxLib", 
                    .product(name: "GRPC", package: "grpc-swift"),
                    .product(name: "PostgresClientKit", package: "PostgresClientKit"), 
                    .product(name: "Lifecycle", package: "swift-service-lifecycle"), 
                    ]),

                .target(name: "DmxClient", dependencies: [
                    "DmxLib",
                    .product(name: "GRPC", package: "grpc-swift"),
                ]),
            ] 
        )

这应该可以做到。您不需要向所有源都在本地计算机上的目标添加“依赖项”。

// swift-tools-version:5.3

import PackageDescription

let package = Package(
    name: "dmx-db",
    products: [
        .executable(name: "DmxServer", targets: ["DmxServer"]),
        .executable(name: "DmxClient", targets: ["DmxClient"]),
                // This lib will be imported into both, client and server. 
        .library(name: "DmxLib", targets: ["DmxLib"]),
    ],
    dependencies: [
        .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.21"),
        .package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "1.0.0"),
        .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "1.0.0-alpha.5"),
    ],
    targets: [
        .target(name: "DmxServer", dependencies: [
            "DmxLib", 
            .product(name: "GRPC", package: "grpc-swift"),
            .product(name: "PostgresClientKit", package: "PostgresClientKit"), 
            .product(name: "Lifecycle", package: "swift-service-lifecycle"), 
        ]),
        .target(name: "DmxClient", dependencies: [
            "DmxLib",
            .product(name: "GRPC", package: "grpc-swift"),
        ]),
        .target(name: "DmxLib", dependencies: []),
    ]
)

这确实需要您在包的根目录中有一个 Sources 目录,并且在其中有三个文件夹,分别命名为 DmxLibDmxClientDmxServer,分别.

注意:我实际上已经将 swift-tools-version 更新为 5.3,因为我从 one of my projects 复制并修改了它,但我认为它应该适用于 [=15] =] 的 5.2

对于LOCAL,我们受苦了Xcode UI/UX..

(在我的示例中,我有一个 SPM“LocalSPMLib”和一个消费者应用程序“LocalSPMConsumerApp”)

你可以这样做:

  1. 照常添加 SPM 通过 SPM 菜单添加或拖入项目。

它将添加到项目中,但不会工作... 应该出现在二进制文件下但不是 ;(

  1. RE-add 作为二进制库(糟糕...但有效...)

现在您可以调用:

import XCTest
import LocalSPMLib

@testable import LocalSPMConsumerApp

class LocalSPMConsumerAppTests: XCTestCase {

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {
        XCTAssertEqual(LocalSPMLib().version, 1)

    }

}