@@ -15,11 +15,44 @@ import SWBCore
15
15
import Foundation
16
16
17
17
@PluginExtensionSystemActor public func initializePlugin( _ manager: PluginManager ) {
18
+ let plugin = GenericUnixPlugin ( )
18
19
manager. register ( GenericUnixDeveloperDirectoryExtension ( ) , type: DeveloperDirectoryExtensionPoint . self)
19
20
manager. register ( GenericUnixPlatformSpecsExtension ( ) , type: SpecificationsExtensionPoint . self)
20
21
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
+ }
23
56
}
24
57
25
58
struct GenericUnixDeveloperDirectoryExtension : DeveloperDirectoryExtension {
@@ -65,9 +98,11 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
65
98
}
66
99
67
100
struct GenericUnixSDKRegistryExtension : SDKRegistryExtension {
101
+ let plugin : GenericUnixPlugin
102
+
68
103
func additionalSDKs( context: any SDKRegistryExtensionAdditionalSDKsContext ) async throws -> [ ( path: Path , platform: SWBCore . Platform ? , data: [ String : PropertyListItem ] ) ] {
69
104
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 {
71
106
return [ ]
72
107
}
73
108
@@ -96,6 +131,23 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
96
131
tripleEnvironment = " "
97
132
}
98
133
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
+
99
151
return try [ ( . root, platform, [
100
152
" Type " : . plString( " SDK " ) ,
101
153
" Version " : . plString( Version ( ProcessInfo . processInfo. operatingSystemVersion) . zeroTrimmed. description) ,
@@ -110,62 +162,54 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
110
162
" LLVMTargetTripleEnvironment " : . plString( tripleEnvironment) ,
111
163
" LLVMTargetTripleSys " : . plString( operatingSystem. xcodePlatformName) ,
112
164
" LLVMTargetTripleVendor " : . plString( " unknown " ) ,
113
- ] )
165
+ ] . merging ( deploymentTargetSettings , uniquingKeysWith : { _ , new in new } ) )
114
166
] ) ,
115
167
] ) ]
116
168
}
117
169
}
118
170
119
171
struct GenericUnixToolchainRegistryExtension : ToolchainRegistryExtension {
172
+ let plugin : GenericUnixPlugin
173
+
120
174
func additionalToolchains( context: any ToolchainRegistryExtensionAdditionalToolchainsContext ) async throws -> [ Toolchain ] {
121
175
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 {
123
178
return [ ]
124
179
}
125
180
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 ( )
166
194
}
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
+ ]
169
213
}
170
214
}
171
215
0 commit comments