@@ -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 {
@@ -69,9 +102,11 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
69
102
}
70
103
71
104
struct GenericUnixSDKRegistryExtension : SDKRegistryExtension {
105
+ let plugin : GenericUnixPlugin
106
+
72
107
func additionalSDKs( context: any SDKRegistryExtensionAdditionalSDKsContext ) async throws -> [ ( path: Path , platform: SWBCore . Platform ? , data: [ String : PropertyListItem ] ) ] {
73
108
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 {
75
110
return [ ]
76
111
}
77
112
@@ -100,6 +135,23 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
100
135
tripleEnvironment = " "
101
136
}
102
137
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
+
103
155
return try [ ( . root, platform, [
104
156
" Type " : . plString( " SDK " ) ,
105
157
" Version " : . plString( Version ( ProcessInfo . processInfo. operatingSystemVersion) . zeroTrimmed. description) ,
@@ -114,62 +166,54 @@ struct GenericUnixSDKRegistryExtension: SDKRegistryExtension {
114
166
" LLVMTargetTripleEnvironment " : . plString( tripleEnvironment) ,
115
167
" LLVMTargetTripleSys " : . plString( operatingSystem. xcodePlatformName) ,
116
168
" LLVMTargetTripleVendor " : . plString( " unknown " ) ,
117
- ] )
169
+ ] . merging ( deploymentTargetSettings , uniquingKeysWith : { _ , new in new } ) )
118
170
] ) ,
119
171
] ) ]
120
172
}
121
173
}
122
174
123
175
struct GenericUnixToolchainRegistryExtension : ToolchainRegistryExtension {
176
+ let plugin : GenericUnixPlugin
177
+
124
178
func additionalToolchains( context: any ToolchainRegistryExtensionAdditionalToolchainsContext ) async throws -> [ Toolchain ] {
125
179
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 {
127
182
return [ ]
128
183
}
129
184
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 ( )
170
198
}
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
+ ]
173
217
}
174
218
}
175
219
0 commit comments