diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4b87fe91e..f049d5e18 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,11 +25,9 @@ jobs: fail-fast: false matrix: include: - - image: swift:6.1 - swift-build-flags: -c release - - image: swift:6.0-jammy + - image: swift:6.2 swift-build-flags: -c release - - image: swift:5.10.1-noble + - image: swift:6.1 swift-build-flags: -c release name: Build and Test on ${{ matrix.image }} runs-on: ubuntu-latest @@ -48,19 +46,8 @@ jobs: fail-fast: false matrix: include: - - image: swift:6.1 - swift-version: '6.1' - env: - MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_10_requests: 323000 - MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_1_request: 161000 - MAX_ALLOCS_ALLOWED_embedded_server_bidi_1k_rpcs_10_small_requests: 110000 - MAX_ALLOCS_ALLOWED_embedded_server_bidi_1k_rpcs_1_small_request: 65000 - MAX_ALLOCS_ALLOWED_embedded_server_unary_1k_rpcs_1_small_request: 61000 - MAX_ALLOCS_ALLOWED_unary_1k_ping_pong: 163000 - MAX_ALLOCS_ALLOWED_unary_1k_ping_pong_interceptors_client: 170000 - MAX_ALLOCS_ALLOWED_unary_1k_ping_pong_interceptors_server: 170000 - - image: swift:6.0-jammy - swift-version: '6.0' + - image: swift:6.2 + swift-version: '6.2' env: MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_10_requests: 323000 MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_1_request: 161000 @@ -70,8 +57,8 @@ jobs: MAX_ALLOCS_ALLOWED_unary_1k_ping_pong: 163000 MAX_ALLOCS_ALLOWED_unary_1k_ping_pong_interceptors_client: 170000 MAX_ALLOCS_ALLOWED_unary_1k_ping_pong_interceptors_server: 170000 - - image: swift:5.10.1-noble - swift-version: '5.10' + - image: swift:6.1 + swift-version: '6.1' env: MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_10_requests: 323000 MAX_ALLOCS_ALLOWED_bidi_1k_rpcs_1_request: 161000 @@ -96,12 +83,10 @@ jobs: fail-fast: false matrix: include: + - image: swift:6.2 + swift-tools-version: '6.2' - image: swift:6.1 swift-tools-version: '6.1' - - image: swift:6.0-jammy - swift-tools-version: '6.0' - - image: swift:5.10.1-noble - swift-tools-version: '5.10' name: Integration Tests on ${{ matrix.image }} runs-on: ubuntu-latest container: diff --git a/Package.swift b/Package.swift index 70254e4b7..a70c4ceea 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.10 +// swift-tools-version: 6.1 /* * Copyright 2017, gRPC Authors All rights reserved. * @@ -26,6 +26,7 @@ let grpcTargetName = grpcProductName let cgrpcZlibTargetName = cgrpcZlibProductName let includeNIOSSL = ProcessInfo.processInfo.environment["GRPC_NO_NIO_SSL"] == nil +let defaultSwiftSettings: [SwiftSetting] = [.swiftLanguageMode(.v5)] // MARK: - Package Dependencies @@ -80,400 +81,487 @@ let packageDependencies: [Package.Dependency] = [ extension Target.Dependency { // Target dependencies; external - static let grpc: Self = .target(name: grpcTargetName) - static let cgrpcZlib: Self = .target(name: cgrpcZlibTargetName) - static let protocGenGRPCSwift: Self = .target(name: "protoc-gen-grpc-swift") - static let reflectionService: Self = .target(name: "GRPCReflectionService") + static var grpc: Self { .target(name: grpcTargetName) } + static var cgrpcZlib: Self { .target(name: cgrpcZlibTargetName) } + static var protocGenGRPCSwift: Self { .target(name: "protoc-gen-grpc-swift") } + static var reflectionService: Self { .target(name: "GRPCReflectionService") } // Target dependencies; internal - static let grpcSampleData: Self = .target(name: "GRPCSampleData") - static let echoModel: Self = .target(name: "EchoModel") - static let echoImplementation: Self = .target(name: "EchoImplementation") - static let helloWorldModel: Self = .target(name: "HelloWorldModel") - static let routeGuideModel: Self = .target(name: "RouteGuideModel") - static let interopTestModels: Self = .target(name: "GRPCInteroperabilityTestModels") - static let interopTestImplementation: Self = + static var grpcSampleData: Self { .target(name: "GRPCSampleData") } + static var echoModel: Self { .target(name: "EchoModel") } + static var echoImplementation: Self { .target(name: "EchoImplementation") } + static var helloWorldModel: Self { .target(name: "HelloWorldModel") } + static var routeGuideModel: Self { .target(name: "RouteGuideModel") } + static var interopTestModels: Self { .target(name: "GRPCInteroperabilityTestModels") } + static var interopTestImplementation: Self { .target(name: "GRPCInteroperabilityTestsImplementation") - static let interoperabilityTests: Self = .target(name: "InteroperabilityTests") + } + static var interoperabilityTests: Self { .target(name: "InteroperabilityTests") } // Product dependencies - static let argumentParser: Self = .product( - name: "ArgumentParser", - package: "swift-argument-parser" - ) - static let nio: Self = .product(name: "NIO", package: "swift-nio") - static let nioConcurrencyHelpers: Self = .product( - name: "NIOConcurrencyHelpers", - package: "swift-nio" - ) - static let nioCore: Self = .product(name: "NIOCore", package: "swift-nio") - static let nioEmbedded: Self = .product(name: "NIOEmbedded", package: "swift-nio") - static let nioExtras: Self = .product(name: "NIOExtras", package: "swift-nio-extras") - static let nioFoundationCompat: Self = .product(name: "NIOFoundationCompat", package: "swift-nio") - static let nioHTTP1: Self = .product(name: "NIOHTTP1", package: "swift-nio") - static let nioHTTP2: Self = .product(name: "NIOHTTP2", package: "swift-nio-http2") - static let nioPosix: Self = .product(name: "NIOPosix", package: "swift-nio") - static let nioSSL: Self = .product(name: "NIOSSL", package: "swift-nio-ssl") - static let nioTLS: Self = .product(name: "NIOTLS", package: "swift-nio") - static let nioTransportServices: Self = .product( - name: "NIOTransportServices", - package: "swift-nio-transport-services" - ) - static let nioTestUtils: Self = .product(name: "NIOTestUtils", package: "swift-nio") - static let nioFileSystem: Self = .product(name: "_NIOFileSystem", package: "swift-nio") - static let logging: Self = .product(name: "Logging", package: "swift-log") - static let protobuf: Self = .product(name: "SwiftProtobuf", package: "swift-protobuf") - static let protobufPluginLibrary: Self = .product( - name: "SwiftProtobufPluginLibrary", - package: "swift-protobuf" - ) - static let atomics: Self = .product(name: "Atomics", package: "swift-atomics") - static let dequeModule: Self = .product(name: "DequeModule", package: "swift-collections") + static var argumentParser: Self { + .product( + name: "ArgumentParser", + package: "swift-argument-parser" + ) + } + static var nio: Self { .product(name: "NIO", package: "swift-nio") } + static var nioConcurrencyHelpers: Self { + .product( + name: "NIOConcurrencyHelpers", + package: "swift-nio" + ) + } + static var nioCore: Self { .product(name: "NIOCore", package: "swift-nio") } + static var nioEmbedded: Self { .product(name: "NIOEmbedded", package: "swift-nio") } + static var nioExtras: Self { .product(name: "NIOExtras", package: "swift-nio-extras") } + static var nioFoundationCompat: Self { .product(name: "NIOFoundationCompat", package: "swift-nio") } + static var nioHTTP1: Self { .product(name: "NIOHTTP1", package: "swift-nio") } + static var nioHTTP2: Self { .product(name: "NIOHTTP2", package: "swift-nio-http2") } + static var nioPosix: Self { .product(name: "NIOPosix", package: "swift-nio") } + static var nioSSL: Self { .product(name: "NIOSSL", package: "swift-nio-ssl") } + static var nioTLS: Self { .product(name: "NIOTLS", package: "swift-nio") } + static var nioTransportServices: Self { + .product( + name: "NIOTransportServices", + package: "swift-nio-transport-services" + ) + } + static var nioTestUtils: Self { .product(name: "NIOTestUtils", package: "swift-nio") } + static var nioFileSystem: Self { .product(name: "_NIOFileSystem", package: "swift-nio") } + static var logging: Self { .product(name: "Logging", package: "swift-log") } + static var protobuf: Self { .product(name: "SwiftProtobuf", package: "swift-protobuf") } + static var protobufPluginLibrary: Self { + .product( + name: "SwiftProtobufPluginLibrary", + package: "swift-protobuf" + ) + } + static var atomics: Self { .product(name: "Atomics", package: "swift-atomics") } + static var dequeModule: Self { .product(name: "DequeModule", package: "swift-collections") } } // MARK: - Targets extension Target { - static let grpc: Target = .target( - name: grpcTargetName, - dependencies: [ - .cgrpcZlib, - .nio, - .nioCore, - .nioPosix, - .nioEmbedded, - .nioFoundationCompat, - .nioTLS, - .nioTransportServices, - .nioHTTP1, - .nioHTTP2, - .nioExtras, - .logging, - .protobuf, - .dequeModule, - .atomics - ].appending( - .nioSSL, if: includeNIOSSL - ), - path: "Sources/GRPC" - ) - - static let cgrpcZlib: Target = .target( - name: cgrpcZlibTargetName, - path: "Sources/CGRPCZlib", - linkerSettings: [ - .linkedLibrary("z"), - ] - ) - - static let protocGenGRPCSwift: Target = .executableTarget( - name: "protoc-gen-grpc-swift", - dependencies: [ - .protobuf, - .protobufPluginLibrary, - ], - exclude: [ - "README.md", - ] - ) - - static let grpcSwiftPlugin: Target = .plugin( - name: "GRPCSwiftPlugin", - capability: .buildTool(), - dependencies: [ - .protocGenGRPCSwift, - ] - ) - - static let grpcTests: Target = .testTarget( - name: "GRPCTests", - dependencies: [ - .grpc, - .echoModel, - .echoImplementation, - .helloWorldModel, - .interopTestModels, - .interopTestImplementation, - .grpcSampleData, - .nioCore, - .nioConcurrencyHelpers, - .nioPosix, - .nioTLS, - .nioHTTP1, - .nioHTTP2, - .nioEmbedded, - .nioTransportServices, - .logging, - .reflectionService, - .atomics - ].appending( - .nioSSL, if: includeNIOSSL - ), - exclude: [ - "Codegen/Serialization/echo.grpc.reflection" - ] - ) - - static let interopTestModels: Target = .target( - name: "GRPCInteroperabilityTestModels", - dependencies: [ - .grpc, - .nio, - .protobuf, - ], - exclude: [ - "README.md", - "generate.sh", - "src/proto/grpc/testing/empty.proto", - "src/proto/grpc/testing/empty_service.proto", - "src/proto/grpc/testing/messages.proto", - "src/proto/grpc/testing/test.proto", - "unimplemented_call.patch", - ] - ) - - static let interopTestImplementation: Target = .target( - name: "GRPCInteroperabilityTestsImplementation", - dependencies: [ - .grpc, - .interopTestModels, - .nioCore, - .nioPosix, - .nioHTTP1, - .logging, - ].appending( - .nioSSL, if: includeNIOSSL - ) - ) - - static let interopTests: Target = .executableTarget( - name: "GRPCInteroperabilityTests", - dependencies: [ - .grpc, - .interopTestImplementation, - .nioCore, - .nioPosix, - .logging, - .argumentParser, - ] - ) - - static let backoffInteropTest: Target = .executableTarget( - name: "GRPCConnectionBackoffInteropTest", - dependencies: [ - .grpc, - .interopTestModels, - .nioCore, - .nioPosix, - .logging, - .argumentParser, - ], - exclude: [ - "README.md", - ] - ) - - static let perfTests: Target = .executableTarget( - name: "GRPCPerformanceTests", - dependencies: [ - .grpc, - .grpcSampleData, - .nioCore, - .nioEmbedded, - .nioPosix, - .nioHTTP2, - .argumentParser, - ] - ) - - static let grpcSampleData: Target = .target( - name: "GRPCSampleData", - dependencies: includeNIOSSL ? [.nioSSL] : [], - exclude: [ - "bundle.p12", - ] - ) - - static let echoModel: Target = .target( - name: "EchoModel", - dependencies: [ - .grpc, - .nio, - .protobuf, - ], - path: "Examples/v1/Echo/Model" - ) - - static let echoImplementation: Target = .target( - name: "EchoImplementation", - dependencies: [ - .echoModel, - .grpc, - .nioCore, - .nioHTTP2, - .protobuf, - ], - path: "Examples/v1/Echo/Implementation" - ) - - static let echo: Target = .executableTarget( - name: "Echo", - dependencies: [ - .grpc, - .echoModel, - .echoImplementation, - .grpcSampleData, - .nioCore, - .nioPosix, - .logging, - .argumentParser, - ].appending( - .nioSSL, if: includeNIOSSL - ), - path: "Examples/v1/Echo/Runtime" - ) - - static let helloWorldModel: Target = .target( - name: "HelloWorldModel", - dependencies: [ - .grpc, - .nio, - .protobuf, - ], - path: "Examples/v1/HelloWorld/Model" - ) - - static let helloWorldClient: Target = .executableTarget( - name: "HelloWorldClient", - dependencies: [ - .grpc, - .helloWorldModel, - .nioCore, - .nioPosix, - .argumentParser, - ], - path: "Examples/v1/HelloWorld/Client" - ) - - static let helloWorldServer: Target = .executableTarget( - name: "HelloWorldServer", - dependencies: [ - .grpc, - .helloWorldModel, - .nioCore, - .nioPosix, - .argumentParser, - ], - path: "Examples/v1/HelloWorld/Server" - ) - - static let routeGuideModel: Target = .target( - name: "RouteGuideModel", - dependencies: [ - .grpc, - .nio, - .protobuf, - ], - path: "Examples/v1/RouteGuide/Model" - ) - - static let routeGuideClient: Target = .executableTarget( - name: "RouteGuideClient", - dependencies: [ - .grpc, - .routeGuideModel, - .nioCore, - .nioPosix, - .argumentParser, - ], - path: "Examples/v1/RouteGuide/Client" - ) - - static let routeGuideServer: Target = .executableTarget( - name: "RouteGuideServer", - dependencies: [ - .grpc, - .routeGuideModel, - .nioCore, - .nioConcurrencyHelpers, - .nioPosix, - .argumentParser, - ], - path: "Examples/v1/RouteGuide/Server" - ) - - static let packetCapture: Target = .executableTarget( - name: "PacketCapture", - dependencies: [ - .grpc, - .echoModel, - .nioCore, - .nioPosix, - .nioExtras, - .argumentParser, - ], - path: "Examples/v1/PacketCapture", - exclude: [ - "README.md", - ] - ) - - static let reflectionService: Target = .target( - name: "GRPCReflectionService", - dependencies: [ - .grpc, - .nio, - .protobuf, - ], - path: "Sources/GRPCReflectionService" - ) - - static let reflectionServer: Target = .executableTarget( - name: "ReflectionServer", - dependencies: [ - .grpc, - .reflectionService, - .helloWorldModel, - .nioCore, - .nioPosix, - .argumentParser, - .echoModel, - .echoImplementation - ], - path: "Examples/v1/ReflectionService", - resources: [ - .copy("Generated") - ] - ) + static var grpc: Target { + .target( + name: grpcTargetName, + dependencies: [ + .cgrpcZlib, + .nio, + .nioCore, + .nioPosix, + .nioEmbedded, + .nioFoundationCompat, + .nioTLS, + .nioTransportServices, + .nioHTTP1, + .nioHTTP2, + .nioExtras, + .logging, + .protobuf, + .dequeModule, + .atomics + ].appending( + .nioSSL, if: includeNIOSSL + ), + path: "Sources/GRPC", + swiftSettings: defaultSwiftSettings + ) + } + + static var cgrpcZlib: Target { + .target( + name: cgrpcZlibTargetName, + path: "Sources/CGRPCZlib", + swiftSettings: defaultSwiftSettings, + linkerSettings: [ + .linkedLibrary("z"), + ] + ) + } + + static var protocGenGRPCSwift: Target { + .executableTarget( + name: "protoc-gen-grpc-swift", + dependencies: [ + .protobuf, + .protobufPluginLibrary, + ], + exclude: [ + "README.md", + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var grpcSwiftPlugin: Target { + .plugin( + name: "GRPCSwiftPlugin", + capability: .buildTool(), + dependencies: [ + .protocGenGRPCSwift, + ] + ) + } + + static var grpcTests: Target { + .testTarget( + name: "GRPCTests", + dependencies: [ + .grpc, + .echoModel, + .echoImplementation, + .helloWorldModel, + .interopTestModels, + .interopTestImplementation, + .grpcSampleData, + .nioCore, + .nioConcurrencyHelpers, + .nioPosix, + .nioTLS, + .nioHTTP1, + .nioHTTP2, + .nioEmbedded, + .nioTransportServices, + .logging, + .reflectionService, + .atomics + ].appending( + .nioSSL, if: includeNIOSSL + ), + exclude: [ + "Codegen/Serialization/echo.grpc.reflection" + ], + swiftSettings: defaultSwiftSettings, + ) + } + + static var interopTestModels: Target { + .target( + name: "GRPCInteroperabilityTestModels", + dependencies: [ + .grpc, + .nio, + .protobuf, + ], + exclude: [ + "README.md", + "generate.sh", + "src/proto/grpc/testing/empty.proto", + "src/proto/grpc/testing/empty_service.proto", + "src/proto/grpc/testing/messages.proto", + "src/proto/grpc/testing/test.proto", + "unimplemented_call.patch", + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var interopTestImplementation: Target { + .target( + name: "GRPCInteroperabilityTestsImplementation", + dependencies: [ + .grpc, + .interopTestModels, + .nioCore, + .nioPosix, + .nioHTTP1, + .logging, + ].appending( + .nioSSL, if: includeNIOSSL + ), + swiftSettings: defaultSwiftSettings + ) + } + + static var interopTests: Target { + .executableTarget( + name: "GRPCInteroperabilityTests", + dependencies: [ + .grpc, + .interopTestImplementation, + .nioCore, + .nioPosix, + .logging, + .argumentParser, + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var backoffInteropTest: Target { + .executableTarget( + name: "GRPCConnectionBackoffInteropTest", + dependencies: [ + .grpc, + .interopTestModels, + .nioCore, + .nioPosix, + .logging, + .argumentParser, + ], + exclude: [ + "README.md", + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var perfTests: Target { + .executableTarget( + name: "GRPCPerformanceTests", + dependencies: [ + .grpc, + .grpcSampleData, + .nioCore, + .nioEmbedded, + .nioPosix, + .nioHTTP2, + .argumentParser, + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var grpcSampleData: Target { + .target( + name: "GRPCSampleData", + dependencies: includeNIOSSL ? [.nioSSL] : [], + exclude: [ + "bundle.p12", + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var echoModel: Target { + .target( + name: "EchoModel", + dependencies: [ + .grpc, + .nio, + .protobuf, + ], + path: "Examples/v1/Echo/Model", + swiftSettings: defaultSwiftSettings + ) + } + + static var echoImplementation: Target { + .target( + name: "EchoImplementation", + dependencies: [ + .echoModel, + .grpc, + .nioCore, + .nioHTTP2, + .protobuf, + ], + path: "Examples/v1/Echo/Implementation", + swiftSettings: defaultSwiftSettings + ) + } + + static var echo: Target { + .executableTarget( + name: "Echo", + dependencies: [ + .grpc, + .echoModel, + .echoImplementation, + .grpcSampleData, + .nioCore, + .nioPosix, + .logging, + .argumentParser, + ].appending( + .nioSSL, if: includeNIOSSL + ), + path: "Examples/v1/Echo/Runtime", + swiftSettings: defaultSwiftSettings + ) + } + + static var helloWorldModel: Target { + .target( + name: "HelloWorldModel", + dependencies: [ + .grpc, + .nio, + .protobuf, + ], + path: "Examples/v1/HelloWorld/Model", + swiftSettings: defaultSwiftSettings + ) + } + + static var helloWorldClient: Target { + .executableTarget( + name: "HelloWorldClient", + dependencies: [ + .grpc, + .helloWorldModel, + .nioCore, + .nioPosix, + .argumentParser, + ], + path: "Examples/v1/HelloWorld/Client", + swiftSettings: defaultSwiftSettings + ) + } + + static var helloWorldServer: Target { + .executableTarget( + name: "HelloWorldServer", + dependencies: [ + .grpc, + .helloWorldModel, + .nioCore, + .nioPosix, + .argumentParser, + ], + path: "Examples/v1/HelloWorld/Server", + swiftSettings: defaultSwiftSettings + ) + } + + static var routeGuideModel: Target { + .target( + name: "RouteGuideModel", + dependencies: [ + .grpc, + .nio, + .protobuf, + ], + path: "Examples/v1/RouteGuide/Model", + swiftSettings: defaultSwiftSettings + ) + } + + static var routeGuideClient: Target { + .executableTarget( + name: "RouteGuideClient", + dependencies: [ + .grpc, + .routeGuideModel, + .nioCore, + .nioPosix, + .argumentParser, + ], + path: "Examples/v1/RouteGuide/Client", + swiftSettings: defaultSwiftSettings + ) + } + + static var routeGuideServer: Target { + .executableTarget( + name: "RouteGuideServer", + dependencies: [ + .grpc, + .routeGuideModel, + .nioCore, + .nioConcurrencyHelpers, + .nioPosix, + .argumentParser, + ], + path: "Examples/v1/RouteGuide/Server", + swiftSettings: defaultSwiftSettings + ) + } + + static var packetCapture: Target { + .executableTarget( + name: "PacketCapture", + dependencies: [ + .grpc, + .echoModel, + .nioCore, + .nioPosix, + .nioExtras, + .argumentParser, + ], + path: "Examples/v1/PacketCapture", + exclude: [ + "README.md", + ], + swiftSettings: defaultSwiftSettings + ) + } + + static var reflectionService: Target { + .target( + name: "GRPCReflectionService", + dependencies: [ + .grpc, + .nio, + .protobuf, + ], + path: "Sources/GRPCReflectionService", + swiftSettings: defaultSwiftSettings + ) + } + + static var reflectionServer: Target { + .executableTarget( + name: "ReflectionServer", + dependencies: [ + .grpc, + .reflectionService, + .helloWorldModel, + .nioCore, + .nioPosix, + .argumentParser, + .echoModel, + .echoImplementation + ], + path: "Examples/v1/ReflectionService", + resources: [ + .copy("Generated") + ], + swiftSettings: defaultSwiftSettings + ) + } } // MARK: - Products extension Product { - static let grpc: Product = .library( - name: grpcProductName, - targets: [grpcTargetName] - ) - - static let cgrpcZlib: Product = .library( - name: cgrpcZlibProductName, - targets: [cgrpcZlibTargetName] - ) - - static let grpcReflectionService: Product = .library( - name: "GRPCReflectionService", - targets: ["GRPCReflectionService"] - ) - - static let protocGenGRPCSwift: Product = .executable( - name: "protoc-gen-grpc-swift", - targets: ["protoc-gen-grpc-swift"] - ) - - static let grpcSwiftPlugin: Product = .plugin( - name: "GRPCSwiftPlugin", - targets: ["GRPCSwiftPlugin"] - ) + static var grpc: Product { + .library( + name: grpcProductName, + targets: [grpcTargetName] + ) + } + + static var cgrpcZlib: Product { + .library( + name: cgrpcZlibProductName, + targets: [cgrpcZlibTargetName] + ) + } + + static var grpcReflectionService: Product { + .library( + name: "GRPCReflectionService", + targets: ["GRPCReflectionService"] + ) + } + + static var protocGenGRPCSwift: Product { + .executable( + name: "protoc-gen-grpc-swift", + targets: ["protoc-gen-grpc-swift"] + ) + } + + static var grpcSwiftPlugin: Product { + .plugin( + name: "GRPCSwiftPlugin", + targets: ["GRPCSwiftPlugin"] + ) + } } // MARK: - Package