Skip to content

Commit aaa84a0

Browse files
committed
Move Linux business logic into the Generic Unix Plugin
This moves the "fallback system toolchain" logic for Linux (and future Unix-likes such as FreeBSD, OpenBSD, etc.) into the Generic Unix Plugin so that this platform-specific business logic isn't in the core of Swift Build.
1 parent fec0d2b commit aaa84a0

File tree

12 files changed

+181
-150
lines changed

12 files changed

+181
-150
lines changed

Sources/SWBAndroidPlatform/Plugin.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ struct AndroidSDKRegistryExtension: SDKRegistryExtension {
156156
struct AndroidToolchainRegistryExtension: ToolchainRegistryExtension {
157157
let plugin: AndroidPlugin
158158

159-
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async -> [Toolchain] {
159+
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
160160
guard let toolchainPath = try? await plugin.cachedAndroidSDKInstallations(host: context.hostOperatingSystem).first?.toolchainPath else {
161161
return []
162162
}

Sources/SWBCore/Core.swift

+1-8
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public final class Core: Sendable {
229229
self.toolchainPaths = {
230230
var toolchainPaths = [(Path, strict: Bool)]()
231231

232-
toolchainPaths.append((Path(developerPath).join("Toolchains"), strict: !hostOperatingSystem.createFallbackSystemToolchain))
232+
toolchainPaths.append((Path(developerPath).join("Toolchains"), strict: developerPath.hasSuffix(".app/Contents/Developer")))
233233

234234
// FIXME: We should support building the toolchain locally (for `inferiorProductsPath`).
235235

@@ -681,10 +681,3 @@ struct CoreRegistryDelegate : PlatformRegistryDelegate, SDKRegistryDelegate, Spe
681681
core.developerPath
682682
}
683683
}
684-
685-
extension OperatingSystem {
686-
/// Whether the Core is allowed to create a fallback toolchain, SDK, and platform for this operating system in cases where no others have been provided.
687-
@_spi(Testing) public var createFallbackSystemToolchain: Bool {
688-
return self == .linux
689-
}
690-
}

Sources/SWBCore/Extensions/ToolchainRegistryExtension.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ public struct ToolchainRegistryExtensionPoint: ExtensionPoint, Sendable {
2222
}
2323

2424
public protocol ToolchainRegistryExtension: Sendable {
25-
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async -> [Toolchain]
25+
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain]
2626
}
2727

2828
extension ToolchainRegistryExtension {
29-
public func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async -> [Toolchain] {
29+
public func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
3030
[]
3131
}
3232
}
3333

3434
public protocol ToolchainRegistryExtensionAdditionalToolchainsContext: Sendable {
3535
var hostOperatingSystem: OperatingSystem { get }
36+
var toolchainRegistry: ToolchainRegistry { get }
3637
var fs: any FSProxy { get }
3738
}

Sources/SWBCore/PlatformRegistry.swift

+1-25
Original file line numberDiff line numberDiff line change
@@ -331,16 +331,8 @@ public final class PlatformRegistry {
331331
await registerPlatformsInDirectory(path, fs)
332332
}
333333

334-
do {
335-
if hostOperatingSystem.createFallbackSystemToolchain {
336-
try await registerFallbackSystemPlatform(operatingSystem: hostOperatingSystem, fs: fs)
337-
}
338-
} catch {
339-
delegate.error(error)
340-
}
341-
342334
@preconcurrency @PluginExtensionSystemActor func platformInfoExtensions() async -> [any PlatformInfoExtensionPoint.ExtensionProtocol] {
343-
return await delegate.pluginManager.extensions(of: PlatformInfoExtensionPoint.self)
335+
return delegate.pluginManager.extensions(of: PlatformInfoExtensionPoint.self)
344336
}
345337

346338
struct Context: PlatformInfoExtensionAdditionalPlatformsContext {
@@ -361,22 +353,6 @@ public final class PlatformRegistry {
361353
}
362354
}
363355

364-
private func registerFallbackSystemPlatform(operatingSystem: OperatingSystem, fs: any FSProxy) async throws {
365-
try await registerPlatform(Path("/"), .plDict(fallbackSystemPlatformSettings(operatingSystem: operatingSystem)), fs)
366-
}
367-
368-
private func fallbackSystemPlatformSettings(operatingSystem: OperatingSystem) throws -> [String: PropertyListItem] {
369-
try [
370-
"Type": .plString("Platform"),
371-
"Name": .plString(operatingSystem.xcodePlatformName),
372-
"Identifier": .plString(operatingSystem.xcodePlatformName),
373-
"Description": .plString(operatingSystem.xcodePlatformName),
374-
"FamilyName": .plString(operatingSystem.xcodePlatformName.capitalized),
375-
"FamilyIdentifier": .plString(operatingSystem.xcodePlatformName),
376-
"IsDeploymentPlatform": .plString("YES"),
377-
]
378-
}
379-
380356
private func loadDeploymentTargetMacroNames() {
381357
// We must have loaded the extended platform info before doing this,
382358
// since deploymentTargetMacro is set on the Platform objects through there.

Sources/SWBCore/SDKRegistry.swift

-57
Original file line numberDiff line numberDiff line change
@@ -606,63 +606,6 @@ public final class SDKRegistry: SDKRegistryLookup, CustomStringConvertible, Send
606606
for (path, platform) in searchPaths {
607607
registerSDKsInDirectory(path, platform)
608608
}
609-
610-
do {
611-
if hostOperatingSystem.createFallbackSystemToolchain {
612-
try registerFallbackSystemSDK(operatingSystem: hostOperatingSystem, platform: searchPaths.compactMap { $0.1 ?? nil }.only)
613-
}
614-
} catch {
615-
delegate.error(error)
616-
}
617-
}
618-
619-
private func registerFallbackSystemSDK(operatingSystem: OperatingSystem, platform: Platform?) throws {
620-
try registerSDK(Path("/"), Path("/"), platform, .plDict(fallbackSystemSDKSettings(operatingSystem: operatingSystem)))
621-
}
622-
623-
private func fallbackSystemSDKSettings(operatingSystem: OperatingSystem) throws -> [String: PropertyListItem] {
624-
let defaultProperties: [String: PropertyListItem]
625-
switch operatingSystem {
626-
case .linux:
627-
defaultProperties = [
628-
// Workaround to avoid `-dependency_info` on Linux.
629-
"LD_DEPENDENCY_INFO_FILE": .plString(""),
630-
631-
"GENERATE_TEXT_BASED_STUBS": "NO",
632-
"GENERATE_INTERMEDIATE_TEXT_BASED_STUBS": "NO",
633-
634-
"CHOWN": "/usr/bin/chown",
635-
"AR": "llvm-ar",
636-
]
637-
default:
638-
defaultProperties = [:]
639-
}
640-
641-
let tripleEnvironment: String
642-
switch operatingSystem {
643-
case .linux:
644-
tripleEnvironment = "gnu"
645-
default:
646-
tripleEnvironment = ""
647-
}
648-
649-
return try [
650-
"Type": .plString("SDK"),
651-
"Version": .plString(Version(ProcessInfo.processInfo.operatingSystemVersion).zeroTrimmed.description),
652-
"CanonicalName": .plString(operatingSystem.xcodePlatformName),
653-
"IsBaseSDK": .plBool(true),
654-
"DefaultProperties": .plDict([
655-
"PLATFORM_NAME": .plString(operatingSystem.xcodePlatformName),
656-
].merging(defaultProperties, uniquingKeysWith: { _, new in new })),
657-
"SupportedTargets": .plDict([
658-
operatingSystem.xcodePlatformName: .plDict([
659-
"Archs": .plArray([.plString(Architecture.hostStringValue ?? "unknown")]),
660-
"LLVMTargetTripleEnvironment": .plString(tripleEnvironment),
661-
"LLVMTargetTripleSys": .plString(operatingSystem.xcodePlatformName),
662-
"LLVMTargetTripleVendor": .plString("unknown"),
663-
])
664-
]),
665-
]
666609
}
667610

668611
/// Register all the SDKs in the given directory.

Sources/SWBCore/Settings/Settings.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -5282,7 +5282,7 @@ extension Settings {
52825282
}
52835283

52845284
extension OperatingSystem {
5285-
@_spi(Testing) public var xcodePlatformName: String {
5285+
public var xcodePlatformName: String {
52865286
get throws {
52875287
switch self {
52885288
case .macOS:

Sources/SWBCore/ToolchainRegistry.swift

+5-37
Original file line numberDiff line numberDiff line change
@@ -443,55 +443,23 @@ public final class ToolchainRegistry: @unchecked Sendable {
443443
}
444444
}
445445

446-
do {
447-
if hostOperatingSystem.createFallbackSystemToolchain {
448-
try registerFallbackSystemToolchain(operatingSystem: hostOperatingSystem)
449-
}
450-
} catch {
451-
delegate.error(error)
452-
}
453-
454446
struct Context: ToolchainRegistryExtensionAdditionalToolchainsContext {
455447
var hostOperatingSystem: OperatingSystem
448+
var toolchainRegistry: ToolchainRegistry
456449
var fs: any FSProxy
457450
}
458451

459452
for toolchainExtension in await delegate.pluginManager.extensions(of: ToolchainRegistryExtensionPoint.self) {
460-
for toolchain in await toolchainExtension.additionalToolchains(context: Context(hostOperatingSystem: hostOperatingSystem, fs: fs)) {
461-
do {
453+
do {
454+
for toolchain in try await toolchainExtension.additionalToolchains(context: Context(hostOperatingSystem: hostOperatingSystem, toolchainRegistry: self, fs: fs)) {
462455
try register(toolchain)
463-
} catch {
464-
delegate.error(error)
465456
}
457+
} catch {
458+
delegate.error(error)
466459
}
467460
}
468461
}
469462

470-
private func registerFallbackSystemToolchain(operatingSystem: OperatingSystem) throws {
471-
if lookup(Self.defaultToolchainIdentifier) != nil {
472-
return
473-
}
474-
475-
if let swift = StackedSearchPath(environment: .current, fs: fs).lookup(Path("swift")), fs.exists(swift) {
476-
let hasUsrBin = swift.normalize().str.hasSuffix("/usr/bin/swift")
477-
let hasUsrLocalBin = swift.normalize().str.hasSuffix("/usr/local/bin/swift")
478-
let path: Path
479-
switch (hasUsrBin, hasUsrLocalBin) {
480-
case (true, false):
481-
path = swift.dirname.dirname.dirname
482-
case (false, true):
483-
path = swift.dirname.dirname.dirname.dirname
484-
case (false, false):
485-
return
486-
case (true, true):
487-
preconditionFailure()
488-
}
489-
let llvmDirectories = try Array(fs.listdir(Path("/usr/lib")).filter { $0.hasPrefix("llvm-") }.sorted().reversed())
490-
let llvmDirectoriesLocal = try Array(fs.listdir(Path("/usr/local")).filter { $0.hasPrefix("llvm") }.sorted().reversed())
491-
try register(Toolchain(Self.defaultToolchainIdentifier, "Default", Version(), [], path, [], llvmDirectories.map { "/usr/lib/\($0)/lib" } + llvmDirectoriesLocal.map { "/usr/local/\($0)/lib" } + ["/usr/lib64"], [:], [:], [:], executableSearchPaths: [path.join("usr").join("bin"), path.join("usr").join("local").join("bin"), path.join("usr").join("libexec")], testingLibraryPlatformNames: [], fs: fs))
492-
}
493-
}
494-
495463
/// Register all the toolchains in the given directory.
496464
private func registerToolchainsInDirectory(_ path: Path, strict: Bool, operatingSystem: OperatingSystem, delegate: any ToolchainRegistryDelegate) async throws {
497465
let toolchainPaths: [Path] = try fs.listdir(path)

Sources/SWBGenericUnixPlatform/Plugin.swift

+131
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import Foundation
1616

1717
@PluginExtensionSystemActor public func initializePlugin(_ manager: PluginManager) {
1818
manager.register(GenericUnixPlatformSpecsExtension(), type: SpecificationsExtensionPoint.self)
19+
manager.register(GenericUnixPlatformInfoExtension(), type: PlatformInfoExtensionPoint.self)
20+
manager.register(GenericUnixSDKRegistryExtension(), type: SDKRegistryExtensionPoint.self)
21+
manager.register(GenericUnixToolchainRegistryExtension(), type: ToolchainRegistryExtensionPoint.self)
1922
}
2023

2124
struct GenericUnixPlatformSpecsExtension: SpecificationsExtension {
@@ -27,3 +30,131 @@ struct GenericUnixPlatformSpecsExtension: SpecificationsExtension {
2730
["linux": ["generic-unix"]]
2831
}
2932
}
33+
34+
struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
35+
func additionalPlatforms(context: any PlatformInfoExtensionAdditionalPlatformsContext) throws -> [(path: Path, data: [String: PropertyListItem])] {
36+
let operatingSystem = context.hostOperatingSystem
37+
guard operatingSystem.createFallbackSystemToolchain else {
38+
return []
39+
}
40+
41+
return try [
42+
(.root, [
43+
"Type": .plString("Platform"),
44+
"Name": .plString(operatingSystem.xcodePlatformName),
45+
"Identifier": .plString(operatingSystem.xcodePlatformName),
46+
"Description": .plString(operatingSystem.xcodePlatformName),
47+
"FamilyName": .plString(operatingSystem.xcodePlatformName.capitalized),
48+
"FamilyIdentifier": .plString(operatingSystem.xcodePlatformName),
49+
"IsDeploymentPlatform": .plString("YES"),
50+
])
51+
]
52+
}
53+
}
54+
55+
struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
56+
func additionalSDKs(context: any SDKRegistryExtensionAdditionalSDKsContext) async throws -> [(path: Path, platform: SWBCore.Platform?, data: [String: PropertyListItem])] {
57+
let operatingSystem = context.hostOperatingSystem
58+
guard operatingSystem.createFallbackSystemToolchain, let platform = try context.platformRegistry.lookup(name: operatingSystem.xcodePlatformName) else {
59+
return []
60+
}
61+
62+
let defaultProperties: [String: PropertyListItem]
63+
switch operatingSystem {
64+
case .linux:
65+
defaultProperties = [
66+
// Workaround to avoid `-dependency_info` on Linux.
67+
"LD_DEPENDENCY_INFO_FILE": .plString(""),
68+
69+
"GENERATE_TEXT_BASED_STUBS": "NO",
70+
"GENERATE_INTERMEDIATE_TEXT_BASED_STUBS": "NO",
71+
72+
"CHOWN": "/usr/bin/chown",
73+
"AR": "llvm-ar",
74+
]
75+
default:
76+
defaultProperties = [:]
77+
}
78+
79+
let tripleEnvironment: String
80+
switch operatingSystem {
81+
case .linux:
82+
tripleEnvironment = "gnu"
83+
default:
84+
tripleEnvironment = ""
85+
}
86+
87+
return try [(.root, platform, [
88+
"Type": .plString("SDK"),
89+
"Version": .plString(Version(ProcessInfo.processInfo.operatingSystemVersion).zeroTrimmed.description),
90+
"CanonicalName": .plString(operatingSystem.xcodePlatformName),
91+
"IsBaseSDK": .plBool(true),
92+
"DefaultProperties": .plDict([
93+
"PLATFORM_NAME": .plString(operatingSystem.xcodePlatformName),
94+
].merging(defaultProperties, uniquingKeysWith: { _, new in new })),
95+
"SupportedTargets": .plDict([
96+
operatingSystem.xcodePlatformName: .plDict([
97+
"Archs": .plArray([.plString(Architecture.hostStringValue ?? "unknown")]),
98+
"LLVMTargetTripleEnvironment": .plString(tripleEnvironment),
99+
"LLVMTargetTripleSys": .plString(operatingSystem.xcodePlatformName),
100+
"LLVMTargetTripleVendor": .plString("unknown"),
101+
])
102+
]),
103+
])]
104+
}
105+
}
106+
107+
struct GenericUnixToolchainRegistryExtension: ToolchainRegistryExtension {
108+
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
109+
let operatingSystem = context.hostOperatingSystem
110+
guard operatingSystem.createFallbackSystemToolchain else {
111+
return []
112+
}
113+
114+
let fs = context.fs
115+
116+
if let swift = StackedSearchPath(environment: .current, fs: fs).lookup(Path("swift")), fs.exists(swift) {
117+
let realSwiftPath = try fs.realpath(swift).dirname.normalize()
118+
let hasUsrBin = realSwiftPath.str.hasSuffix("/usr/bin")
119+
let hasUsrLocalBin = realSwiftPath.str.hasSuffix("/usr/local/bin")
120+
let path: Path
121+
switch (hasUsrBin, hasUsrLocalBin) {
122+
case (true, false):
123+
path = realSwiftPath.dirname.dirname
124+
case (false, true):
125+
path = realSwiftPath.dirname.dirname.dirname
126+
case (false, false):
127+
throw StubError.error("Unexpected toolchain layout for Swift installation path: \(realSwiftPath)")
128+
case (true, true):
129+
preconditionFailure()
130+
}
131+
let llvmDirectories = try Array(fs.listdir(Path("/usr/lib")).filter { $0.hasPrefix("llvm-") }.sorted().reversed())
132+
let llvmDirectoriesLocal = try Array(fs.listdir(Path("/usr/local")).filter { $0.hasPrefix("llvm") }.sorted().reversed())
133+
return [
134+
Toolchain(
135+
ToolchainRegistry.defaultToolchainIdentifier,
136+
"Default",
137+
Version(),
138+
["default"],
139+
path,
140+
[],
141+
llvmDirectories.map { "/usr/lib/\($0)/lib" } + llvmDirectoriesLocal.map { "/usr/local/\($0)/lib" } + ["/usr/lib64"],
142+
[:],
143+
[:],
144+
[:],
145+
executableSearchPaths: realSwiftPath.dirname.relativeSubpath(from: path).map { [path.join($0).join("bin")] } ?? [],
146+
testingLibraryPlatformNames: [],
147+
fs: fs)
148+
]
149+
}
150+
151+
return []
152+
}
153+
}
154+
155+
extension OperatingSystem {
156+
/// Whether the Core is allowed to create a fallback toolchain, SDK, and platform for this operating system in cases where no others have been provided.
157+
var createFallbackSystemToolchain: Bool {
158+
return self == .linux
159+
}
160+
}

Sources/SWBQNXPlatform/Plugin.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ struct QNXSDKRegistryExtension: SDKRegistryExtension {
141141
struct QNXToolchainRegistryExtension: ToolchainRegistryExtension {
142142
let plugin: QNXPlugin
143143

144-
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async -> [Toolchain] {
144+
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
145145
guard let toolchainPath = try? await plugin.cachedQNXSDPInstallations(host: context.hostOperatingSystem).first?.hostPath else {
146146
return []
147147
}

0 commit comments

Comments
 (0)