Skip to content

Commit 280cc27

Browse files
committed
Handle the OS version in the triple for FreeBSD
We're going to keep the versioned triple, so it needs to be passed through after all.
1 parent 94ed881 commit 280cc27

File tree

6 files changed

+127
-74
lines changed

6 files changed

+127
-74
lines changed

Sources/SWBAndroidPlatform/AndroidSDK.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -93,30 +93,6 @@ public import Foundation
9393
case bits64 = 64
9494
}
9595

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-
}
117-
}
118-
}
119-
12096
public let bitness: Bitness
12197
public let `default`: Bool
12298
public let deprecated: Bool

Sources/SWBGenericUnixPlatform/Plugin.swift

Lines changed: 76 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,44 @@ import SWBCore
1515
import Foundation
1616

1717
@PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) {
18+
let plugin = GenericUnixPlugin()
1819
manager.register(GenericUnixDeveloperDirectoryExtension(), type: DeveloperDirectoryExtensionPoint.self)
1920
manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
2021
manager.register(GenericUnixPlatformInfoExtension(), type: PlatformInfoExtensionPoint.self)
21-
manager.register(GenericUnixSDKRegistryExtension(), type: SDKRegistryExtensionPoint.self)
22-
manager.register(GenericUnixToolchainRegistryExtension(), type: ToolchainRegistryExtensionPoint.self)
22+
manager.register(GenericUnixSDKRegistryExtension(plugin: plugin), type: SDKRegistryExtensionPoint.self)
23+
manager.register(GenericUnixToolchainRegistryExtension(plugin: plugin), type: ToolchainRegistryExtensionPoint.self)
24+
}
25+
26+
final class GenericUnixPlugin: Sendable {
27+
func swiftExecutablePath(fs: any FSProxy) -> Path? {
28+
[
29+
Environment.current["SWIFT_EXEC"].map(Path.init),
30+
StackedSearchPath(environment: .current, fs: fs).lookup(Path("swift"))
31+
].compactMap { $0 }.first(where: fs.exists)
32+
}
33+
34+
func swiftTargetInfo(swiftExecutablePath: Path) async throws -> SwiftTargetInfo {
35+
let args = ["-print-target-info"]
36+
let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: swiftExecutablePath.str), arguments: args)
37+
guard executionResult.exitStatus.isSuccess else {
38+
throw RunProcessNonZeroExitError(args: [swiftExecutablePath.str] + args, workingDirectory: nil, environment: [:], status: executionResult.exitStatus, stdout: ByteString(executionResult.stdout), stderr: ByteString(executionResult.stderr))
39+
}
40+
return try JSONDecoder().decode(SwiftTargetInfo.self, from: executionResult.stdout)
41+
}
42+
}
43+
44+
struct SwiftTargetInfo: Decodable {
45+
struct TargetInfo: Decodable {
46+
let triple: LLVMTriple
47+
let unversionedTriple: LLVMTriple
48+
}
49+
let target: TargetInfo
50+
}
51+
52+
extension SwiftTargetInfo.TargetInfo {
53+
var tripleVersion: String? {
54+
triple != unversionedTriple && triple.system.hasPrefix(unversionedTriple.system) ? String(triple.system.dropFirst(unversionedTriple.system.count)).nilIfEmpty : nil
55+
}
2356
}
2457

2558
struct GenericUnixDeveloperDirectoryExtension: DeveloperDirectoryExtension {
@@ -69,9 +102,11 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
69102
}
70103

71104
struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
105+
let plugin: GenericUnixPlugin
106+
72107
func additionalSDKs(context: any SDKRegistryExtensionAdditionalSDKsContext) async throws -> [(path: Path, platform: SWBCore.Platform?, data: [String: PropertyListItem])] {
73108
let operatingSystem = context.hostOperatingSystem
74-
guard operatingSystem.createFallbackSystemToolchain, let platform = try context.platformRegistry.lookup(name: operatingSystem.xcodePlatformName) else {
109+
guard operatingSystem.createFallbackSystemToolchain, let platform = try context.platformRegistry.lookup(name: operatingSystem.xcodePlatformName), let swift = plugin.swiftExecutablePath(fs: context.fs) else {
75110
return []
76111
}
77112

@@ -100,6 +135,8 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
100135
tripleEnvironment = ""
101136
}
102137

138+
let swiftTargetInfo = try await plugin.swiftTargetInfo(swiftExecutablePath: swift)
139+
103140
return try [(.root, platform, [
104141
"Type": .plString("SDK"),
105142
"Version": .plString(Version(ProcessInfo.processInfo.operatingSystemVersion).zeroTrimmed.description),
@@ -112,7 +149,7 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
112149
operatingSystem.xcodePlatformName: .plDict([
113150
"Archs": .plArray([.plString(Architecture.hostStringValue ?? "unknown")]),
114151
"LLVMTargetTripleEnvironment": .plString(tripleEnvironment),
115-
"LLVMTargetTripleSys": .plString(operatingSystem.xcodePlatformName),
152+
"LLVMTargetTripleSys": .plString(operatingSystem.xcodePlatformName + (swiftTargetInfo.target.tripleVersion ?? "")),
116153
"LLVMTargetTripleVendor": .plString("unknown"),
117154
])
118155
]),
@@ -121,55 +158,47 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
121158
}
122159

123160
struct GenericUnixToolchainRegistryExtension: ToolchainRegistryExtension {
161+
let plugin: GenericUnixPlugin
162+
124163
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
125164
let operatingSystem = context.hostOperatingSystem
126-
guard operatingSystem.createFallbackSystemToolchain else {
165+
let fs = context.fs
166+
guard operatingSystem.createFallbackSystemToolchain, let swift = plugin.swiftExecutablePath(fs: fs) else {
127167
return []
128168
}
129169

130-
let fs = context.fs
131-
132-
for swift in [
133-
Environment.current["SWIFT_EXEC"].map(Path.init),
134-
StackedSearchPath(environment: .current, fs: fs).lookup(Path("swift"))
135-
].compactMap(\.self) {
136-
if fs.exists(swift) {
137-
let realSwiftPath = try fs.realpath(swift).dirname.normalize()
138-
let hasUsrBin = realSwiftPath.str.hasSuffix("/usr/bin")
139-
let hasUsrLocalBin = realSwiftPath.str.hasSuffix("/usr/local/bin")
140-
let path: Path
141-
switch (hasUsrBin, hasUsrLocalBin) {
142-
case (true, false):
143-
path = realSwiftPath.dirname.dirname
144-
case (false, true):
145-
path = realSwiftPath.dirname.dirname.dirname
146-
case (false, false):
147-
throw StubError.error("Unexpected toolchain layout for Swift installation path: \(realSwiftPath)")
148-
case (true, true):
149-
preconditionFailure()
150-
}
151-
let llvmDirectories = try Array(fs.listdir(Path("/usr/lib")).filter { $0.hasPrefix("llvm-") }.sorted().reversed())
152-
let llvmDirectoriesLocal = try Array(fs.listdir(Path("/usr/local")).filter { $0.hasPrefix("llvm") }.sorted().reversed())
153-
return [
154-
Toolchain(
155-
identifier: ToolchainRegistry.defaultToolchainIdentifier,
156-
displayName: "Default",
157-
version: Version(),
158-
aliases: ["default"],
159-
path: path,
160-
frameworkPaths: [],
161-
libraryPaths: llvmDirectories.map { "/usr/lib/\($0)/lib" } + llvmDirectoriesLocal.map { "/usr/local/\($0)/lib" } + ["/usr/lib64"],
162-
defaultSettings: [:],
163-
overrideSettings: [:],
164-
defaultSettingsWhenPrimary: [:],
165-
executableSearchPaths: realSwiftPath.dirname.relativeSubpath(from: path).map { [path.join($0).join("bin")] } ?? [],
166-
testingLibraryPlatformNames: [],
167-
fs: fs)
168-
]
169-
}
170+
let realSwiftPath = try fs.realpath(swift).dirname.normalize()
171+
let hasUsrBin = realSwiftPath.str.hasSuffix("/usr/bin")
172+
let hasUsrLocalBin = realSwiftPath.str.hasSuffix("/usr/local/bin")
173+
let path: Path
174+
switch (hasUsrBin, hasUsrLocalBin) {
175+
case (true, false):
176+
path = realSwiftPath.dirname.dirname
177+
case (false, true):
178+
path = realSwiftPath.dirname.dirname.dirname
179+
case (false, false):
180+
throw StubError.error("Unexpected toolchain layout for Swift installation path: \(realSwiftPath)")
181+
case (true, true):
182+
preconditionFailure()
170183
}
171-
172-
return []
184+
let llvmDirectories = try Array(fs.listdir(Path("/usr/lib")).filter { $0.hasPrefix("llvm-") }.sorted().reversed())
185+
let llvmDirectoriesLocal = try Array(fs.listdir(Path("/usr/local")).filter { $0.hasPrefix("llvm") }.sorted().reversed())
186+
return [
187+
Toolchain(
188+
identifier: ToolchainRegistry.defaultToolchainIdentifier,
189+
displayName: "Default",
190+
version: Version(),
191+
aliases: ["default"],
192+
path: path,
193+
frameworkPaths: [],
194+
libraryPaths: llvmDirectories.map { "/usr/lib/\($0)/lib" } + llvmDirectoriesLocal.map { "/usr/local/\($0)/lib" } + ["/usr/lib64"],
195+
defaultSettings: [:],
196+
overrideSettings: [:],
197+
defaultSettingsWhenPrimary: [:],
198+
executableSearchPaths: realSwiftPath.dirname.relativeSubpath(from: path).map { [path.join($0).join("bin")] } ?? [],
199+
testingLibraryPlatformNames: [],
200+
fs: fs)
201+
]
173202
}
174203
}
175204

Sources/SWBTestSupport/CoreTestSupport.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ extension Core {
5656
developerPath = .xcode(xcodeDeveloperDirPath)
5757
} else {
5858
// In the context of auto-generated package schemes, try to infer the active Xcode.
59-
let potentialDeveloperPath = getEnvironmentVariable("PATH")?.components(separatedBy: String(Path.pathEnvironmentSeparator)).first.map(Path.init)?.dirname.dirname
59+
let potentialDeveloperPath = getEnvironmentVariable(.path)?.components(separatedBy: String(Path.pathEnvironmentSeparator)).first.map(Path.init)?.dirname.dirname
6060
let versionInfo = potentialDeveloperPath?.dirname.join("version.plist")
6161
if let versionInfo = versionInfo, (try? PropertyList.fromPath(versionInfo, fs: localFS))?.dictValue?["ProjectName"] == "IDEApplication" {
6262
developerPath = potentialDeveloperPath.map { .xcode($0) }

Sources/SWBUtil/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ add_library(SWBUtil
5555
LazyCache.swift
5656
Library.swift
5757
LineReader.swift
58+
LLVMTriple.swift
5859
Lock.swift
5960
MachO.swift
6061
Math.swift

Sources/SWBUtil/LLVMTriple.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
public struct LLVMTriple: Decodable, Equatable, Sendable, CustomStringConvertible {
14+
public var arch: String
15+
public var vendor: String
16+
public var system: String
17+
public var environment: String
18+
19+
public var description: String {
20+
"\(arch)-\(vendor)-\(system)-\(environment)"
21+
}
22+
23+
public init(_ string: String) throws {
24+
guard let match = try #/(?<arch>.+)-(?<vendor>.+)-(?<system>.+)-(?<environment>.+)/#.wholeMatch(in: string) else {
25+
throw LLVMTripleError.invalidTripleStringFormat(string)
26+
}
27+
self.arch = String(match.output.arch)
28+
self.vendor = String(match.output.vendor)
29+
self.system = String(match.output.system)
30+
self.environment = String(match.output.environment)
31+
}
32+
33+
public init(from decoder: any Swift.Decoder) throws {
34+
self = try Self(decoder.singleValueContainer().decode(String.self))
35+
}
36+
}
37+
38+
enum LLVMTripleError: Error, CustomStringConvertible {
39+
case invalidTripleStringFormat(String)
40+
41+
var description: String {
42+
switch self {
43+
case let .invalidTripleStringFormat(tripleString):
44+
"Invalid triple string format: \(tripleString)"
45+
}
46+
}
47+
}

Sources/SWBWindowsPlatform/VSInstallation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ public struct VSInstallation: Decodable, Sendable {
5757
]
5858
let executionResult = try await Process.getOutput(url: URL(fileURLWithPath: vswhere.str), arguments: args)
5959
guard executionResult.exitStatus.isSuccess else {
60-
throw RunProcessNonZeroExitError(args: args, workingDirectory: nil, environment: [:], status: executionResult.exitStatus, stdout: ByteString(executionResult.stdout), stderr: ByteString(executionResult.stderr))
60+
throw RunProcessNonZeroExitError(args: [vswhere.str] + args, workingDirectory: nil, environment: [:], status: executionResult.exitStatus, stdout: ByteString(executionResult.stdout), stderr: ByteString(executionResult.stderr))
6161
}
6262
return try JSONDecoder().decode([VSInstallation].self, from: executionResult.stdout)
6363
}
6464

6565
private static func vswherePath(fs: any FSProxy) throws -> Path? {
6666
var paths: [Path] = []
67-
if let path = try POSIX.getenv("PATH") {
67+
if let path = getEnvironmentVariable(.path) {
6868
paths.append(contentsOf: path.split(separator: Path.pathEnvironmentSeparator).map(Path.init).filter {
6969
// PATH may contain unexpanded shell variable references
7070
$0.isAbsolute

0 commit comments

Comments
 (0)