@@ -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 {
@@ -69,9 +102,11 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
69102}
70103
71104struct 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,23 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
100135 tripleEnvironment = " "
101136 }
102137
138+ let swiftTargetInfo = try await plugin. swiftTargetInfo ( swiftExecutablePath: swift)
139+
140+ let deploymentTargetSettings : [ String : PropertyListItem ]
141+ if operatingSystem == . freebsd {
142+ guard let tripleVersion = swiftTargetInfo. target. tripleVersion else {
143+ throw StubError . error ( " Unknown FreeBSD triple version " )
144+ }
145+ deploymentTargetSettings = [
146+ " DeploymentTargetSettingName " : . plString( " FREEBSD_DEPLOYMENT_TARGET " ) ,
147+ " DefaultDeploymentTarget " : . plString( tripleVersion) ,
148+ " MinimumDeploymentTarget " : . plString( tripleVersion) ,
149+ " MaximumDeploymentTarget " : . plString( tripleVersion) ,
150+ ]
151+ } else {
152+ deploymentTargetSettings = [ : ]
153+ }
154+
103155 return try [ ( . root, platform, [
104156 " Type " : . plString( " SDK " ) ,
105157 " Version " : . plString( Version ( ProcessInfo . processInfo. operatingSystemVersion) . zeroTrimmed. description) ,
@@ -114,62 +166,54 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
114166 " LLVMTargetTripleEnvironment " : . plString( tripleEnvironment) ,
115167 " LLVMTargetTripleSys " : . plString( operatingSystem. xcodePlatformName) ,
116168 " LLVMTargetTripleVendor " : . plString( " unknown " ) ,
117- ] )
169+ ] . merging ( deploymentTargetSettings , uniquingKeysWith : { _ , new in new } ) )
118170 ] ) ,
119171 ] ) ]
120172 }
121173}
122174
123175struct GenericUnixToolchainRegistryExtension : ToolchainRegistryExtension {
176+ let plugin : GenericUnixPlugin
177+
124178 func additionalToolchains( context: any ToolchainRegistryExtensionAdditionalToolchainsContext ) async throws -> [ Toolchain ] {
125179 let operatingSystem = context. hostOperatingSystem
126- guard operatingSystem. createFallbackSystemToolchain else {
180+ let fs = context. fs
181+ guard operatingSystem. createFallbackSystemToolchain, let swift = plugin. swiftExecutablePath ( fs: fs) else {
127182 return [ ]
128183 }
129184
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- }
185+ let realSwiftPath = try fs. realpath ( swift) . dirname. normalize ( )
186+ let hasUsrBin = realSwiftPath. str. hasSuffix ( " /usr/bin " )
187+ let hasUsrLocalBin = realSwiftPath. str. hasSuffix ( " /usr/local/bin " )
188+ let path : Path
189+ switch ( hasUsrBin, hasUsrLocalBin) {
190+ case ( true , false ) :
191+ path = realSwiftPath. dirname. dirname
192+ case ( false , true ) :
193+ path = realSwiftPath. dirname. dirname. dirname
194+ case ( false , false ) :
195+ throw StubError . error ( " Unexpected toolchain layout for Swift installation path: \( realSwiftPath) " )
196+ case ( true , true ) :
197+ preconditionFailure ( )
170198 }
171-
172- return [ ]
199+ let llvmDirectories = try Array ( fs. listdir ( Path ( " /usr/lib " ) ) . filter { $0. hasPrefix ( " llvm- " ) } . sorted ( ) . reversed ( ) )
200+ let llvmDirectoriesLocal = try Array ( fs. listdir ( Path ( " /usr/local " ) ) . filter { $0. hasPrefix ( " llvm " ) } . sorted ( ) . reversed ( ) )
201+ return [
202+ Toolchain (
203+ identifier: ToolchainRegistry . defaultToolchainIdentifier,
204+ displayName: " Default " ,
205+ version: Version ( ) ,
206+ aliases: [ " default " ] ,
207+ path: path,
208+ frameworkPaths: [ ] ,
209+ libraryPaths: llvmDirectories. map { " /usr/lib/ \( $0) /lib " } + llvmDirectoriesLocal. map { " /usr/local/ \( $0) /lib " } + [ " /usr/lib64 " ] ,
210+ defaultSettings: [ : ] ,
211+ overrideSettings: [ : ] ,
212+ defaultSettingsWhenPrimary: [ : ] ,
213+ executableSearchPaths: realSwiftPath. dirname. relativeSubpath ( from: path) . map { [ path. join ( $0) . join ( " bin " ) ] } ?? [ ] ,
214+ testingLibraryPlatformNames: [ ] ,
215+ fs: fs)
216+ ]
173217 }
174218}
175219
0 commit comments