From 9a1530813e138699aca84b0408e4adf2cfa78ed8 Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Sat, 7 Jun 2025 10:49:36 -0700 Subject: [PATCH 1/3] Replace bespoke availability system Removes the script based availability system with the experimental availability macro feature. --- .github/workflows/pull_request.yml | 23 +++- Package.swift | 83 ++++++++++++- Sources/System/Errno.swift | 12 +- Sources/System/FileDescriptor.swift | 18 +-- Sources/System/FileHelpers.swift | 2 +- Sources/System/FileOperations.swift | 20 +-- Sources/System/FilePath/FilePath.swift | 8 +- .../FilePath/FilePathComponentView.swift | 16 +-- .../System/FilePath/FilePathComponents.swift | 28 ++--- Sources/System/FilePath/FilePathParsing.swift | 16 +-- Sources/System/FilePath/FilePathString.swift | 34 ++--- Sources/System/FilePath/FilePathSyntax.swift | 16 +-- Sources/System/FilePermissions.swift | 4 +- Sources/System/Internals/CInterop.swift | 4 +- Sources/System/MachPort.swift | 32 ++--- Sources/System/PlatformString.swift | 6 +- Sources/System/Util.swift | 8 +- Tests/SystemTests/ErrnoTest.swift | 2 +- Tests/SystemTests/FileOperationsTest.swift | 2 +- .../FilePathComponentsTest.swift | 4 +- .../FilePathTests/FilePathDecodable.swift | 2 +- .../FilePathTests/FilePathExtras.swift | 4 +- .../FilePathTests/FilePathParsingTest.swift | 2 +- .../FilePathTests/FilePathSyntaxTest.swift | 6 +- .../FilePathTests/FilePathTest.swift | 4 +- Tests/SystemTests/FileTypesTest.swift | 4 +- Tests/SystemTests/MachPortTests.swift | 2 +- Tests/SystemTests/MockingTest.swift | 2 +- Utilities/expand-availability.py | 117 ------------------ 29 files changed, 230 insertions(+), 251 deletions(-) delete mode 100755 Utilities/expand-availability.py diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index ec43b5b5..d4949eb1 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -10,8 +10,27 @@ jobs: uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main with: linux_os_versions: '["jammy", "focal"]' - enable_macos_checks: false - macos_xcode_versions: '["16.3"]' + enable_macos_checks: true + swift_flags: "-Xbuild-tools-swiftc -DSYSTEM_CI" + + build-abi-stable: + name: Build ABI Stable + uses: swiftlang/github-workflows/.github/workflows/swift_package_test.yml@main + with: + enable_linux_checks: false + enable_macos_checks: true + enable_windows_checks: false + # Only build + macos_build_command: "xcrun swift build --build-tests" + # Only test against latest Xcode + macos_exclude_xcode_versions: | + [ + {"xcode_version": "16.0"}, + {"xcode_version": "16.1"}, + {"xcode_version": "16.2"}, + ] + # Enable availability to match ABI stable verion of system. + swift_flags: "-Xbuild-tools-swiftc -DSYSTEM_CI -Xbuild-tools-swiftc -DSYSTEM_ABI_STABLE" soundness: name: Soundness diff --git a/Package.swift b/Package.swift index 9cbfc6e9..74a70160 100644 --- a/Package.swift +++ b/Package.swift @@ -12,11 +12,70 @@ import PackageDescription -let cSettings: [CSetting] = [ - .define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])), +struct Available { + var name: String + var version: String + var osAvailability: String + var sourceAvailability: String + + init( + _ version: String, + _ osAvailability: String + ) { + self.name = "System" + self.version = version + self.osAvailability = osAvailability + self.sourceAvailability = "macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0" + } + + var swiftSetting: SwiftSetting { + #if SYSTEM_ABI_STABLE + // Use availability matching Darwin API. + let availability = self.osAvailability + #else + // Use availability matching SwiftPM default. + let availability = self.sourceAvailability + #endif + return .enableExperimentalFeature( + "AvailabilityMacro=\(self.name) \(version):\(availability)") + } +} + +let availability: [Available] = [ + Available("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"), + + Available("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"), + + Available("0.0.3", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), + Available("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), + + Available("1.1.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + Available("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + + Available("1.2.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + Available("1.3.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + + Available("1.3.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), + Available("1.3.2", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), + Available("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), + + Available("1.4.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), + Available("1.4.2", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), + Available("1.5.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), + Available("1.6.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), +] + +let swiftSettingsAvailability = availability.map(\.swiftSetting) + +#if SYSTEM_CI +let swiftSettingsCI: [SwiftSetting] = [ + .unsafeFlags(["-require-explicit-availability=error"]), ] +#else +let swiftSettingsCI: [SwiftSetting] = [] +#endif -let swiftSettings: [SwiftSetting] = [ +let swiftSettings = swiftSettingsAvailability + swiftSettingsCI + [ .define( "SYSTEM_PACKAGE_DARWIN", .when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])), @@ -25,6 +84,22 @@ let swiftSettings: [SwiftSetting] = [ .enableExperimentalFeature("Lifetimes"), ] +let cSettings: [CSetting] = [ + .define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])), +] + +#if SYSTEM_ABI_STABLE +let platforms: [SupportedPlatform] = [ + .macOS("26"), + .iOS("26"), + .watchOS("26"), + .tvOS("26"), + .visionOS("26"), +] +#else +let platforms: [SupportedPlatform]? = nil +#endif + #if os(Linux) let filesToExclude = ["CMakeLists.txt"] #else @@ -39,6 +114,7 @@ let testsToExclude = ["IORequestTests.swift", "IORingTests.swift"] let package = Package( name: "swift-system", + platforms: platforms, products: [ .library(name: "SystemPackage", targets: ["SystemPackage"]), ], @@ -63,3 +139,4 @@ let package = Package( cSettings: cSettings, swiftSettings: swiftSettings), ]) + diff --git a/Sources/System/Errno.swift b/Sources/System/Errno.swift index e88b96d9..43b46af5 100644 --- a/Sources/System/Errno.swift +++ b/Sources/System/Errno.swift @@ -10,7 +10,7 @@ /// An error number used by system calls to communicate what kind of error /// occurred. @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct Errno: RawRepresentable, Error, Hashable, Codable { /// The raw C error number. @_alwaysEmitIntoClient @@ -1391,7 +1391,7 @@ public struct Errno: RawRepresentable, Error, Hashable, Codable { } // Constants defined in header but not man page -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { /// Operation would block. /// @@ -1520,7 +1520,7 @@ extension Errno { #endif } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { // TODO: We want to provide safe access to `errno`, but we need a // release-barrier to do so. @@ -1535,14 +1535,14 @@ extension Errno { } // Use "hidden" entry points for `NSError` bridging -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { public var _code: Int { Int(rawValue) } public var _domain: String { "NSPOSIXErrorDomain" } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the most recent error /// returned by a system call. @@ -1562,7 +1562,7 @@ extension Errno: CustomStringConvertible, CustomDebugStringConvertible { public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension Errno { @_alwaysEmitIntoClient public static func ~=(_ lhs: Errno, _ rhs: Error) -> Bool { diff --git a/Sources/System/FileDescriptor.swift b/Sources/System/FileDescriptor.swift index c9953e8b..d5f5883b 100644 --- a/Sources/System/FileDescriptor.swift +++ b/Sources/System/FileDescriptor.swift @@ -14,7 +14,7 @@ /// of `FileDescriptor` values, /// in the same way as you manage a raw C file handle. @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FileDescriptor: RawRepresentable, Hashable, Codable { /// The raw C file handle. @_alwaysEmitIntoClient @@ -26,7 +26,7 @@ public struct FileDescriptor: RawRepresentable, Hashable, Codable { } // Standard file descriptors. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// The standard input file descriptor, with a numeric value of 0. @_alwaysEmitIntoClient @@ -41,11 +41,11 @@ extension FileDescriptor { public static var standardError: FileDescriptor { .init(rawValue: 2) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// The desired read and write access for a newly opened file. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct AccessMode: RawRepresentable, Sendable, Hashable, Codable { /// The raw C access mode. @_alwaysEmitIntoClient @@ -88,7 +88,7 @@ extension FileDescriptor { /// Options that specify behavior for a newly-opened file. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct OpenOptions: OptionSet, Sendable, Hashable, Codable { /// The raw C options. @_alwaysEmitIntoClient @@ -326,7 +326,7 @@ extension FileDescriptor { /// Options for specifying what a file descriptor's offset is relative to. @frozen - @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + @available(System 0.0.1, *) public struct SeekOrigin: RawRepresentable, Sendable, Hashable, Codable { /// The raw C value. @_alwaysEmitIntoClient @@ -402,7 +402,7 @@ extension FileDescriptor { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.AccessMode : CustomStringConvertible, CustomDebugStringConvertible { @@ -421,7 +421,7 @@ extension FileDescriptor.AccessMode public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.SeekOrigin : CustomStringConvertible, CustomDebugStringConvertible { @@ -444,7 +444,7 @@ extension FileDescriptor.SeekOrigin public var debugDescription: String { self.description } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor.OpenOptions : CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Sources/System/FileHelpers.swift b/Sources/System/FileHelpers.swift index 2ddb0729..5b082766 100644 --- a/Sources/System/FileHelpers.swift +++ b/Sources/System/FileHelpers.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// Runs a closure and then closes the file descriptor, even if an error occurs. /// diff --git a/Sources/System/FileOperations.swift b/Sources/System/FileOperations.swift index 2a8509bd..9ddc16c3 100644 --- a/Sources/System/FileOperations.swift +++ b/Sources/System/FileOperations.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FileDescriptor { /// Opens or creates a file for reading or writing. /// @@ -368,7 +368,7 @@ extension FileDescriptor { } #if !os(WASI) -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FileDescriptor { /// Duplicates this file descriptor and return the newly created copy. /// @@ -398,7 +398,7 @@ extension FileDescriptor { /// /// The corresponding C functions are `dup` and `dup2`. @_alwaysEmitIntoClient - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public func duplicate( as target: FileDescriptor? = nil, retryOnInterrupt: Bool = true @@ -406,7 +406,7 @@ extension FileDescriptor { try _duplicate(as: target, retryOnInterrupt: retryOnInterrupt).get() } - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) @usableFromInline internal func _duplicate( as target: FileDescriptor?, @@ -435,7 +435,7 @@ extension FileDescriptor { #endif #if !os(WASI) -@available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) +@available(System 1.1.0, *) extension FileDescriptor { /// Creates a unidirectional data channel, which can be used for interprocess communication. /// @@ -443,12 +443,12 @@ extension FileDescriptor { /// /// The corresponding C function is `pipe`. @_alwaysEmitIntoClient - @available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) + @available(System 1.1.0, *) public static func pipe() throws -> (readEnd: FileDescriptor, writeEnd: FileDescriptor) { try _pipe().get() } - @available(/*System 1.1.0: macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4*/iOS 8, *) + @available(System 1.1.0, *) @usableFromInline internal static func _pipe() -> Result<(readEnd: FileDescriptor, writeEnd: FileDescriptor), Errno> { var fds: (Int32, Int32) = (-1, -1) @@ -463,7 +463,7 @@ extension FileDescriptor { } #endif -@available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.2.0, *) extension FileDescriptor { /// Truncates or extends the file referenced by this file descriptor. /// @@ -485,7 +485,7 @@ extension FileDescriptor { /// associated with the file. /// /// The corresponding C function is `ftruncate`. - @available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.2.0, *) @_alwaysEmitIntoClient public func resize( to newSize: Int64, @@ -497,7 +497,7 @@ extension FileDescriptor { ).get() } - @available(/*System 1.2.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.2.0, *) @usableFromInline internal func _resize( to newSize: Int64, diff --git a/Sources/System/FilePath/FilePath.swift b/Sources/System/FilePath/FilePath.swift index f056759d..b27d053a 100644 --- a/Sources/System/FilePath/FilePath.swift +++ b/Sources/System/FilePath/FilePath.swift @@ -37,7 +37,7 @@ /// However, the rules for path equivalence /// are file-system–specific and have additional considerations /// like case insensitivity, Unicode normalization, and symbolic links. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FilePath: Sendable { // TODO(docs): Section on all the new syntactic operations, lexical normalization, decomposition, // components, etc. @@ -59,16 +59,16 @@ public struct FilePath: Sendable { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { /// The length of the file path, excluding the null terminator. public var length: Int { _storage.length } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: Hashable {} -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: Codable { // Encoder is synthesized; it probably should have been explicit and used // a single-value container, but making that change now is somewhat risky. diff --git a/Sources/System/FilePath/FilePathComponentView.swift b/Sources/System/FilePath/FilePathComponentView.swift index 39381b4b..be176305 100644 --- a/Sources/System/FilePath/FilePathComponentView.swift +++ b/Sources/System/FilePath/FilePathComponentView.swift @@ -9,7 +9,7 @@ // MARK: - API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// A bidirectional, range replaceable collection of the non-root components /// that make up a file path. @@ -28,7 +28,7 @@ extension FilePath { /// /// path.components.removeAll { $0.kind == .currentDirectory } /// // path is "/home/username/bin/scripts/tree" - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct ComponentView: Sendable { internal var _path: FilePath internal var _start: SystemString.Index @@ -64,11 +64,11 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: BidirectionalCollection { public typealias Element = FilePath.Component - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Index: Sendable, Comparable, Hashable { internal typealias Storage = SystemString.Index @@ -100,7 +100,7 @@ extension FilePath.ComponentView: BidirectionalCollection { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: RangeReplaceableCollection { public init() { self.init(FilePath()) @@ -150,7 +150,7 @@ extension FilePath.ComponentView: RangeReplaceableCollection { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Create a file path from a root and a collection of components. public init( @@ -179,7 +179,7 @@ extension FilePath { // MARK: - Internals -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView: _PathSlice { internal var _range: Range { _start ..< _path._storage.endIndex @@ -192,7 +192,7 @@ extension FilePath.ComponentView: _PathSlice { // MARK: - Invariants -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView { internal func _invariantCheck() { #if DEBUG diff --git a/Sources/System/FilePath/FilePathComponents.swift b/Sources/System/FilePath/FilePathComponents.swift index b304a0a7..f2352617 100644 --- a/Sources/System/FilePath/FilePathComponents.swift +++ b/Sources/System/FilePath/FilePathComponents.swift @@ -9,7 +9,7 @@ // MARK: - API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Represents a root of a file path. /// @@ -28,7 +28,7 @@ extension FilePath { /// * `\\server\share\` /// * `\\?\UNC\server\share\` /// * `\\?\Volume{12345678-abcd-1111-2222-123445789abc}\` - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Root: Sendable { internal var _path: FilePath internal var _rootEnd: SystemString.Index @@ -55,7 +55,7 @@ extension FilePath { /// file.kind == .regular // true /// file.extension // "txt" /// path.append(file) // path is "/tmp/foo.txt" - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public struct Component: Sendable { internal var _path: FilePath internal var _range: Range @@ -74,13 +74,13 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Whether a component is a regular file or directory name, or a special /// directory `.` or `..` @frozen - @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + @available(System 0.0.2, *) public enum Kind: Sendable { /// The special directory `.`, representing the current directory. case currentDirectory @@ -100,7 +100,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { // TODO: Windows analysis APIs } @@ -186,17 +186,17 @@ extension _PathSlice { internal var _storage: SystemString { _path._storage } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: _PathSlice { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: _PathSlice { internal var _range: Range { (..<_rootEnd).relative(to: _path._storage) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: _PlatformStringable { func _withPlatformString(_ body: (UnsafePointer) throws -> Result) rethrows -> Result { try _storage.withPlatformString(body) @@ -208,7 +208,7 @@ extension FilePath: _PlatformStringable { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { // The index of the `.` denoting an extension internal func _extensionIndex() -> SystemString.Index? { @@ -237,7 +237,7 @@ internal func _makeExtension(_ ext: String) -> SystemString { return result } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { internal init?(_ str: SystemString) { // FIXME: explicit null root? Or something else? @@ -250,7 +250,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { internal init?(_ str: SystemString) { // FIXME: explicit null root? Or something else? @@ -265,7 +265,7 @@ extension FilePath.Root { // MARK: - Invariants -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { // TODO: ensure this all gets easily optimized away in release... internal func _invariantCheck() { @@ -278,7 +278,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { internal func _invariantCheck() { #if DEBUG diff --git a/Sources/System/FilePath/FilePathParsing.swift b/Sources/System/FilePath/FilePathParsing.swift index c31e6a5b..f372dd67 100644 --- a/Sources/System/FilePath/FilePathParsing.swift +++ b/Sources/System/FilePath/FilePathParsing.swift @@ -116,7 +116,7 @@ extension SystemString { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal mutating func _removeTrailingSeparator() { _storage._removeTrailingSeparator() @@ -197,7 +197,7 @@ extension SystemString { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal var _relativeStart: SystemString.Index { _storage._relativePathStart @@ -209,7 +209,7 @@ extension FilePath { // Parse separators -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal typealias _Index = SystemString.Index @@ -273,7 +273,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.ComponentView { // TODO: Store this... internal var _relativeStart: SystemString.Index { @@ -298,7 +298,7 @@ extension SystemString { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { // Asserting self is a root, returns whether this is an // absolute root. @@ -323,7 +323,7 @@ extension FilePath.Root { } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal var _portableDescription: String { guard _windowsPaths else { return description } @@ -345,7 +345,7 @@ internal var _windowsPaths: Bool { #endif } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { // Whether we should add a separator when doing an append internal var _needsSeparatorForAppend: Bool { @@ -373,7 +373,7 @@ extension FilePath { } // MARK: - Invariants -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { internal func _invariantsSatisfied() -> Bool { var normal = self diff --git a/Sources/System/FilePath/FilePathString.swift b/Sources/System/FilePath/FilePathString.swift index 4fe9c1fd..45f79c8a 100644 --- a/Sources/System/FilePath/FilePathString.swift +++ b/Sources/System/FilePath/FilePathString.swift @@ -9,7 +9,7 @@ // MARK: - Platform string -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Creates a file path by copying bytes from a null-terminated platform /// string. @@ -109,7 +109,7 @@ extension FilePath { #endif } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Creates a file path component by copying bytes from a null-terminated /// platform string. @@ -198,7 +198,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { /// Creates a file path root by copying bytes from a null-terminated platform /// string. @@ -287,7 +287,7 @@ extension FilePath.Root { // MARK: - String literals -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: ExpressibleByStringLiteral { /// Creates a file path from a string literal. /// @@ -306,7 +306,7 @@ extension FilePath: ExpressibleByStringLiteral { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: ExpressibleByStringLiteral { /// Create a file path component from a string literal. /// @@ -331,7 +331,7 @@ extension FilePath.Component: ExpressibleByStringLiteral { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: ExpressibleByStringLiteral { /// Create a file path root from a string literal. /// @@ -356,7 +356,7 @@ extension FilePath.Root: ExpressibleByStringLiteral { // MARK: - Printing and dumping -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the file path. /// @@ -372,7 +372,7 @@ extension FilePath: CustomStringConvertible, CustomDebugStringConvertible { public var debugDescription: String { description.debugDescription } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the path component. @@ -389,7 +389,7 @@ extension FilePath.Component: CustomStringConvertible, CustomDebugStringConverti public var debugDescription: String { description.debugDescription } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root: CustomStringConvertible, CustomDebugStringConvertible { /// A textual representation of the path root. @@ -409,7 +409,7 @@ extension FilePath.Root: CustomStringConvertible, CustomDebugStringConvertible { // MARK: - Convenience helpers // Convenience helpers -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Creates a string by interpreting the path’s content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -420,7 +420,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// Creates a string by interpreting the component’s content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -431,7 +431,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Root { /// On Unix, this returns `"/"`. /// @@ -445,7 +445,7 @@ extension FilePath.Root { // MARK: - Decoding and validating -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension String { /// Creates a string by interpreting the file path's content as UTF-8 on Unix /// and UTF-16 on Windows. @@ -475,7 +475,7 @@ extension String { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// Creates a string by interpreting the path component's content as UTF-8 on /// Unix and UTF-16 on Windows. @@ -505,7 +505,7 @@ extension String { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// On Unix, creates the string `"/"` /// @@ -558,7 +558,7 @@ extension String { // MARK: - Deprecations -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension String { @available(*, deprecated, renamed: "init(decoding:)") public init(_ path: FilePath) { self.init(decoding: path) } @@ -568,7 +568,7 @@ extension String { } #if !os(Windows) -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePath { /// For backwards compatibility only. This initializer is equivalent to /// the preferred `FilePath(platformString:)`. diff --git a/Sources/System/FilePath/FilePathSyntax.swift b/Sources/System/FilePath/FilePathSyntax.swift index 1c3fc097..eb1f25df 100644 --- a/Sources/System/FilePath/FilePathSyntax.swift +++ b/Sources/System/FilePath/FilePathSyntax.swift @@ -9,7 +9,7 @@ // MARK: - Query API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns true if this path uniquely identifies the location of /// a file without reference to an additional starting location. @@ -99,7 +99,7 @@ extension FilePath { } // MARK: - Decompose a path -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns the root of a path if there is one, otherwise `nil`. /// @@ -182,7 +182,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns the final component of the path. /// Returns `nil` if the path is empty or only contains a root. @@ -252,7 +252,7 @@ extension FilePath { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath.Component { /// The extension of this file or directory component. /// @@ -283,7 +283,7 @@ extension FilePath.Component { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// The extension of the file or directory last component. @@ -349,7 +349,7 @@ extension FilePath { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Whether the path is in lexical-normal form, that is `.` and `..` /// components have been collapsed lexically (i.e. without following @@ -430,7 +430,7 @@ extension FilePath { } // Modification and concatenation API -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { // TODO(Windows docs): example with roots /// If `prefix` is a prefix of `self`, removes it and returns `true`. @@ -583,7 +583,7 @@ extension FilePath { } // MARK - Renamed -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { @available(*, unavailable, renamed: "removingLastComponent()") public var dirname: FilePath { removingLastComponent() } diff --git a/Sources/System/FilePermissions.swift b/Sources/System/FilePermissions.swift index 918246ef..f849a997 100644 --- a/Sources/System/FilePermissions.swift +++ b/Sources/System/FilePermissions.swift @@ -17,7 +17,7 @@ /// let perms = FilePermissions(rawValue: 0o644) /// perms == [.ownerReadWrite, .groupRead, .otherRead] // true @frozen -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public struct FilePermissions: OptionSet, Sendable, Hashable, Codable { /// The raw C file permissions. @_alwaysEmitIntoClient @@ -132,7 +132,7 @@ public struct FilePermissions: OptionSet, Sendable, Hashable, Codable { public static var saveText: FilePermissions { .init(rawValue: 0o1000) } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) extension FilePermissions : CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Sources/System/Internals/CInterop.swift b/Sources/System/Internals/CInterop.swift index 80d37d05..b6de1233 100644 --- a/Sources/System/Internals/CInterop.swift +++ b/Sources/System/Internals/CInterop.swift @@ -37,12 +37,12 @@ import Bionic public typealias CModeT = CInt #else /// The C `mode_t` type. -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) public typealias CModeT = mode_t #endif /// A namespace for C and platform types -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) public enum CInterop { #if os(Windows) public typealias Mode = CInt diff --git a/Sources/System/MachPort.swift b/Sources/System/MachPort.swift index 8cc05096..313f6c28 100644 --- a/Sources/System/MachPort.swift +++ b/Sources/System/MachPort.swift @@ -11,10 +11,10 @@ import Darwin.Mach -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) public protocol MachPortRight {} -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) @inlinable internal func _machPrecondition( file: StaticString = #file, @@ -26,10 +26,10 @@ internal func _machPrecondition( precondition(kr == expected, file: file, line: line) } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) @frozen public enum Mach { - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public struct Port: ~Copyable { @usableFromInline internal var _name: mach_port_name_t @@ -133,7 +133,7 @@ public enum Mach { public struct SendOnceRight: MachPortRight {} } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.ReceiveRight { /// Transfer ownership of an existing, unmanaged, but already guarded, /// Mach port right into a Mach.Port by name. @@ -158,7 +158,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This initializer will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public init() { var storage: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL) _machPrecondition( @@ -181,7 +181,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// After this function completes, the Mach.Port is destroyed and no longer /// usable. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func relinquish( ) -> (name: mach_port_name_t, context: mach_port_context_t) { let destructured = (name: _name, context: _context) @@ -204,7 +204,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// Mach.ReceiveRights. Use relinquish() to avoid the syscall and extract /// the context value along with the port name. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func unguardAndRelinquish() -> mach_port_name_t { let (name, context) = self.relinquish() _machPrecondition(mach_port_unguard(mach_task_self_, name, context)) @@ -221,7 +221,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// The body block may optionally return something, which will then be /// returned to the caller of withBorrowedName. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func withBorrowedName( body: (mach_port_name_t, mach_port_context_t) -> ReturnType ) -> ReturnType { @@ -235,7 +235,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This function will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func makeSendOnceRight() -> Mach.Port { // send once rights do not coalesce var newRight: mach_port_name_t = mach_port_name_t(MACH_PORT_NULL) @@ -264,7 +264,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// This function will abort if the right could not be created. /// Callers may assert that a valid right is always returned. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func makeSendRight() -> Mach.Port { let how = MACH_MSG_TYPE_MAKE_SEND @@ -282,7 +282,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { /// /// Each get/set of this property makes a syscall. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public var makeSendCount: mach_port_mscount_t { get { var status: mach_port_status = mach_port_status() @@ -311,7 +311,7 @@ extension Mach.Port where RightType == Mach.ReceiveRight { } } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.SendRight { /// Transfer ownership of the underlying port right to the caller. /// @@ -337,7 +337,7 @@ extension Mach.Port where RightType == Mach.SendRight { /// receiving side has been deallocated, then copySendRight() will throw /// a Mach.PortRightError.deadName error. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public func copySendRight() throws -> Mach.Port { let how = MACH_MSG_TYPE_COPY_SEND @@ -354,7 +354,7 @@ extension Mach.Port where RightType == Mach.SendRight { } } -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) extension Mach.Port where RightType == Mach.SendOnceRight { /// Transfer ownership of the underlying port right to the caller. /// @@ -366,7 +366,7 @@ extension Mach.Port where RightType == Mach.SendOnceRight { /// After this function completes, the Mach.Port is destroyed and no longer /// usable. @inlinable - @available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) + @available(System 1.4.0, *) public consuming func relinquish() -> mach_port_name_t { let name = _name discard self diff --git a/Sources/System/PlatformString.swift b/Sources/System/PlatformString.swift index 664a6089..7b8fd90c 100644 --- a/Sources/System/PlatformString.swift +++ b/Sources/System/PlatformString.swift @@ -7,7 +7,7 @@ See https://swift.org/LICENSE.txt for license information */ -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension String { /// Creates a string by interpreting the null-terminated platform string as /// UTF-8 on Unix and UTF-16 on Windows. @@ -165,7 +165,7 @@ extension String { } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension CInterop.PlatformChar { internal var _platformCodeUnit: CInterop.PlatformUnicodeEncoding.CodeUnit { #if os(Windows) @@ -176,7 +176,7 @@ extension CInterop.PlatformChar { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension CInterop.PlatformUnicodeEncoding.CodeUnit { internal var _platformChar: CInterop.PlatformChar { #if os(Windows) diff --git a/Sources/System/Util.swift b/Sources/System/Util.swift index 3a8df9ac..e4832ac5 100644 --- a/Sources/System/Util.swift +++ b/Sources/System/Util.swift @@ -8,21 +8,21 @@ */ // Results in errno if i == -1 -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) private func valueOrErrno( _ i: I ) -> Result { i == -1 ? .failure(Errno.current) : .success(i) } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) private func nothingOrErrno( _ i: I ) -> Result<(), Errno> { valueOrErrno(i).map { _ in () } } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) internal func valueOrErrno( retryOnInterrupt: Bool, _ f: () -> I ) -> Result { @@ -36,7 +36,7 @@ internal func valueOrErrno( } while true } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) internal func nothingOrErrno( retryOnInterrupt: Bool, _ f: () -> I ) -> Result<(), Errno> { diff --git a/Tests/SystemTests/ErrnoTest.swift b/Tests/SystemTests/ErrnoTest.swift index 5f4551ba..767190ee 100644 --- a/Tests/SystemTests/ErrnoTest.swift +++ b/Tests/SystemTests/ErrnoTest.swift @@ -19,7 +19,7 @@ import System import WinSDK #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class ErrnoTest: XCTestCase { func testConstants() { XCTAssert(EPERM == Errno.notPermitted.rawValue) diff --git a/Tests/SystemTests/FileOperationsTest.swift b/Tests/SystemTests/FileOperationsTest.swift index 479e503f..e4609bb3 100644 --- a/Tests/SystemTests/FileOperationsTest.swift +++ b/Tests/SystemTests/FileOperationsTest.swift @@ -20,7 +20,7 @@ import Android import CSystem #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FileOperationsTest: XCTestCase { #if !os(WASI) // Would need to use _getConst funcs from CSystem func testSyscalls() { diff --git a/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift b/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift index e816bb5a..d72d59a2 100644 --- a/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathComponentsTest.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) struct TestPathComponents: TestCase { var path: FilePath var expectedRoot: FilePath.Root? @@ -100,7 +100,7 @@ struct TestPathComponents: TestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathComponentsTest: XCTestCase { func testAdHocRRC() { var path: FilePath = "/usr/local/bin" diff --git a/Tests/SystemTests/FilePathTests/FilePathDecodable.swift b/Tests/SystemTests/FilePathTests/FilePathDecodable.swift index 290bef2f..b88b0299 100644 --- a/Tests/SystemTests/FilePathTests/FilePathDecodable.swift +++ b/Tests/SystemTests/FilePathTests/FilePathDecodable.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FilePathDecodableTest: XCTestCase { func testInvalidFilePath() { // _storage is a valid SystemString, but the invariants of FilePath are diff --git a/Tests/SystemTests/FilePathTests/FilePathExtras.swift b/Tests/SystemTests/FilePathTests/FilePathExtras.swift index 82f11373..ff4b1b37 100644 --- a/Tests/SystemTests/FilePathTests/FilePathExtras.swift +++ b/Tests/SystemTests/FilePathTests/FilePathExtras.swift @@ -6,7 +6,7 @@ #endif // Why can't I write this extension on `FilePath.ComponentView.SubSequence`? -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension Slice where Base == FilePath.ComponentView { internal var _storageSlice: SystemString.SubSequence { base._path._storage[self.startIndex._storage ..< self.endIndex._storage] @@ -15,7 +15,7 @@ extension Slice where Base == FilePath.ComponentView { // Proposed API that didn't make the cut, but we stil want to keep our testing for -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension FilePath { /// Returns `self` relative to `base`. /// This does not cosult the file system or resolve symlinks. diff --git a/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift b/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift index 766bdf8d..66e9105e 100644 --- a/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathParsingTest.swift @@ -68,7 +68,7 @@ extension ParsingTestCase { @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathParsingTest: XCTestCase { func testNormalization() { let unixPaths: Array = [ diff --git a/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift b/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift index d23999a2..4e182556 100644 --- a/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathSyntaxTest.swift @@ -146,7 +146,7 @@ extension SyntaxTestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension SyntaxTestCase { func testComponents(_ path: FilePath, expected: [String]) { let expectedComponents = expected.map { FilePath.Component($0)! } @@ -342,7 +342,7 @@ private struct WindowsRootTestCase: TestCase { var line: UInt } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) extension WindowsRootTestCase { func runAllTests() { withWindowsPaths(enabled: true) { @@ -357,7 +357,7 @@ extension WindowsRootTestCase { } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathSyntaxTest: XCTestCase { func testPathSyntax() { let unixPaths: Array = [ diff --git a/Tests/SystemTests/FilePathTests/FilePathTest.swift b/Tests/SystemTests/FilePathTests/FilePathTest.swift index b50cc17e..ef71c850 100644 --- a/Tests/SystemTests/FilePathTests/FilePathTest.swift +++ b/Tests/SystemTests/FilePathTests/FilePathTest.swift @@ -15,7 +15,7 @@ import SystemPackage import System #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) func filePathFromInvalidCodePointSequence(_ bytes: S) -> FilePath where S.Element == CInterop.PlatformUnicodeEncoding.CodeUnit { var array = Array(bytes) assert(array.last != 0, "already null terminated") @@ -28,7 +28,7 @@ func filePathFromInvalidCodePointSequence(_ bytes: S) -> FilePath w } } -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class FilePathTest: XCTestCase { struct TestPath { let filePath: FilePath diff --git a/Tests/SystemTests/FileTypesTest.swift b/Tests/SystemTests/FileTypesTest.swift index a818dfba..0ddcb0de 100644 --- a/Tests/SystemTests/FileTypesTest.swift +++ b/Tests/SystemTests/FileTypesTest.swift @@ -18,7 +18,7 @@ import System import Android #endif -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FileDescriptorTest: XCTestCase { func testStandardDescriptors() { XCTAssertEqual(FileDescriptor.standardInput.rawValue, 0) @@ -76,7 +76,7 @@ final class FileDescriptorTest: XCTestCase { } -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) +@available(System 0.0.1, *) final class FilePermissionsTest: XCTestCase { func testPermissions() { diff --git a/Tests/SystemTests/MachPortTests.swift b/Tests/SystemTests/MachPortTests.swift index 073da9a5..fde04d8c 100644 --- a/Tests/SystemTests/MachPortTests.swift +++ b/Tests/SystemTests/MachPortTests.swift @@ -18,7 +18,7 @@ import SystemPackage import System #endif -@available(/*System 1.4.0: macOS 9999, iOS 9999, watchOS 9999, tvOS 9999*/iOS 8, *) +@available(System 1.4.0, *) final class MachPortTests: XCTestCase { func refCountForMachPortName(name:mach_port_name_t, kind:mach_port_right_t) -> mach_port_urefs_t { var refCount:mach_port_urefs_t = .max diff --git a/Tests/SystemTests/MockingTest.swift b/Tests/SystemTests/MockingTest.swift index 1f2c96da..38985c6b 100644 --- a/Tests/SystemTests/MockingTest.swift +++ b/Tests/SystemTests/MockingTest.swift @@ -15,7 +15,7 @@ import XCTest @testable import System #endif -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) +@available(System 0.0.2, *) final class MockingTest: XCTestCase { func testMocking() { XCTAssertFalse(mockingEnabled) diff --git a/Utilities/expand-availability.py b/Utilities/expand-availability.py deleted file mode 100755 index 4cb1a1be..00000000 --- a/Utilities/expand-availability.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -# This script can be used to automatically add/remove `@available` attributes to -# declarations in Swift sources in this package. -# -# In order for this to work, ABI-impacting declarations need to be annotated -# with special comments in the following format: -# -# @available(/*System 0.0.2*/iOS 8, *) -# public func greeting() -> String { -# "Hello" -# } -# -# (The iOS 8 availability is a dummy no-op declaration -- it only has to be -# there because `@available(*)` isn't valid syntax, and commenting out the -# entire `@available` attribute would interfere with parser tools for doc -# comments. `iOS 8` is the shortest version string that matches the minimum -# possible deployment target for Swift code, so we use that as our dummy -# availability version. `@available(iOS 8, *)` is functionally equivalent to not -# having an `@available` attribute at all.) -# -# The script adds full availability incantations to these comments. It can run -# in one of two modes: -# -# By default, `expand-availability.py` expands availability macros within the -# comments. This is useful during package development to cross-reference -# availability across `SystemPackage` and the ABI-stable `System` module that -# ships in Apple's OS releases: -# -# @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -# public func greeting() -> String { -# "Hello" -# } -# -# `expand-availability.py --attributes` adds actual availability declarations. -# This is used by maintainers to build ABI stable releases of System on Apple's -# platforms: -# -# @available(/*System 0.0.2: */macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -# public func greeting() -> String { -# "Hello" -# } -# -# The script recognizes all three forms of these annotations and updates them on -# every run, so we can run the script to enable/disable attributes as needed. - -import os -import os.path -import fileinput -import re -import sys -import argparse - -versions = { - "System 0.0.1": "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0", - "System 0.0.2": "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0", - "System 1.1.0": "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4", - "System 1.2.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", - "System 1.3.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", - "System 1.4.0": "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999", -} - -parser = argparse.ArgumentParser(description="Expand availability macros.") -parser.add_argument("--attributes", help="Add @available attributes", - action="store_true") -args = parser.parse_args() - -def swift_sources_in(path): - result = [] - for (dir, _, files) in os.walk(path): - for file in files: - extension = os.path.splitext(file)[1] - if extension == ".swift": - result.append(os.path.join(dir, file)) - return result - -# Old-style syntax: -# /*System 0.0.2*/ -# /*System 0.0.2, @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)*/ -# /*System 0.0.2*/@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -old_macro_pattern = re.compile( - r"/\*(System [^ *]+)(, @available\([^)]*\))?\*/(@available\([^)]*\))?") - -# New-style comments: -# @available(/*SwiftSystem 0.0.2*/macOS 10, *) -# @available(/*SwiftSystem 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -# @available(/*SwiftSystem 0.0.2*/macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) -# -# These do not interfere with our tools' ability to find doc comments. -macro_pattern = re.compile( - r"@available\(/\*(System [^ *:]+)[^*/)]*\*/([^)]*)\*\)") - -def available_attribute(filename, lineno, symbolic_version): - expansion = versions[symbolic_version] - if expansion is None: - raise ValueError("{0}:{1}: error: Unknown System version '{0}'" - .format(fileinput.filename(), fileinput.lineno(), symbolic_version)) - if args.attributes: - attribute = "@available(/*{0}*/{1}, *)".format(symbolic_version, expansion) - else: - # Sadly `@available(*)` is not valid syntax, so we have to mention at - # least one actual platform here. - attribute = "@available(/*{0}: {1}*/iOS 8, *)".format(symbolic_version, expansion) - return attribute - - -sources = swift_sources_in("Sources") + swift_sources_in("Tests") -for line in fileinput.input(files=sources, inplace=True): - match = re.search(macro_pattern, line) - if match is None: - match = re.search(old_macro_pattern, line) - if match: - symbolic_version = match.group(1) - replacement = available_attribute( - fileinput.filename(), fileinput.lineno(), symbolic_version) - line = line[:match.start()] + replacement + line[match.end():] - print(line, end="") From e5198c2b2d062741dc6653b993ce31566049364d Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Wed, 30 Jul 2025 08:50:14 -0700 Subject: [PATCH 2/3] disable 16.0 and 16.1 --- .github/workflows/pull_request.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d4949eb1..35d50227 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -11,6 +11,13 @@ jobs: with: linux_os_versions: '["jammy", "focal"]' enable_macos_checks: true + # FIXME: https://github.com/swiftlang/github-workflows/pull/140 + # Xcode 16.0 and 16.1 are not actually available + macos_exclude_xcode_versions: | + [ + {"xcode_version": "16.0"}, + {"xcode_version": "16.1"}, + ] swift_flags: "-Xbuild-tools-swiftc -DSYSTEM_CI" build-abi-stable: @@ -22,12 +29,12 @@ jobs: enable_windows_checks: false # Only build macos_build_command: "xcrun swift build --build-tests" - # Only test against latest Xcode + # FIXME: https://github.com/swiftlang/github-workflows/pull/140 + # Xcode 16.0 and 16.1 are not actually available macos_exclude_xcode_versions: | [ {"xcode_version": "16.0"}, {"xcode_version": "16.1"}, - {"xcode_version": "16.2"}, ] # Enable availability to match ABI stable verion of system. swift_flags: "-Xbuild-tools-swiftc -DSYSTEM_CI -Xbuild-tools-swiftc -DSYSTEM_ABI_STABLE" From f97a80426c77504e51cffc6189d2f23e0965c83e Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Wed, 30 Jul 2025 08:53:33 -0700 Subject: [PATCH 3/3] update readme --- Package.swift | 1 + README.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 74a70160..35059250 100644 --- a/Package.swift +++ b/Package.swift @@ -63,6 +63,7 @@ let availability: [Available] = [ Available("1.4.2", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), Available("1.5.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), Available("1.6.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), + Available("1.6.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), ] let swiftSettingsAvailability = availability.map(\.swiftSetting) diff --git a/README.md b/README.md index 0089f681..0b75fd04 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ To use the `SystemPackage` library in a SwiftPM project, add the following line to the dependencies in your `Package.swift` file: ```swift -.package(url: "https://github.com/apple/swift-system", from: "1.6.0"), +.package(url: "https://github.com/apple/swift-system", from: "1.6.1"), ``` Finally, include `"SystemPackage"` as a dependency for your executable target: @@ -41,7 +41,7 @@ Finally, include `"SystemPackage"` as a dependency for your executable target: let package = Package( // name, platforms, products, etc. dependencies: [ - .package(url: "https://github.com/apple/swift-system", from: "1.6.0"), + .package(url: "https://github.com/apple/swift-system", from: "1.6.1"), // other dependencies ], targets: [