Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,23 @@ struct Available {
var swiftSetting: SwiftSetting {
#if SYSTEM_ABI_STABLE
// Use availability matching Darwin API.
let availability = self.osAvailability
let availabilityType = self.osAvailability
#else
// Use availability matching SwiftPM default.
let availability = self.sourceAvailability
let availabilityType = self.sourceAvailability
#endif
return .enableExperimentalFeature(
"AvailabilityMacro=\(self.name) \(version):\(availability)")
"AvailabilityMacro=\(self.name) \(version):\(availabilityType)")
}

var compatibilitySetting: SwiftSetting {
.enableExperimentalFeature(
"AvailabilityMacro=\(self.name) \(version):\(osAvailability)"
)
}
}

let availability: [Available] = [
let availabilityList: [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"),
Expand All @@ -68,7 +74,7 @@ let availability: [Available] = [
Available("99", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"),
]

let swiftSettingsAvailability = availability.map(\.swiftSetting)
let availabilitySettings = availabilityList.map(\.swiftSetting)

#if SYSTEM_CI
let swiftSettingsCI: [SwiftSetting] = [
Expand All @@ -78,7 +84,7 @@ let swiftSettingsCI: [SwiftSetting] = [
let swiftSettingsCI: [SwiftSetting] = []
#endif

let swiftSettings = swiftSettingsAvailability + swiftSettingsCI + [
let sharedSwiftSettings = swiftSettingsCI + [
.define(
"SYSTEM_PACKAGE_DARWIN",
.when(platforms: [.macOS, .macCatalyst, .iOS, .watchOS, .tvOS, .visionOS])),
Expand All @@ -87,6 +93,8 @@ let swiftSettings = swiftSettingsAvailability + swiftSettingsCI + [
.enableExperimentalFeature("Lifetimes"),
]

let swiftSettings = sharedSwiftSettings + availabilitySettings

let cSettings: [CSetting] = [
.define("_CRT_SECURE_NO_WARNINGS", .when(platforms: [.windows])),
]
Expand Down Expand Up @@ -135,12 +143,29 @@ let package = Package(
exclude: filesToExclude,
cSettings: cSettings,
swiftSettings: swiftSettings),
.target(
name: "SystemCompatibilityAdaptors",
dependencies: ["SystemPackage"],
path: "Sources/SystemCompatibilityAdaptors",
exclude: [],
cSettings: cSettings,
swiftSettings:
sharedSwiftSettings + availabilityList.map(\.compatibilitySetting)
),
.testTarget(
name: "SystemTests",
dependencies: ["SystemPackage"],
exclude: testsToExclude,
cSettings: cSettings,
swiftSettings: swiftSettings),
.testTarget(
name: "SystemCompatibilityAdaptorTests",
dependencies: ["SystemCompatibilityAdaptors", "SystemPackage"],
exclude: [],
cSettings: cSettings,
swiftSettings:
sharedSwiftSettings + availabilityList.map(\.compatibilitySetting)
),
],
swiftLanguageVersions: [.v5]
)
43 changes: 43 additions & 0 deletions Sources/SystemCompatibilityAdaptors/CompatibilityAdaptors.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
This source file is part of the Swift System open source project

Copyright (c) 2025 - 2026 Apple Inc. and the Swift System project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
*/

#if canImport(System) && canImport(SystemPackage)
import System
import SystemPackage

extension SystemPackage.FilePath {
@available(System 0.0.2, *)
public init(converting path: System.FilePath) {
self = path.withPlatformString(Self.init(platformString:))
}
}

@available(System 0.0.1, *)
extension System.FilePath {
@available(System 0.0.2, *)
public init(converting path: SystemPackage.FilePath) {
self = path.withPlatformString(Self.init(platformString:))
}
}

extension SystemPackage.FileDescriptor {
@available(System 0.0.1, *)
public init(converting descriptor: System.FileDescriptor) {
self.init(rawValue: descriptor.rawValue)
}
}

@available(System 0.0.1, *)
extension System.FileDescriptor {
@available(System 0.0.1, *)
public init(converting descriptor: SystemPackage.FileDescriptor) {
self.init(rawValue: descriptor.rawValue)
}
}
#endif // canImport(System) && canImport(SystemPackage)
34 changes: 34 additions & 0 deletions Tests/SystemCompatibilityAdaptorTests/AdaptorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#if canImport(System) && canImport(SystemPackage)

import Testing

import SystemPackage
import System

import SystemCompatibilityAdaptors

@Suite("CompatibilityAdaptors")
private struct CompatibilityAdaptorTests {

@available(System 0.0.2, *)
@Test
func filePathAdaptor() throws {
let fp = SystemPackage.FilePath("/bar")

let sfp = System.FilePath(converting: fp)

// If we had access to the underlying array as API, this would look less silly
#expect(fp == SystemPackage.FilePath(converting: sfp))
}

@available(System 0.0.1, *)
@Test
func fileDescriptorAdaptor() throws {
let fd = try SystemPackage.FileDescriptor.standardInput.duplicate()

let sfd: System.FileDescriptor = System.FileDescriptor(converting: fd)

#expect(fd.rawValue == sfd.rawValue)
}
}
#endif // canImport(System) && canImport(SystemPackage)