|
10 | 10 | // |
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | | -import struct Foundation.URL |
14 | | - |
15 | | -private import struct Basics.AbsolutePath |
16 | | -private import func Basics.resolveSymlinks |
17 | | - |
18 | | -internal import SPMBuildCore |
19 | | - |
20 | | -// FIXME: should import these module with `private` or `internal` access control |
21 | | -import class Build.BuildPlan |
22 | | -import class Build.ClangModuleBuildDescription |
23 | | -import class Build.SwiftModuleBuildDescription |
24 | | -import struct PackageGraph.ResolvedModule |
25 | | -import struct PackageGraph.ModulesGraph |
26 | | -internal import class PackageModel.UserToolchain |
| 13 | +import Foundation |
| 14 | +import TSCBasic |
| 15 | + |
| 16 | +// Ideally wouldn't expose these (it defeats the purpose of this module), but we should replace this entire API with |
| 17 | +// a BSP server, so this is good enough for now (and LSP is using all these types internally anyway). |
| 18 | +import Basics |
| 19 | +import Build |
| 20 | +import PackageGraph |
| 21 | +internal import PackageLoading |
| 22 | +internal import PackageModel |
| 23 | +import SPMBuildCore |
27 | 24 |
|
28 | 25 | public enum BuildDestination { |
29 | 26 | case host |
@@ -102,7 +99,7 @@ private struct WrappedClangTargetBuildDescription: BuildTarget { |
102 | 99 | } |
103 | 100 |
|
104 | 101 | public func compileArguments(for fileURL: URL) throws -> [String] { |
105 | | - let filePath = try resolveSymlinks(try AbsolutePath(validating: fileURL.path)) |
| 102 | + let filePath = try resolveSymlinks(try Basics.AbsolutePath(validating: fileURL.path)) |
106 | 103 | let commandLine = try description.emitCommandLine(for: filePath) |
107 | 104 | // First element on the command line is the compiler itself, not an argument. |
108 | 105 | return Array(commandLine.dropFirst()) |
@@ -160,14 +157,52 @@ public struct BuildDescription { |
160 | 157 |
|
161 | 158 | /// The inputs of the build plan so we don't need to re-compute them on every call to |
162 | 159 | /// `fileAffectsSwiftOrClangBuildSettings`. |
163 | | - private let inputs: [BuildPlan.Input] |
| 160 | + private let inputs: [Build.BuildPlan.Input] |
164 | 161 |
|
165 | | - // FIXME: should not use `BuildPlan` in the public interface |
| 162 | + /// Wrap an already constructed build plan. |
166 | 163 | public init(buildPlan: Build.BuildPlan) { |
167 | 164 | self.buildPlan = buildPlan |
168 | 165 | self.inputs = buildPlan.inputs |
169 | 166 | } |
170 | 167 |
|
| 168 | + /// Construct a build description, compiling build tool plugins and generating their output when necessary. |
| 169 | + public static func load( |
| 170 | + destinationBuildParameters: BuildParameters, |
| 171 | + toolsBuildParameters: BuildParameters, |
| 172 | + packageGraph: ModulesGraph, |
| 173 | + pluginConfiguration: PluginConfiguration, |
| 174 | + traitConfiguration: TraitConfiguration, |
| 175 | + disableSandbox: Bool, |
| 176 | + scratchDirectory: URL, |
| 177 | + fileSystem: any FileSystem, |
| 178 | + observabilityScope: ObservabilityScope |
| 179 | + ) async throws -> (description: BuildDescription, errors: String) { |
| 180 | + let bufferedOutput = BufferedOutputByteStream() |
| 181 | + let threadSafeOutput = ThreadSafeOutputByteStream(bufferedOutput) |
| 182 | + |
| 183 | + // This is quite an abuse of `BuildOperation`, building plugins should really be refactored out of it. Though |
| 184 | + // even better would be to have a BSP server that handles both preparing and getting settings. |
| 185 | + // https://github.com/swiftlang/swift-package-manager/issues/8287 |
| 186 | + let operation = BuildOperation( |
| 187 | + productsBuildParameters: destinationBuildParameters, |
| 188 | + toolsBuildParameters: toolsBuildParameters, |
| 189 | + cacheBuildManifest: true, |
| 190 | + packageGraphLoader: { packageGraph }, |
| 191 | + pluginConfiguration: pluginConfiguration, |
| 192 | + scratchDirectory: try Basics.AbsolutePath(validating: scratchDirectory.path), |
| 193 | + traitConfiguration: traitConfiguration, |
| 194 | + additionalFileRules: FileRuleDescription.swiftpmFileTypes, |
| 195 | + pkgConfigDirectories: [], |
| 196 | + outputStream: threadSafeOutput, |
| 197 | + logLevel: .error, |
| 198 | + fileSystem: fileSystem, |
| 199 | + observabilityScope: observabilityScope |
| 200 | + ) |
| 201 | + |
| 202 | + let plan = try await operation.generatePlan() |
| 203 | + return (BuildDescription(buildPlan: plan), bufferedOutput.bytes.description) |
| 204 | + } |
| 205 | + |
171 | 206 | func getBuildTarget( |
172 | 207 | for module: ResolvedModule, |
173 | 208 | destination: BuildParameters.Destination |
@@ -219,7 +254,7 @@ public struct BuildDescription { |
219 | 254 | /// Returns `true` if the file at the given path might influence build settings for a `swiftc` or `clang` invocation |
220 | 255 | /// generated by SwiftPM. |
221 | 256 | public func fileAffectsSwiftOrClangBuildSettings(_ url: URL) -> Bool { |
222 | | - guard let filePath = try? AbsolutePath(validating: url.path) else { |
| 257 | + guard let filePath = try? Basics.AbsolutePath(validating: url.path) else { |
223 | 258 | return false |
224 | 259 | } |
225 | 260 |
|
|
0 commit comments