Skip to content

Commit 095e66b

Browse files
committed
Public API for getting information about build targets
Until now, SourceKit-LSP has been using a couple of internal data structures of the build plan, which were incidentally public, for this. This changes those data structures to internal and exposes a new public API for accessing information about build targets, including those for plugins. Note that this API is part of a new module called `SwiftPM` which could be the sstart of a "proper" public API for SwiftPM. That said, right now it depends on several types of existing modules in its public interface and that isn't likely to be resolved as part of this particular change. rdar://112120976
1 parent 4c35491 commit 095e66b

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

Package.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ let swiftPMDataModelProduct = (
4242
"PackageMetadata",
4343
"PackageModel",
4444
"SourceControl",
45+
"SwiftPM",
4546
"Workspace",
4647
]
4748
)
@@ -148,6 +149,15 @@ let package = Package(
148149
linkerSettings: packageLibraryLinkSettings
149150
),
150151

152+
// SwiftPM public API
153+
.target(
154+
name: "SwiftPM",
155+
dependencies: [
156+
"Build",
157+
"SPMBuildCore"
158+
]
159+
),
160+
151161
// MARK: SwiftPM specific support libraries
152162

153163
.systemLibrary(name: "SPMSQLite3", pkgConfig: systemSQLitePkgConfig),
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
// FIXME: should not import this module
16+
import Build
17+
// FIXME: should be internal imports
18+
import PackageGraph
19+
/*private*/ import SPMBuildCore
20+
21+
public protocol BuildTarget {
22+
// FIXME: should not use `ResolvedTarget` in the public interface
23+
var target: ResolvedTarget { get }
24+
var sources: [URL] { get }
25+
26+
func compileArguments() throws -> [String]
27+
}
28+
29+
extension ClangTargetBuildDescription: BuildTarget {
30+
public var sources: [URL] {
31+
return (try? compilePaths().map { URL(fileURLWithPath: $0.source.pathString) }) ?? []
32+
}
33+
34+
public func compileArguments() throws -> [String] {
35+
var args = try self.basicArguments()
36+
args += sources.map { $0.absoluteString }
37+
return args
38+
}
39+
}
40+
41+
private struct WrappedSwiftTargetBuildDescription: BuildTarget {
42+
private let description: SwiftTargetBuildDescription
43+
private let buildParameters: BuildParameters
44+
45+
init(description: SwiftTargetBuildDescription, buildParameters: BuildParameters) {
46+
self.description = description
47+
self.buildParameters = buildParameters
48+
}
49+
50+
var target: ResolvedTarget {
51+
return description.target
52+
}
53+
54+
var sources: [URL] {
55+
return description.sources.map { URL(fileURLWithPath: $0.pathString) }
56+
}
57+
58+
func compileArguments() throws -> [String] {
59+
var args = try description.compileArguments()
60+
args += sources.map { $0.absoluteString }
61+
args += ["-I", buildParameters.buildPath.pathString]
62+
return args
63+
}
64+
}
65+
66+
public struct BuildDescription {
67+
private let buildPlan: Build.BuildPlan
68+
69+
// FIXME: should not use `BuildPlan` in the public interface
70+
public init(buildPlan: Build.BuildPlan) {
71+
self.buildPlan = buildPlan
72+
}
73+
74+
// FIXME: should not use `ResolvedTarget` in the public interface
75+
public func getBuildTarget(for target: ResolvedTarget) -> BuildTarget? {
76+
if let description = buildPlan.targetMap[target] {
77+
switch description {
78+
case .clang(let description):
79+
return description
80+
case .swift(let description):
81+
return WrappedSwiftTargetBuildDescription(description: description, buildParameters: buildPlan.buildParameters)
82+
}
83+
} else {
84+
if target.type == .plugin, let package = self.buildPlan.graph.package(for: target) {
85+
return PluginTargetBuildDescription(target: target, toolsVersion: package.manifest.toolsVersion)
86+
}
87+
return nil
88+
}
89+
}
90+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Foundation
14+
15+
// FIXME: should be an internal import
16+
import class PackageGraph.ResolvedTarget
17+
18+
/*private*/ import class PackageLoading.ManifestLoader
19+
/*private*/ import struct PackageModel.ToolsVersion
20+
/*private*/ import class PackageModel.UserToolchain
21+
22+
struct PluginTargetBuildDescription: BuildTarget {
23+
// FIXME: should not use `ResolvedTarget` in the public interface
24+
public let target: ResolvedTarget
25+
private let toolsVersion: ToolsVersion
26+
27+
init(target: ResolvedTarget, toolsVersion: ToolsVersion) {
28+
assert(target.type == .plugin)
29+
self.target = target
30+
self.toolsVersion = toolsVersion
31+
}
32+
33+
var sources: [URL] {
34+
return target.sources.paths.map { URL(fileURLWithPath: $0.pathString) }
35+
}
36+
37+
func compileArguments() throws -> [String] {
38+
// FIXME: This is very odd and we should clean this up by merging `ManifestLoader` and `DefaultPluginScriptRunner` again.
39+
let loader = ManifestLoader(toolchain: try UserToolchain(swiftSDK: .hostSwiftSDK()))
40+
return loader.interpreterFlags(for: self.toolsVersion)
41+
}
42+
43+
44+
}

0 commit comments

Comments
 (0)