From 92667f8b3e7dd2f887aa69ccdb41f9f20da2f303 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 13 Nov 2025 15:30:53 +0000 Subject: [PATCH 1/7] Drop support for Swift 5.10 - Remove 5.10 from CI and Makefile workarounds - Remove 5.10 specific package manifests - Fix deprecation warnings from 6.0 - Bump language mode to 6 and remove 'StrictConcurrency=Complete' --- .github/workflows/build.yml | 9 -- .../Package@swift-5.10.swift | 40 -------- .../MultiModule/Package@swift-5.10.swift | 40 -------- Makefile | 16 +-- Package.swift | 3 +- Package@swift-5.10.swift | 98 ------------------- Package@swift-6.0.swift | 5 +- PluginExamples/Package@swift-5.10.swift | 60 ------------ README.md | 4 +- .../CodeGenerator.swift | 2 +- .../CommandLine+Extensions.swift | 2 +- 11 files changed, 9 insertions(+), 270 deletions(-) delete mode 100644 CompileTests/InternalImportsByDefault/Package@swift-5.10.swift delete mode 100644 CompileTests/MultiModule/Package@swift-5.10.swift delete mode 100644 Package@swift-5.10.swift delete mode 100644 PluginExamples/Package@swift-5.10.swift diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 070e73cc6..00839737a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,9 +29,6 @@ jobs: hook: "SWIFT_BUILD_TEST_HOOK=\"-Xswiftc -warnings-as-errors\"" - version: "6.0" hook: "SWIFT_BUILD_TEST_HOOK=\"-Xswiftc -warnings-as-errors\"" - - version: "5.10" - # No "hook", see https://github.com/apple/swift-protobuf/issues/1560 for the - # current issue with using -warnings-as-errors on linux. container: image: swift:${{ matrix.swift.version }} steps: @@ -51,16 +48,10 @@ jobs: - name: Test runtime run: make test-runtime ${{ matrix.swift.hook }} - name: Test plugin - # The protoc build isn't part of Package@swift-5.10.swift - if: ${{ matrix.swift.version != '5.10' }} run: make test-plugin - name: Test SPM plugin - # The protoc build isn't part of Package@swift-5.10.swift - if: ${{ matrix.swift.version != '5.10' }} run: make test-spm-plugin - name: Compilation Tests - # The protoc build isn't part of Package@swift-5.10.swift - if: ${{ matrix.swift.version != '5.10' }} run: make compile-tests api-breakage: diff --git a/CompileTests/InternalImportsByDefault/Package@swift-5.10.swift b/CompileTests/InternalImportsByDefault/Package@swift-5.10.swift deleted file mode 100644 index a1139925c..000000000 --- a/CompileTests/InternalImportsByDefault/Package@swift-5.10.swift +++ /dev/null @@ -1,40 +0,0 @@ -// swift-tools-version: 5.10 - -// Package.swift -// -// Copyright (c) 2024 Apple Inc. and the project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See LICENSE.txt for license information: -// https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt - -import PackageDescription - -let package = Package( - name: "CompileTests", - dependencies: [ - .package(path: "../..") - ], - targets: [ - .executableTarget( - name: "InternalImportsByDefault", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ], - exclude: [ - "Protos/SomeProtoWithBytes.proto", - "Protos/ServiceOnly.proto", - ], - swiftSettings: [ - .enableExperimentalFeature("InternalImportsByDefault"), - .enableExperimentalFeature("AccessLevelOnImport"), - // Enable warnings as errors so the build fails if warnings are - // present in generated code. - .unsafeFlags(["-warnings-as-errors"]), - ], - plugins: [ - .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") - ] - ) - ] -) diff --git a/CompileTests/MultiModule/Package@swift-5.10.swift b/CompileTests/MultiModule/Package@swift-5.10.swift deleted file mode 100644 index bd57970c7..000000000 --- a/CompileTests/MultiModule/Package@swift-5.10.swift +++ /dev/null @@ -1,40 +0,0 @@ -// swift-tools-version: 5.10 - -import PackageDescription - -let package = Package( - name: "CompileTests", - dependencies: [ - .package(name: "swift-protobuf", path: "../..") - ], - targets: [ - .testTarget( - name: "Test1", - dependencies: ["ImportsAPublicly"] - ), - .testTarget( - name: "Test2", - dependencies: ["ImportsImportsAPublicly"] - ), - .target( - name: "ModuleA", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ] - ), - .target( - name: "ImportsAPublicly", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf"), - .target(name: "ModuleA"), - ] - ), - .target( - name: "ImportsImportsAPublicly", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf"), - .target(name: "ImportsAPublicly"), - ] - ), - ] -) diff --git a/Makefile b/Makefile index e9788cd6a..80a44da89 100644 --- a/Makefile +++ b/Makefile @@ -213,14 +213,8 @@ test-plugin: build ${PROTOC_GEN_SWIFT} ${PROTOC} diff -ru _test Reference # Test the SPM plugin. -# TODO: simplify this when swift 5.10 support is dropped. test-spm-plugin: - @SWIFT_VERSION=$$(${SWIFT} --version | head -n1 | sed 's/.*Swift version \([0-9]*\)\..*/\1/'); \ - if [ "$$SWIFT_VERSION" -lt 6 ]; then \ - env PROTOC_PATH=$$(realpath ${PROTOC}) ${SWIFT} test --package-path PluginExamples; \ - else \ - ${SWIFT} test --package-path PluginExamples; \ - fi + ${SWIFT} test --package-path PluginExamples compile-tests: \ compile-tests-multimodule \ @@ -233,14 +227,8 @@ compile-tests-multimodule: # Test that ensures that using access level modifiers on imports yields code that's buildable # when `InternalImportsByDefault` is enabled on the module. -# TODO: simplify this when swift 5.10 support is dropped. compile-tests-internalimportsbydefault: - @SWIFT_VERSION=$$(${SWIFT} --version | head -n1 | sed 's/.*Swift version \([0-9]*\)\..*/\1/'); \ - if [ "$$SWIFT_VERSION" -lt 6 ]; then \ - env PROTOC_PATH=$$(realpath ${PROTOC}) ${SWIFT} build --package-path CompileTests/InternalImportsByDefault; \ - else \ - ${SWIFT} build --package-path CompileTests/InternalImportsByDefault; \ - fi + ${SWIFT} build --package-path CompileTests/InternalImportsByDefault # Rebuild the reference files by running the local version of protoc-gen-swift diff --git a/Package.swift b/Package.swift index d13064687..baf7be9ce 100644 --- a/Package.swift +++ b/Package.swift @@ -417,7 +417,7 @@ let package = Package( swiftSettings: .packageSettings ), ], - swiftLanguageModes: [.v5], + swiftLanguageModes: [.v6], cxxLanguageStandard: .gnucxx17 ) @@ -426,7 +426,6 @@ let package = Package( extension Array where Element == PackageDescription.SwiftSetting { static var packageSettings: Self { [ - .enableExperimentalFeature("StrictConcurrency=complete"), .enableUpcomingFeature("ExistentialAny"), ] } diff --git a/Package@swift-5.10.swift b/Package@swift-5.10.swift deleted file mode 100644 index c6fed849a..000000000 --- a/Package@swift-5.10.swift +++ /dev/null @@ -1,98 +0,0 @@ -// swift-tools-version:5.10 - -// Package.swift -// -// Copyright (c) 2014 - 2018 Apple Inc. and the project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See LICENSE.txt for license information: -// https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt -// - -import PackageDescription - -let package = Package( - name: "SwiftProtobuf", - products: [ - .executable( - name: "protoc-gen-swift", - targets: ["protoc-gen-swift"] - ), - .library( - name: "SwiftProtobuf", - targets: ["SwiftProtobuf"] - ), - .library( - name: "SwiftProtobufPluginLibrary", - targets: ["SwiftProtobufPluginLibrary"] - ), - .plugin( - name: "SwiftProtobufPlugin", - targets: ["SwiftProtobufPlugin"] - ), - ], - targets: [ - .target( - name: "SwiftProtobuf", - exclude: ["CMakeLists.txt"], - resources: [.copy("PrivacyInfo.xcprivacy")], - swiftSettings: .packageSettings - ), - .target( - name: "SwiftProtobufPluginLibrary", - dependencies: ["SwiftProtobuf"], - exclude: ["CMakeLists.txt"], - resources: [.copy("PrivacyInfo.xcprivacy")], - swiftSettings: .packageSettings - ), - .target( - name: "SwiftProtobufTestHelpers", - dependencies: ["SwiftProtobuf"], - swiftSettings: .packageSettings - ), - .executableTarget( - name: "protoc-gen-swift", - dependencies: ["SwiftProtobufPluginLibrary", "SwiftProtobuf"], - exclude: ["CMakeLists.txt"], - swiftSettings: .packageSettings - ), - .executableTarget( - name: "Conformance", - dependencies: ["SwiftProtobuf"], - exclude: ["failure_list_swift.txt", "text_format_failure_list_swift.txt"], - swiftSettings: .packageSettings - ), - .plugin( - name: "SwiftProtobufPlugin", - capability: .buildTool(), - dependencies: ["protoc-gen-swift"] - ), - .testTarget( - name: "SwiftProtobufTests", - dependencies: ["SwiftProtobuf"], - swiftSettings: .packageSettings - ), - .testTarget( - name: "SwiftProtobufPluginLibraryTests", - dependencies: ["SwiftProtobufPluginLibrary", "SwiftProtobufTestHelpers"], - swiftSettings: .packageSettings - ), - .testTarget( - name: "protoc-gen-swiftTests", - dependencies: ["protoc-gen-swift", "SwiftProtobufTestHelpers"], - swiftSettings: .packageSettings - ), - ], - swiftLanguageVersions: [.v5] -) - -// Settings for every Swift target in this package, like project-level settings -// in an Xcode project. -extension Array where Element == PackageDescription.SwiftSetting { - static var packageSettings: Self { - [ - .enableExperimentalFeature("StrictConcurrency=complete"), - .enableUpcomingFeature("ExistentialAny"), - ] - } -} diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 9c3f2170c..5fa6cee1e 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.10 +// swift-tools-version:6.0 // Package.swift // @@ -408,7 +408,7 @@ let package = Package( swiftSettings: .packageSettings ), ], - swiftLanguageVersions: [.v5], + swiftLanguageVersions: [.v6], cxxLanguageStandard: .gnucxx17 ) @@ -417,7 +417,6 @@ let package = Package( extension Array where Element == PackageDescription.SwiftSetting { static var packageSettings: Self { [ - .enableExperimentalFeature("StrictConcurrency=complete"), .enableUpcomingFeature("ExistentialAny"), ] } diff --git a/PluginExamples/Package@swift-5.10.swift b/PluginExamples/Package@swift-5.10.swift deleted file mode 100644 index e7bda8d98..000000000 --- a/PluginExamples/Package@swift-5.10.swift +++ /dev/null @@ -1,60 +0,0 @@ -// swift-tools-version: 5.10 - -import PackageDescription - -let package = Package( - name: "PluginExamples", - dependencies: [ - .package(path: "../") - ], - targets: [ - .target( - name: "Simple", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ], - plugins: [ - .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") - ] - ), - .target( - name: "Nested", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ], - plugins: [ - .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") - ] - ), - .target( - name: "Import", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ], - plugins: [ - .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") - ] - ), - .target( - name: "AccessLevelOnImport", - dependencies: [ - .product(name: "SwiftProtobuf", package: "swift-protobuf") - ], - swiftSettings: [ - .enableExperimentalFeature("AccessLevelOnImport") - ], - plugins: [ - .plugin(name: "SwiftProtobufPlugin", package: "swift-protobuf") - ] - ), - .testTarget( - name: "ExampleTests", - dependencies: [ - .target(name: "Simple"), - .target(name: "Nested"), - .target(name: "Import"), - .target(name: "AccessLevelOnImport"), - ] - ), - ] -) diff --git a/README.md b/README.md index 67496ac27..5132533d8 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ your project as explained below. To use Swift with Protocol buffers, you'll need: -* A Swift 5.10 or later compiler (or, if building with Xcode, Xcode 15.3 or later +* A Swift 6.0 or later compiler (or, if building with Xcode, Xcode 15.3 or later as required by the App Store). The Swift protobuf project is being developed and tested against the latest release version of Swift available from [Swift.org](https://swift.org) @@ -269,7 +269,7 @@ let binaryData: Data = try info.serializedBytes() let binaryDataAsBytes: [UInt8] = try info.serializedBytes() // Note that while the `serializedBytes()` spelling is generally preferred, -// you may also use `serializedData()` to get the bytes as an instance of +// you may also use `serializedData()` to get the bytes as an instance of // `Data` where required. // This means that the following two statements are equivalent: // let binaryData: Data = try info.serializedBytes() diff --git a/Sources/SwiftProtobufPluginLibrary/CodeGenerator.swift b/Sources/SwiftProtobufPluginLibrary/CodeGenerator.swift index bffc95bfc..e35f59c25 100644 --- a/Sources/SwiftProtobufPluginLibrary/CodeGenerator.swift +++ b/Sources/SwiftProtobufPluginLibrary/CodeGenerator.swift @@ -82,7 +82,7 @@ extension CommandLine { /// - Returns: An array of command-line arguments. fileprivate static let safeArguments: [String] = UnsafeBufferPointer(start: unsafeArgv, count: Int(argc)).compactMap { - String(validatingUTF8: $0!) + String(validatingCString: $0!) } } diff --git a/Sources/protoc-gen-swift/CommandLine+Extensions.swift b/Sources/protoc-gen-swift/CommandLine+Extensions.swift index 3c3f31fbe..7c6f5f300 100644 --- a/Sources/protoc-gen-swift/CommandLine+Extensions.swift +++ b/Sources/protoc-gen-swift/CommandLine+Extensions.swift @@ -17,7 +17,7 @@ extension CommandLine { // form. Idea from https://github.com/swiftlang/swift/issues/66213 let safeArgs: [String] = UnsafeBufferPointer(start: unsafeArgv, count: Int(argc)).compactMap { - String(validatingUTF8: $0!) + String(validatingCString: $0!) } guard let base = safeArgs.first else { From 62938c16a9dca98055c09a59e3366e09557ddd8b Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 13 Nov 2025 15:55:32 +0000 Subject: [PATCH 2/7] format --- Package.swift | 2 +- Package@swift-6.0.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index baf7be9ce..78d7285c7 100644 --- a/Package.swift +++ b/Package.swift @@ -426,7 +426,7 @@ let package = Package( extension Array where Element == PackageDescription.SwiftSetting { static var packageSettings: Self { [ - .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("ExistentialAny") ] } } diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 5fa6cee1e..5af0b16db 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -417,7 +417,7 @@ let package = Package( extension Array where Element == PackageDescription.SwiftSetting { static var packageSettings: Self { [ - .enableUpcomingFeature("ExistentialAny"), + .enableUpcomingFeature("ExistentialAny") ] } } From b845fdebf340d4b0d97780e4081b9455df1ed104 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 14 Nov 2025 08:33:27 +0000 Subject: [PATCH 3/7] inline test hook --- .github/workflows/build.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 00839737a..b97f56845 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,11 +24,8 @@ jobs: # which is also what would be desired, so we don't bother listing explicit ones. swift: - version: "6.2" - hook: "SWIFT_BUILD_TEST_HOOK=\"-Xswiftc -warnings-as-errors\"" - version: "6.1" - hook: "SWIFT_BUILD_TEST_HOOK=\"-Xswiftc -warnings-as-errors\"" - version: "6.0" - hook: "SWIFT_BUILD_TEST_HOOK=\"-Xswiftc -warnings-as-errors\"" container: image: swift:${{ matrix.swift.version }} steps: @@ -44,9 +41,9 @@ jobs: # `make` is needed for using our own `Makefile`. run: apt-get update && apt-get install -y make g++ - name: Build - run: make build ${{ matrix.swift.hook }} + run: make build -Xswiftc -warnings-as-errors - name: Test runtime - run: make test-runtime ${{ matrix.swift.hook }} + run: make test-runtime -Xswiftc -warnings-as-errors - name: Test plugin run: make test-plugin - name: Test SPM plugin From 0c062bc1f6df9bf993d5e0428ab8285fe4859f2f Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 14 Nov 2025 08:37:36 +0000 Subject: [PATCH 4/7] Language version -> language mode --- Package@swift-6.0.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index 5af0b16db..bef01ad0d 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -408,7 +408,7 @@ let package = Package( swiftSettings: .packageSettings ), ], - swiftLanguageVersions: [.v6], + swiftLanguageModes: [.v6], cxxLanguageStandard: .gnucxx17 ) From 28c7dad475dad0768b8f76d894d36130c7e50cc7 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 14 Nov 2025 08:38:08 +0000 Subject: [PATCH 5/7] Xcode version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5132533d8..4e502747d 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ your project as explained below. To use Swift with Protocol buffers, you'll need: -* A Swift 6.0 or later compiler (or, if building with Xcode, Xcode 15.3 or later +* A Swift 6.0 or later compiler (or, if building with Xcode, Xcode 16.0 or later as required by the App Store). The Swift protobuf project is being developed and tested against the latest release version of Swift available from [Swift.org](https://swift.org) From 6c74eb58e1326d6c77634ff8557cdcf9583e6ab3 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 14 Nov 2025 10:11:46 +0000 Subject: [PATCH 6/7] preconcurrency warning in plugin --- Plugins/SwiftProtobufPlugin/plugin.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/SwiftProtobufPlugin/plugin.swift b/Plugins/SwiftProtobufPlugin/plugin.swift index 74af4b966..300d0924e 100644 --- a/Plugins/SwiftProtobufPlugin/plugin.swift +++ b/Plugins/SwiftProtobufPlugin/plugin.swift @@ -6,7 +6,7 @@ struct SwiftProtobufPlugin { /// Errors thrown by the `SwiftProtobufPlugin` enum PluginError: Error, CustomStringConvertible { /// Indicates that the target where the plugin was applied to was not `SourceModuleTarget`. - case invalidTarget(Target) + case invalidTarget(String) /// Indicates that the file extension of an input file was not `.proto`. case invalidInputFileExtension(String) /// Indicates that there was no configuration file at the required location. @@ -15,7 +15,7 @@ struct SwiftProtobufPlugin { var description: String { switch self { case let .invalidTarget(target): - return "Expected a SwiftSourceModuleTarget but got '\(type(of: target))'." + return "Expected a SwiftSourceModuleTarget but got '\(target)'." case let .invalidInputFileExtension(path): return "The input file '\(path)' does not have a '.proto' extension." case let .noConfigFound(path): @@ -245,7 +245,7 @@ extension SwiftProtobufPlugin: BuildToolPlugin { target: Target ) async throws -> [Command] { guard let swiftTarget = target as? SwiftSourceModuleTarget else { - throw PluginError.invalidTarget(target) + throw PluginError.invalidTarget(String(describing: type(of: target))) } return try createBuildCommands( pluginWorkDirectory: context.pluginWorkDirectory, From 357f788e86665401ed58a8863994faa3fe587fb3 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Fri, 14 Nov 2025 10:16:44 +0000 Subject: [PATCH 7/7] test hook as env --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b97f56845..2b495487d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,9 +41,9 @@ jobs: # `make` is needed for using our own `Makefile`. run: apt-get update && apt-get install -y make g++ - name: Build - run: make build -Xswiftc -warnings-as-errors + run: make build SWIFT_BUILD_TEST_HOOK="-Xswiftc -warnings-as-errors" - name: Test runtime - run: make test-runtime -Xswiftc -warnings-as-errors + run: make test-runtime SWIFT_BUILD_TEST_HOOK="-Xswiftc -warnings-as-errors" - name: Test plugin run: make test-plugin - name: Test SPM plugin