@@ -15,11 +15,44 @@ import SWBCore
1515import 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
2558struct GenericUnixDeveloperDirectoryExtension : DeveloperDirectoryExtension {
@@ -65,9 +98,11 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
6598}
6699
67100struct GenericUnixSDKRegistryExtension : SDKRegistryExtension {
101+ let plugin : GenericUnixPlugin
102+
68103 func additionalSDKs( context: any SDKRegistryExtensionAdditionalSDKsContext ) async throws -> [ ( path: Path , platform: SWBCore . Platform ? , data: [ String : PropertyListItem ] ) ] {
69104 let operatingSystem = context. hostOperatingSystem
70- guard operatingSystem. createFallbackSystemToolchain, let platform = try context. platformRegistry. lookup ( name: operatingSystem. xcodePlatformName) else {
105+ guard operatingSystem. createFallbackSystemToolchain, let platform = try context. platformRegistry. lookup ( name: operatingSystem. xcodePlatformName) , let swift = plugin . swiftExecutablePath ( fs : context . fs ) else {
71106 return [ ]
72107 }
73108
@@ -96,6 +131,23 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
96131 tripleEnvironment = " "
97132 }
98133
134+ let swiftTargetInfo = try await plugin. swiftTargetInfo ( swiftExecutablePath: swift)
135+
136+ let deploymentTargetSettings : [ String : PropertyListItem ]
137+ if operatingSystem == . freebsd {
138+ guard let tripleVersion = swiftTargetInfo. target. tripleVersion else {
139+ throw StubError . error ( " Unknown FreeBSD triple version " )
140+ }
141+ deploymentTargetSettings = [
142+ " DeploymentTargetSettingName " : . plString( " FREEBSD_DEPLOYMENT_TARGET " ) ,
143+ " DefaultDeploymentTarget " : . plString( tripleVersion) ,
144+ " MinimumDeploymentTarget " : . plString( tripleVersion) ,
145+ " MaximumDeploymentTarget " : . plString( tripleVersion) ,
146+ ]
147+ } else {
148+ deploymentTargetSettings = [ : ]
149+ }
150+
99151 return try [ ( . root, platform, [
100152 " Type " : . plString( " SDK " ) ,
101153 " Version " : . plString( Version ( ProcessInfo . processInfo. operatingSystemVersion) . zeroTrimmed. description) ,
@@ -110,62 +162,54 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
110162 " LLVMTargetTripleEnvironment " : . plString( tripleEnvironment) ,
111163 " LLVMTargetTripleSys " : . plString( operatingSystem. xcodePlatformName) ,
112164 " LLVMTargetTripleVendor " : . plString( " unknown " ) ,
113- ] )
165+ ] . merging ( deploymentTargetSettings , uniquingKeysWith : { _ , new in new } ) )
114166 ] ) ,
115167 ] ) ]
116168 }
117169}
118170
119171struct GenericUnixToolchainRegistryExtension : ToolchainRegistryExtension {
172+ let plugin : GenericUnixPlugin
173+
120174 func additionalToolchains( context: any ToolchainRegistryExtensionAdditionalToolchainsContext ) async throws -> [ Toolchain ] {
121175 let operatingSystem = context. hostOperatingSystem
122- guard operatingSystem. createFallbackSystemToolchain else {
176+ let fs = context. fs
177+ guard operatingSystem. createFallbackSystemToolchain, let swift = plugin. swiftExecutablePath ( fs: fs) else {
123178 return [ ]
124179 }
125180
126- let fs = context. fs
127-
128- for swift in [
129- Environment . current [ " SWIFT_EXEC " ] . map ( Path . init) ,
130- StackedSearchPath ( environment: . current, fs: fs) . lookup ( Path ( " swift " ) )
131- ] . compactMap ( \. self) {
132- if fs. exists ( swift) {
133- let realSwiftPath = try fs. realpath ( swift) . dirname. normalize ( )
134- let hasUsrBin = realSwiftPath. str. hasSuffix ( " /usr/bin " )
135- let hasUsrLocalBin = realSwiftPath. str. hasSuffix ( " /usr/local/bin " )
136- let path : Path
137- switch ( hasUsrBin, hasUsrLocalBin) {
138- case ( true , false ) :
139- path = realSwiftPath. dirname. dirname
140- case ( false , true ) :
141- path = realSwiftPath. dirname. dirname. dirname
142- case ( false , false ) :
143- throw StubError . error ( " Unexpected toolchain layout for Swift installation path: \( realSwiftPath) " )
144- case ( true , true ) :
145- preconditionFailure ( )
146- }
147- let llvmDirectories = try Array ( fs. listdir ( Path ( " /usr/lib " ) ) . filter { $0. hasPrefix ( " llvm- " ) } . sorted ( ) . reversed ( ) )
148- let llvmDirectoriesLocal = try Array ( fs. listdir ( Path ( " /usr/local " ) ) . filter { $0. hasPrefix ( " llvm " ) } . sorted ( ) . reversed ( ) )
149- return [
150- Toolchain (
151- identifier: ToolchainRegistry . defaultToolchainIdentifier,
152- displayName: " Default " ,
153- version: Version ( ) ,
154- aliases: [ " default " ] ,
155- path: path,
156- frameworkPaths: [ ] ,
157- libraryPaths: llvmDirectories. map { " /usr/lib/ \( $0) /lib " } + llvmDirectoriesLocal. map { " /usr/local/ \( $0) /lib " } + [ " /usr/lib64 " ] ,
158- defaultSettings: [ : ] ,
159- overrideSettings: [ : ] ,
160- defaultSettingsWhenPrimary: [ : ] ,
161- executableSearchPaths: realSwiftPath. dirname. relativeSubpath ( from: path) . map { [ path. join ( $0) . join ( " bin " ) ] } ?? [ ] ,
162- testingLibraryPlatformNames: [ ] ,
163- fs: fs)
164- ]
165- }
181+ let realSwiftPath = try fs. realpath ( swift) . dirname. normalize ( )
182+ let hasUsrBin = realSwiftPath. str. hasSuffix ( " /usr/bin " )
183+ let hasUsrLocalBin = realSwiftPath. str. hasSuffix ( " /usr/local/bin " )
184+ let path : Path
185+ switch ( hasUsrBin, hasUsrLocalBin) {
186+ case ( true , false ) :
187+ path = realSwiftPath. dirname. dirname
188+ case ( false , true ) :
189+ path = realSwiftPath. dirname. dirname. dirname
190+ case ( false , false ) :
191+ throw StubError . error ( " Unexpected toolchain layout for Swift installation path: \( realSwiftPath) " )
192+ case ( true , true ) :
193+ preconditionFailure ( )
166194 }
167-
168- return [ ]
195+ let llvmDirectories = try Array ( fs. listdir ( Path ( " /usr/lib " ) ) . filter { $0. hasPrefix ( " llvm- " ) } . sorted ( ) . reversed ( ) )
196+ let llvmDirectoriesLocal = try Array ( fs. listdir ( Path ( " /usr/local " ) ) . filter { $0. hasPrefix ( " llvm " ) } . sorted ( ) . reversed ( ) )
197+ return [
198+ Toolchain (
199+ identifier: ToolchainRegistry . defaultToolchainIdentifier,
200+ displayName: " Default " ,
201+ version: Version ( ) ,
202+ aliases: [ " default " ] ,
203+ path: path,
204+ frameworkPaths: [ ] ,
205+ libraryPaths: llvmDirectories. map { " /usr/lib/ \( $0) /lib " } + llvmDirectoriesLocal. map { " /usr/local/ \( $0) /lib " } + [ " /usr/lib64 " ] ,
206+ defaultSettings: [ : ] ,
207+ overrideSettings: [ : ] ,
208+ defaultSettingsWhenPrimary: [ : ] ,
209+ executableSearchPaths: realSwiftPath. dirname. relativeSubpath ( from: path) . map { [ path. join ( $0) . join ( " bin " ) ] } ?? [ ] ,
210+ testingLibraryPlatformNames: [ ] ,
211+ fs: fs)
212+ ]
169213 }
170214}
171215
0 commit comments