Skip to content

Commit 5d3db35

Browse files
adding support for custom platforms (#3742)
Adding support for 'custom' platform declaration in minimum-deployment-target clause. rdar://82632420
1 parent 7e53f24 commit 5d3db35

File tree

7 files changed

+163
-3
lines changed

7 files changed

+163
-3
lines changed

Sources/PackageDescription/SupportedPlatforms.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public struct Platform: Encodable, Equatable {
1919
self.name = name
2020
}
2121

22+
@available(_PackageDescription, introduced: 5.6)
23+
public static func custom(_ platformName: String) -> Platform {
24+
return Platform(name: platformName)
25+
}
26+
2227
/// The macOS platform.
2328
public static let macOS: Platform = Platform(name: "macos")
2429

@@ -213,6 +218,16 @@ public struct SupportedPlatform: Encodable, Equatable {
213218
public static func driverKit(_ versionString: String) -> SupportedPlatform {
214219
return SupportedPlatform(platform: .driverKit, version: SupportedPlatform.DriverKitVersion(string: versionString).version)
215220
}
221+
222+
/// Configures the minimum deployment target version for custom platforms.
223+
///
224+
/// - Since: First available in PackageDescription 5.6
225+
///
226+
/// - Parameter version: The minimum deployment target that the package supports.
227+
@available(_PackageDescription, introduced: 5.6)
228+
public static func custom(_ platformName: String, versionString: String) -> SupportedPlatform {
229+
return SupportedPlatform(platform: .custom(platformName), version: versionString)
230+
}
216231
}
217232

218233
/// An extension to the SupportedPlatform struct that defines major platform versions.

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,8 @@ public final class PackageBuilder {
10181018

10191019
/// Add each declared platform to the supported platforms list.
10201020
for platform in manifest.platforms {
1021-
let declaredPlatform = platformRegistry.platformByName[platform.platformName]!
1021+
let declaredPlatform = platformRegistry.platformByName[platform.platformName]
1022+
?? PackageModel.Platform.custom(name: platform.platformName, oldestSupportedVersion: platform.version)
10221023
var version = PlatformVersion(platform.version)
10231024

10241025
if let xcTestMinimumDeploymentTarget = xcTestMinimumDeploymentTargets[declaredPlatform], isTest, version < xcTestMinimumDeploymentTarget {

Sources/PackageModel/ManifestSourceGeneration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ fileprivate extension SourceCodeFragment {
115115
case "driverkit":
116116
self.init(enum: "DriverKit", string: platform.version)
117117
default:
118-
self.init(enum: platform.platformName, string: platform.version)
118+
self.init(enum: "custom", subnodes: [ .init(string: platform.platformName), .init(key: "versionString", string: platform.version) ])
119119
}
120120
}
121121

Sources/PackageModel/Platform.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ public struct Platform: Equatable, Hashable, Codable {
2424
self.name = name
2525
self.oldestSupportedVersion = oldestSupportedVersion
2626
}
27-
27+
28+
public static func custom(name: String, oldestSupportedVersion: String) -> Platform {
29+
return Platform(name: name, oldestSupportedVersion: PlatformVersion(oldestSupportedVersion))
30+
}
31+
2832
public static let macOS: Platform = Platform(name: "macos", oldestSupportedVersion: "10.10")
2933
public static let macCatalyst: Platform = Platform(name: "maccatalyst", oldestSupportedVersion: "13.0")
3034
public static let iOS: Platform = Platform(name: "ios", oldestSupportedVersion: "9.0")

Tests/PackageLoadingTests/PD_5_6_LoadingTests.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,45 @@ class PackageDescription5_6LoadingTests: PackageDescriptionLoadingTests {
112112
XCTAssertEqual(manifest.targets[0].sources, ["CountMeIn.swift"])
113113
}
114114
}
115+
116+
func testCustomPlatforms() throws {
117+
// One custom platform.
118+
var stream = BufferedOutputByteStream()
119+
stream <<< """
120+
import PackageDescription
121+
let package = Package(
122+
name: "Foo",
123+
platforms: [
124+
.custom("customos", versionString: "1.0"),
125+
]
126+
)
127+
"""
128+
129+
loadManifest(stream.bytes) { manifest in
130+
XCTAssertEqual(manifest.platforms, [
131+
PlatformDescription(name: "customos", version: "1.0"),
132+
])
133+
}
134+
135+
// Two custom platforms.
136+
stream = BufferedOutputByteStream()
137+
stream <<< """
138+
import PackageDescription
139+
let package = Package(
140+
name: "Foo",
141+
platforms: [
142+
.custom("customos", versionString: "1.0"),
143+
.custom("anothercustomos", versionString: "2.3"),
144+
]
145+
)
146+
"""
147+
148+
loadManifest(stream.bytes) { manifest in
149+
XCTAssertEqual(manifest.platforms, [
150+
PlatformDescription(name: "customos", version: "1.0"),
151+
PlatformDescription(name: "anothercustomos", version: "2.3"),
152+
])
153+
}
154+
155+
}
115156
}

Tests/PackageLoadingTests/PackageBuilderTests.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,69 @@ class PackageBuilderTests: XCTestCase {
17631763
}
17641764
}
17651765

1766+
func testCustomPlatforms() throws {
1767+
let fs = InMemoryFileSystem(emptyFiles:
1768+
"/Sources/foo/module.modulemap"
1769+
)
1770+
1771+
// One custom platform.
1772+
var manifest = Manifest.createManifest(
1773+
name: "pkg",
1774+
platforms: [
1775+
PlatformDescription(name: "customos", version: "1.0"),
1776+
],
1777+
v: .v5_6,
1778+
targets: [
1779+
try TargetDescription(name: "foo", type: .system),
1780+
]
1781+
)
1782+
1783+
// default platforms will be auto-added during package build
1784+
var expectedPlatforms = [
1785+
"linux": "0.0",
1786+
"macos": "10.10",
1787+
"maccatalyst": "13.0",
1788+
"ios": "9.0",
1789+
"tvos": "9.0",
1790+
"driverkit": "19.0",
1791+
"watchos": "2.0",
1792+
"android": "0.0",
1793+
"windows": "0.0",
1794+
"wasi": "0.0",
1795+
"openbsd": "0.0",
1796+
]
1797+
1798+
// add our custom expectations
1799+
expectedPlatforms["customos"] = "1.0"
1800+
1801+
PackageBuilderTester(manifest, in: fs) { package, _ in
1802+
package.checkModule("foo") { t in
1803+
t.checkPlatforms(expectedPlatforms)
1804+
}
1805+
}
1806+
1807+
// Two platforms with overrides.
1808+
manifest = Manifest.createManifest(
1809+
name: "pkg",
1810+
platforms: [
1811+
PlatformDescription(name: "customos", version: "1.0"),
1812+
PlatformDescription(name: "anothercustomos", version: "2.3"),
1813+
],
1814+
v: .v5_6,
1815+
targets: [
1816+
try TargetDescription(name: "foo", type: .system),
1817+
]
1818+
)
1819+
1820+
expectedPlatforms["anothercustomos"] = "2.3"
1821+
1822+
PackageBuilderTester(manifest, in: fs) { package, _ in
1823+
package.checkModule("foo") { t in
1824+
t.checkPlatforms(expectedPlatforms)
1825+
}
1826+
}
1827+
}
1828+
17661829
func testAsmIsIgnoredInV4_2Manifest() throws {
17671830
// .s is not considered a valid source in 4.2 manifest.
17681831
let fs = InMemoryFileSystem(emptyFiles:

Tests/WorkspaceTests/ManifestSourceGenerationTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,42 @@ class ManifestSourceGenerationTests: XCTestCase {
115115
try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_3)
116116
}
117117

118+
func testCustomPlatform() throws {
119+
let manifestContents = """
120+
// swift-tools-version:5.6
121+
// The swift-tools-version declares the minimum version of Swift required to build this package.
122+
123+
import PackageDescription
124+
125+
let package = Package(
126+
name: "MyPackage",
127+
platforms: [
128+
.custom("customOS", versionString: "1.0")
129+
],
130+
products: [
131+
// Products define the executables and libraries a package produces, and make them visible to other packages.
132+
.library(
133+
name: "MyPackage",
134+
targets: ["MyPackage"]),
135+
],
136+
dependencies: [
137+
// Dependencies declare other packages that this package depends on.
138+
// .package(url: /* package url */, from: "1.0.0"),
139+
],
140+
targets: [
141+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
142+
// Targets can depend on other targets in this package, and on products in packages this package depends on.
143+
.target(
144+
name: "MyPackage",
145+
dependencies: []),
146+
.testTarget(
147+
name: "MyPackageTests",
148+
dependencies: ["MyPackage"]),
149+
]
150+
)
151+
"""
152+
try testManifestWritingRoundTrip(manifestContents: manifestContents, toolsVersion: .v5_6)
153+
}
118154

119155
func testAdvancedFeatures() throws {
120156
let manifestContents = """

0 commit comments

Comments
 (0)