Swift Package Manager: ¿Cómo añadir biblioteca compartida local como dependencia a múltiples ejecutables?

Tengo una sencilla aplicación gRPC, un cliente y un servidor. Ambos confían en las uniones generadas de grpc rápido. Para la simplicidad, cuando copie los archivos compartidos una vez en la carpeta cliente y una segunda vez en la carpeta servidor, swift construye y ejecuta ambos. Por razones obvias, quiero separar los archivos compartidos en, bueno, una lib compartida, un servidor lib, y una lib cliente con el objetivo de importar solamente libs compartidas y específicas cliente en el cliente.

Comenzando con mi lib compartida, llamada DmxLib, no puedo conseguir mi cabeza alrededor del paquete. archivo rápido. Esencialmente, los doctores dicen, hacer una lib, añadirla como dependencia y aquí vas. Cuando lo hago, Swift build falla diciendo que los archivos importados no están ahí. Cuando agrego los archivos locales de la carpeta DmXLib a las dependencias del producto, me dice que el archivo no se puede encontrar.

Editor es VSCode y la plataforma es Ubuntu 20.04 con Swift 5.3, no XCode.

¿Cómo declaro correctamente una biblioteca local compartida que puede ser importada y realmente ser utilizada en ambos, el cliente y el servidor?

Mi árbol fuente parece así

enter image description here

Y mi paquete. archivo rápido

        // 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"),
                ]),
            ] 
        )

Pregunta hecha hace 3 años, 4 meses, 28 días - Por apiartisan


4 Respuestas:

  • para LOCAL sufrimos por un mal Xcode UI/UX ..

    (en mi muestra tengo un SPM, "LocalSPMLib" y una aplicación de consumo, "LocalSPMConsumerApp")

    Puedes hacerlo de esta manera:

    1. añadir SPM como siempre añadiendo a través de menús SPM o arrastrando al proyecto.

    añadirá al proyecto, pero no funcionará... Debe aparecer bajo binarios pero NO ;

    1. RE-add as a Binary Lib (vergüenza... pero funciona.)

    enter image description here

    Ahora Puede invocar:

    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)
    
        }
    
    }
    

    Respondida el Dec 17, 2020 a las 11:32 - por htmlhelix

    Votos positivos: 0 | Votos negativos: 0

  • Esto debería hacerlo. Usted no necesita añadir una "dependencia" a un objetivo donde todas las fuentes están en su computadora local.

    // 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: []),
        ]
    )
    

    Esto requiere que usted tenga un Sources directorio en el directorio raíz de tu paquete, y dentro de él tienes tres carpetas, llamadas DmxLib, DmxClient, y DmxServer, respectivamente.

    Nota: En realidad he actualizado el swift-tools-version a 5.3, porque copiado y modificado esto de uno de mis proyectos, pero creo que debe funcionar con un swift-tools-version de 5.2

    Respondida el Dec 17, 2020 a las 11:38 - por byteninja8245

    Votos positivos: 0 | Votos negativos: 0

  • En este caso, parece que estás intentando agregar un archivo específico como una dependencia en lugar de agregar toda la biblioteca compartida como una dependencia en la configuración de tu Package.swift. Aquí hay algunos pasos para corregir esto:

    • Crea una estructura de archivos adecuada para tu proyecto. Asegúrate de tener una carpeta para tu librería compartida (DmxLib), una para el servidor (DmxServer) y otra para el cliente (DmxClient).
    • Mueve todos los archivos relacionados con DmxLib a la carpeta correspondiente.
    • Asegúrate de que tu Package.swift esté bien configurado. Elimina la declaración de la dependencia local específica `datasource.grpc.swift` y en su lugar incluye la carpeta entera de DmxLib como una dependencia para los objetivos que la requieren.
    • Asegúrate de que la estructura de tus carpetas coincida con la estructura de tu Package.swift. Por ejemplo, si has declarado `DmxLib` como un producto en tu Package.swift, asegúrate de tener una carpeta llamada `DmxLib` que contenga los archivos correspondientes.
    • Vuélvete a ejecutar `swift build` para verificar que no haya errores.

    Aquí hay una versión corregida de tu archivo Package.swift con los cambios sugeridos:

    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"]),
            .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: "DmxLib", dependencies: []),
    
            .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"),
            ]),
        ] 
    )
    

    Espero que estos pasos te ayuden a resolver tu problema. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 11:28 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema:

    El error que estás encontrando se debe a que estás intentando importar archivos locales de una carpeta diferente (../Sources/DmxLib/datasource.grpc.swift) en el archivo Package.swift sin declarar correctamente la dependencia.

    La solución:

    Para resolver este problema, debes agregar el directorio DmxLib como una dependencia local en el archivo Package.swift y luego importar los archivos necesarios desde esa dependencia.

    Pasos detallados:

    • Agrega el directorio `DmxLib` como una dependencia local:
    
    dependencies: [
        // Dependencias existentes
        ...,
        // Nueva dependencia local
        .package(path: "../DmxLib")
    ]
    
    • Actualiza la declaración de destino `DmxLib` para importar los archivos necesarios desde la dependencia local:
    
    targets: [
        // Objetivos existentes
        ...,
        // Objetivo actualizado para DmxLib
        .target(name: "DmxLib", dependencies: [
            "DmxLib" // Dependencia local añadida
        ]),
        // Otros objetivos
        ...
    ]
    

    Archivo Package.swift actualizado:

    
    // swift-tools-version:5.2
    
    import PackageDescription
    
    let package = Package(
        name: "dmx-db",
        products: [
            .executable(name: "DmxServer", targets: ["DmxServer"]),
            .executable(name: "DmxClient", targets: ["DmxClient"]),
            .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"),
            .package(path: "../DmxLib") // Dependencia local añadida
        ],
        targets: [
            .target(name: "DmxLib", dependencies: ["DmxLib"]), // Dependencia local añadida
            .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"), ]),
        ]
    )
    

    Una vez que hayas realizado estos cambios, el compilador podrá encontrar y utilizar correctamente los archivos compartidos de DmxLib en tus ejecutables de cliente y servidor.

    Respondida el Dec 18, 2020 a las 11:42 - por Gemini

    Votos positivos: 0 | Votos negativos: 0