Skip to content

Commit 609e2a4

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 609e2a4

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-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: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
20+
public protocol BuildTarget {
21+
// FIXME: should not use `ResolvedTarget` in the public interface
22+
var target: ResolvedTarget { get }
23+
var sources: [URL] { get }
24+
25+
func compileArguments() throws -> [String]
26+
}
27+
28+
extension ClangTargetBuildDescription: BuildTarget {
29+
public var sources: [URL] {
30+
return (try? compilePaths().map { URL(fileURLWithPath: $0.source.pathString) }) ?? []
31+
}
32+
33+
public func compileArguments() throws -> [String] {
34+
return try self.basicArguments()
35+
}
36+
}
37+
38+
private struct WrappedSwiftTargetBuildDescription: BuildTarget {
39+
private let description: SwiftTargetBuildDescription
40+
41+
init(_ description: SwiftTargetBuildDescription) {
42+
self.description = description
43+
}
44+
45+
var target: ResolvedTarget {
46+
return description.target
47+
}
48+
49+
var sources: [URL] {
50+
return description.sources.map { URL(fileURLWithPath: $0.pathString) }
51+
}
52+
53+
func compileArguments() throws -> [String] {
54+
return try description.compileArguments()
55+
}
56+
}
57+
58+
public struct BuildDescription {
59+
private let buildPlan: BuildPlan
60+
61+
// FIXME: should not use `BuildPlan` in the public interface
62+
public init(buildPlan: BuildPlan) {
63+
self.buildPlan = buildPlan
64+
}
65+
66+
// FIXME: should not use `ResolvedTarget` in the public interface
67+
public func getBuildTarget(for target: ResolvedTarget) -> BuildTarget? {
68+
if let description = buildPlan.targetMap[target] {
69+
switch description {
70+
case .clang(let description):
71+
return description
72+
case .swift(let description):
73+
return WrappedSwiftTargetBuildDescription(description)
74+
}
75+
} else {
76+
if target.type == .plugin, let package = self.buildPlan.graph.package(for: target) {
77+
return PluginTargetBuildDescription(target: target, toolsVersion: package.manifest.toolsVersion)
78+
}
79+
return nil
80+
}
81+
}
82+
}
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)