Skip to content

Commit 8f7a93f

Browse files
Merge branch 'main' into automerge/merge-main-2025-08-02_00-48
2 parents 4f8a345 + 12952a3 commit 8f7a93f

File tree

176 files changed

+5772
-1586
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

176 files changed

+5772
-1586
lines changed

.github/workflows/automerge.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ jobs:
1010
name: Create PR to merge main into release branch
1111
uses: swiftlang/github-workflows/.github/workflows/create_automerge_pr.yml@main
1212
with:
13-
base_branch: release/6.2
13+
head_branch: release/6.2
14+
base_branch: main
1415
permissions:
1516
contents: write
1617
pull-requests: write

.licenseignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
**/Package.swift
66
.dir-locals.el
77
.editorconfig
8+
.swift-version
89
CODEOWNERS
910
Package.swift

.swift-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
6.1.0

Package.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ func swiftSettings(languageMode: SwiftLanguageMode) -> [SwiftSetting] {
7070
let package = Package(
7171
name: "SwiftBuild",
7272
defaultLocalization: "en",
73-
platforms: [.macOS("13.0"), .iOS("17.0"), .macCatalyst("17.0")],
73+
platforms: [
74+
.macOS(.v14),
75+
.iOS("17.0"),
76+
.macCatalyst("17.0"),
77+
],
7478
products: [
7579
.executable(name: "swbuild", targets: ["swbuild"]),
7680
.executable(name: "SWBBuildServiceBundle", targets: ["SWBBuildServiceBundle"]),
@@ -110,7 +114,7 @@ let package = Package(
110114
"SWBBuildSystem",
111115
"SWBServiceCore",
112116
"SWBTaskExecution",
113-
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .android, .windows])),
117+
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .openbsd, .android, .windows, .custom("freebsd")])),
114118
],
115119
exclude: ["CMakeLists.txt"],
116120
swiftSettings: swiftSettings(languageMode: .v5)),
@@ -201,7 +205,7 @@ let package = Package(
201205
"SWBCSupport",
202206
"SWBLibc",
203207
.product(name: "ArgumentParser", package: "swift-argument-parser"),
204-
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .android, .windows])),
208+
.product(name: "SystemPackage", package: "swift-system", condition: .when(platforms: [.linux, .openbsd, .android, .windows, .custom("freebsd")])),
205209
],
206210
exclude: ["CMakeLists.txt"],
207211
swiftSettings: swiftSettings(languageMode: .v5)),
@@ -369,7 +373,7 @@ let package = Package(
369373
// Perf tests
370374
.testTarget(
371375
name: "SWBBuildSystemPerfTests",
372-
dependencies: ["SWBBuildSystem", "SWBTestSupport"],
376+
dependencies: ["SWBBuildSystem", "SWBTestSupport", "SwiftBuildTestSupport"],
373377
swiftSettings: swiftSettings(languageMode: .v6)),
374378
.testTarget(
375379
name: "SWBCASPerfTests",
@@ -455,11 +459,11 @@ if useLocalDependencies {
455459
}
456460
} else {
457461
package.dependencies += [
458-
.package(url: "https://github.com/swiftlang/swift-driver.git", branch: "release/6.2"),
462+
.package(url: "https://github.com/swiftlang/swift-driver.git", branch: "main"),
459463
.package(url: "https://github.com/apple/swift-system.git", .upToNextMajor(from: "1.5.0")),
460464
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.3"),
461465
]
462466
if !useLLBuildFramework {
463-
package.dependencies += [.package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: "release/6.2"),]
467+
package.dependencies += [.package(url: "https://github.com/swiftlang/swift-llbuild.git", branch: "main"),]
464468
}
465469
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ When building SwiftPM from sources which include Swift Build integration, passin
1212

1313
### With Xcode
1414

15-
Changes to swift-build can also be tested in Xcode using the `launch-xcode` command plugin provided by the package. Run `swift package --disable-sandbox launch-xcode` from your checkout of swift-build to launch a copy of the currently `xcode-select`ed Xcode.app configured to use your modified copy of the build system service. This workflow is currently supported when using Xcode 16.2.
15+
Changes to swift-build can also be tested in Xcode using the `launch-xcode` command plugin provided by the package. Run `swift package --disable-sandbox launch-xcode` from your checkout of swift-build to launch a copy of the currently `xcode-select`ed Xcode.app configured to use your modified copy of the build system service. This workflow is generally only supported when using the latest available Xcode version.
1616

1717
### With xcodebuild
1818

19-
Changes to swift-build can also be tested in xcodebuild using the `run-xcodebuild` command plugin provided by the package. Run `swift package --disable-sandbox run-xcodebuild` from your checkout of swift-build to run xcodebuild from the currently `xcode-select`ed Xcode.app configured to use your modified copy of the build system service. Arguments followed by `--` will be forwarded to xcodebuild unmodified. This workflow is currently supported when using Xcode 16.2.
19+
Changes to swift-build can also be tested in xcodebuild using the `run-xcodebuild` command plugin provided by the package. Run `swift package --disable-sandbox run-xcodebuild` from your checkout of swift-build to run xcodebuild from the currently `xcode-select`ed Xcode.app configured to use your modified copy of the build system service. Arguments followed by `--` will be forwarded to xcodebuild unmodified. This workflow is generally only supported when using the latest available Xcode version.
2020

2121
### Debugging
2222

Sources/SWBAndroidPlatform/AndroidSDK.swift

Lines changed: 155 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -10,118 +10,197 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import SWBUtil
14-
import Foundation
13+
public import SWBUtil
14+
public import Foundation
1515

16-
struct AndroidSDK: Sendable {
16+
@_spi(Testing) public struct AndroidSDK: Sendable {
1717
public let host: OperatingSystem
1818
public let path: Path
19-
public let ndkVersion: Version?
19+
20+
/// List of NDKs available in this SDK installation, sorted by version number from oldest to newest.
21+
@_spi(Testing) public let ndks: [NDK]
22+
23+
public var latestNDK: NDK? {
24+
ndks.last
25+
}
2026

2127
init(host: OperatingSystem, path: Path, fs: any FSProxy) throws {
2228
self.host = host
2329
self.path = path
30+
self.ndks = try NDK.findInstallations(host: host, sdkPath: path, fs: fs)
31+
}
2432

25-
let ndkBasePath = path.join("ndk")
26-
if fs.exists(ndkBasePath) {
27-
self.ndkVersion = try fs.listdir(ndkBasePath).map { try Version($0) }.max()
28-
} else {
29-
self.ndkVersion = nil
30-
}
33+
@_spi(Testing) public struct NDK: Equatable, Sendable {
34+
public static let minimumNDKVersion = Version(23)
35+
36+
public let host: OperatingSystem
37+
public let path: Path
38+
public let version: Version
39+
public let abis: [String: ABI]
40+
public let deploymentTargetRange: DeploymentTargetRange
41+
42+
init(host: OperatingSystem, path ndkPath: Path, version: Version, fs: any FSProxy) throws {
43+
self.host = host
44+
self.path = ndkPath
45+
self.version = version
3146

32-
if let ndkVersion {
33-
let ndkPath = ndkBasePath.join(ndkVersion.description)
3447
let metaPath = ndkPath.join("meta")
3548

36-
self.abis = try JSONDecoder().decode([String: ABI].self, from: Data(fs.read(metaPath.join("abis.json"))))
49+
guard #available(macOS 14, *) else {
50+
throw StubError.error("Unsupported macOS version")
51+
}
52+
53+
if version < Self.minimumNDKVersion {
54+
throw StubError.error("Android NDK version at path '\(ndkPath.str)' is not supported (r\(Self.minimumNDKVersion.description) or later required)")
55+
}
56+
57+
self.abis = try JSONDecoder().decode(ABIs.self, from: Data(fs.read(metaPath.join("abis.json"))), configuration: version).abis
3758

3859
struct PlatformsInfo: Codable {
3960
let min: Int
4061
let max: Int
4162
}
4263

4364
let platformsInfo = try JSONDecoder().decode(PlatformsInfo.self, from: Data(fs.read(metaPath.join("platforms.json"))))
44-
self.ndkPath = ndkPath
45-
deploymentTargetRange = (platformsInfo.min, platformsInfo.max)
46-
} else {
47-
ndkPath = nil
48-
deploymentTargetRange = nil
49-
abis = nil
65+
deploymentTargetRange = DeploymentTargetRange(min: platformsInfo.min, max: platformsInfo.max)
5066
}
51-
}
5267

53-
struct ABI: Codable {
54-
enum Bitness: Int, Codable {
55-
case bits32 = 32
56-
case bits64 = 64
68+
struct ABIs: DecodableWithConfiguration {
69+
let abis: [String: ABI]
70+
71+
init(from decoder: any Decoder, configuration: Version) throws {
72+
struct DynamicCodingKey: CodingKey {
73+
var stringValue: String
74+
75+
init?(stringValue: String) {
76+
self.stringValue = stringValue
77+
}
78+
79+
let intValue: Int? = nil
80+
81+
init?(intValue: Int) {
82+
nil
83+
}
84+
}
85+
let container = try decoder.container(keyedBy: DynamicCodingKey.self)
86+
abis = try Dictionary(uniqueKeysWithValues: container.allKeys.map { try ($0.stringValue, container.decode(ABI.self, forKey: $0, configuration: configuration)) })
87+
}
5788
}
5889

59-
struct LLVMTriple: Codable {
60-
var arch: String
61-
var vendor: String
62-
var system: String
63-
var environment: String
64-
65-
var description: String {
66-
"\(arch)-\(vendor)-\(system)-\(environment)"
90+
@_spi(Testing) public struct ABI: DecodableWithConfiguration, Equatable, Sendable {
91+
@_spi(Testing) public enum Bitness: Int, Codable, Equatable, Sendable {
92+
case bits32 = 32
93+
case bits64 = 64
6794
}
6895

69-
init(from decoder: any Decoder) throws {
70-
let container = try decoder.singleValueContainer()
71-
let triple = try container.decode(String.self)
72-
if let match = try #/(?<arch>.+)-(?<vendor>.+)-(?<system>.+)-(?<environment>.+)/#.wholeMatch(in: triple) {
73-
self.arch = String(match.output.arch)
74-
self.vendor = String(match.output.vendor)
75-
self.system = String(match.output.system)
76-
self.environment = String(match.output.environment)
77-
} else {
78-
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid triple string: \(triple)")
96+
@_spi(Testing) public struct LLVMTriple: Codable, Equatable, Sendable {
97+
public var arch: String
98+
public var vendor: String
99+
public var system: String
100+
public var environment: String
101+
102+
var description: String {
103+
"\(arch)-\(vendor)-\(system)-\(environment)"
104+
}
105+
106+
public init(from decoder: any Decoder) throws {
107+
let container = try decoder.singleValueContainer()
108+
let triple = try container.decode(String.self)
109+
if let match = try #/(?<arch>.+)-(?<vendor>.+)-(?<system>.+)-(?<environment>.+)/#.wholeMatch(in: triple) {
110+
self.arch = String(match.output.arch)
111+
self.vendor = String(match.output.vendor)
112+
self.system = String(match.output.system)
113+
self.environment = String(match.output.environment)
114+
} else {
115+
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid triple string: \(triple)")
116+
}
79117
}
80118
}
81119

82-
func encode(to encoder: any Encoder) throws {
83-
var container = encoder.singleValueContainer()
84-
try container.encode(description)
120+
public let bitness: Bitness
121+
public let `default`: Bool
122+
public let deprecated: Bool
123+
public let proc: String
124+
public let arch: String
125+
public let triple: String
126+
public let llvm_triple: LLVMTriple
127+
public let min_os_version: Int
128+
129+
enum CodingKeys: String, CodingKey {
130+
case bitness
131+
case `default` = "default"
132+
case deprecated
133+
case proc
134+
case arch
135+
case triple
136+
case llvm_triple = "llvm_triple"
137+
case min_os_version = "min_os_version"
138+
}
139+
140+
public init(from decoder: any Decoder, configuration ndkVersion: Version) throws {
141+
let container = try decoder.container(keyedBy: CodingKeys.self)
142+
self.bitness = try container.decode(Bitness.self, forKey: .bitness)
143+
self.default = try container.decode(Bool.self, forKey: .default)
144+
self.deprecated = try container.decode(Bool.self, forKey: .deprecated)
145+
self.proc = try container.decode(String.self, forKey: .proc)
146+
self.arch = try container.decode(String.self, forKey: .arch)
147+
self.triple = try container.decode(String.self, forKey: .triple)
148+
self.llvm_triple = try container.decode(LLVMTriple.self, forKey: .llvm_triple)
149+
self.min_os_version = try container.decodeIfPresent(Int.self, forKey: .min_os_version) ?? {
150+
if ndkVersion < Version(27) {
151+
return 21 // min_os_version wasn't present prior to NDKr27, fill it in with 21, which is the appropriate value
152+
} else {
153+
throw DecodingError.valueNotFound(Int.self, .init(codingPath: container.codingPath, debugDescription: "No value associated with key \(CodingKeys.min_os_version) (\"\(CodingKeys.min_os_version.rawValue)\")."))
154+
}
155+
}()
85156
}
86157
}
87158

88-
let bitness: Bitness
89-
let `default`: Bool
90-
let deprecated: Bool
91-
let proc: String
92-
let arch: String
93-
let triple: String
94-
let llvm_triple: LLVMTriple
95-
let min_os_version: Int
96-
}
159+
@_spi(Testing) public struct DeploymentTargetRange: Equatable, Sendable {
160+
public let min: Int
161+
public let max: Int
162+
}
97163

98-
public let abis: [String: ABI]?
164+
public var toolchainPath: Path {
165+
path.join("toolchains").join("llvm").join("prebuilt").join(hostTag)
166+
}
99167

100-
public let deploymentTargetRange: (min: Int, max: Int)?
168+
public var sysroot: Path {
169+
toolchainPath.join("sysroot")
170+
}
101171

102-
public let ndkPath: Path?
172+
private var hostTag: String? {
173+
switch host {
174+
case .windows:
175+
// Also works on Windows on ARM via Prism binary translation.
176+
"windows-x86_64"
177+
case .macOS:
178+
// Despite the x86_64 tag in the Darwin name, these are universal binaries including arm64.
179+
"darwin-x86_64"
180+
case .linux:
181+
// Also works on non-x86 archs via binfmt support and qemu (or Rosetta on Apple-hosted VMs).
182+
"linux-x86_64"
183+
default:
184+
nil // unsupported host
185+
}
186+
}
103187

104-
public var toolchainPath: Path? {
105-
ndkPath?.join("toolchains").join("llvm").join("prebuilt").join(hostTag)
106-
}
188+
public static func findInstallations(host: OperatingSystem, sdkPath: Path, fs: any FSProxy) throws -> [NDK] {
189+
let ndkBasePath = sdkPath.join("ndk")
190+
guard fs.exists(ndkBasePath) else {
191+
return []
192+
}
107193

108-
public var sysroot: Path? {
109-
toolchainPath?.join("sysroot")
110-
}
194+
let ndks = try fs.listdir(ndkBasePath).map({ try Version($0) }).sorted()
195+
let supportedNdks = ndks.filter { $0 >= minimumNDKVersion }
111196

112-
private var hostTag: String? {
113-
switch host {
114-
case .windows:
115-
// Also works on Windows on ARM via Prism binary translation.
116-
"windows-x86_64"
117-
case .macOS:
118-
// Despite the x86_64 tag in the Darwin name, these are universal binaries including arm64.
119-
"darwin-x86_64"
120-
case .linux:
121-
// Also works on non-x86 archs via binfmt support and qemu (or Rosetta on Apple-hosted VMs).
122-
"linux-x86_64"
123-
default:
124-
nil // unsupported host
197+
// If we have some NDKs but all of them are unsupported, try parsing them so that parsing fails and provides a more useful error. Otherwise, simply filter out and ignore the unsupported versions.
198+
let discoveredNdks = supportedNdks.isEmpty && !ndks.isEmpty ? ndks : supportedNdks
199+
200+
return try discoveredNdks.map { ndkVersion in
201+
let ndkPath = ndkBasePath.join(ndkVersion.description)
202+
return try NDK(host: host, path: ndkPath, version: ndkVersion, fs: fs)
203+
}
125204
}
126205
}
127206

0 commit comments

Comments
 (0)