Skip to content

Commit ad067fa

Browse files
authored
fix package describe to handle binary targets (#3810)
* fix pacakge describe to handle binary targets motivation: package describe command fails for packages with binary targets changes: * PackageBuilder requires remote artifacts to be set to compute the model, as such make it a required argument * do not call PackageBuilder directly from describe and format commands, instead use Workspace::loadRootPackage API for loading a root package * update Workspace::loadRootPackage to compute artifacts
1 parent d178289 commit ad067fa

File tree

6 files changed

+56
-49
lines changed

6 files changed

+56
-49
lines changed

Sources/Build/BuildPlan.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,8 @@ public class BuildPlan {
18321832
case .artifactsArchive:
18331833
let tools = try self.parseArtifactsArchive(for: binaryTarget)
18341834
tools.forEach { availableTools[$0.name] = $0.executablePath }
1835+
case.unknown:
1836+
throw InternalError("unknown binary target '\(target.name)' type")
18351837
}
18361838
case .plugin:
18371839
continue

Sources/Commands/SwiftPackageTool.swift

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -159,55 +159,49 @@ extension SwiftPackageTool {
159159
struct Describe: SwiftCommand {
160160
static let configuration = CommandConfiguration(
161161
abstract: "Describe the current package")
162-
162+
163163
@OptionGroup(_hiddenFromHelp: true)
164164
var swiftOptions: SwiftToolOptions
165-
165+
166166
@Option(help: "json | text")
167167
var type: DescribeMode = .text
168-
168+
169169
func run(_ swiftTool: SwiftTool) throws {
170170
let workspace = try swiftTool.getActiveWorkspace()
171-
let root = try swiftTool.getWorkspaceRoot()
172-
173-
let rootManifests = try temp_await {
174-
workspace.loadRootManifests(packages: root.packages, diagnostics: swiftTool.observabilityScope.makeDiagnosticsEngine(), completion: $0)
171+
172+
guard let packagePath = try swiftTool.getWorkspaceRoot().packages.first else {
173+
throw StringError("unknown package")
175174
}
176-
guard let rootManifest = rootManifests.values.first else {
177-
throw StringError("invalid manifests at \(root.packages)")
175+
176+
let package = try tsc_await {
177+
workspace.loadRootPackage(
178+
at: packagePath,
179+
observabilityScope: swiftTool.observabilityScope,
180+
completion: $0
181+
)
178182
}
179-
180-
let builder = PackageBuilder(
181-
identity: .plain(rootManifest.name),
182-
manifest: rootManifest,
183-
productFilter: .everything,
184-
path: try swiftTool.getPackageRoot(),
185-
xcTestMinimumDeploymentTargets: MinimumDeploymentTarget.default.xcTestMinimumDeploymentTargets,
186-
fileSystem: localFileSystem,
187-
observabilityScope: swiftTool.observabilityScope
188-
)
189-
let package = try builder.construct()
190-
self.describe(package, in: type, on: swiftTool.outputStream)
183+
184+
try self.describe(package, in: type, on: swiftTool.outputStream)
191185
}
192-
186+
193187
/// Emits a textual description of `package` to `stream`, in the format indicated by `mode`.
194-
func describe(_ package: Package, in mode: DescribeMode, on stream: OutputByteStream) {
188+
func describe(_ package: Package, in mode: DescribeMode, on stream: OutputByteStream) throws {
195189
let desc = DescribedPackage(from: package)
196190
let data: Data
197191
switch mode {
198192
case .json:
199193
let encoder = JSONEncoder.makeWithDefaults()
200194
encoder.keyEncodingStrategy = .convertToSnakeCase
201-
data = try! encoder.encode(desc)
195+
data = try encoder.encode(desc)
202196
case .text:
203197
var encoder = PlainTextEncoder()
204198
encoder.formattingOptions = [.prettyPrinted]
205-
data = try! encoder.encode(desc)
199+
data = try encoder.encode(desc)
206200
}
207201
stream <<< String(decoding: data, as: UTF8.self) <<< "\n"
208202
stream.flush()
209203
}
210-
204+
211205
enum DescribeMode: String, ExpressibleByArgument {
212206
/// JSON format (guaranteed to be parsable and stable across time).
213207
case json
@@ -269,28 +263,18 @@ extension SwiftPackageTool {
269263

270264
// Get the root package.
271265
let workspace = try swiftTool.getActiveWorkspace()
272-
let root = try swiftTool.getWorkspaceRoot()
273-
let rootManifests = try temp_await {
274-
workspace.loadRootManifests(
275-
packages: root.packages,
276-
diagnostics: swiftTool.observabilityScope.makeDiagnosticsEngine(),
266+
267+
guard let packagePath = try swiftTool.getWorkspaceRoot().packages.first else {
268+
throw StringError("unknown package")
269+
}
270+
271+
let package = try tsc_await {
272+
workspace.loadRootPackage(
273+
at: packagePath,
274+
observabilityScope: swiftTool.observabilityScope,
277275
completion: $0
278276
)
279277
}
280-
guard let rootManifest = rootManifests.values.first else {
281-
throw StringError("invalid manifests at \(root.packages)")
282-
}
283-
284-
let builder = PackageBuilder(
285-
identity: .plain(rootManifest.name),
286-
manifest: rootManifest,
287-
productFilter: .everything,
288-
path: try swiftTool.getPackageRoot(),
289-
xcTestMinimumDeploymentTargets: [:], // Minimum deployment target does not matter for this operation.
290-
fileSystem: localFileSystem,
291-
observabilityScope: swiftTool.observabilityScope
292-
)
293-
let package = try builder.construct()
294278

295279
// Use the user provided flags or default to formatting mode.
296280
let formatOptions = swiftFormatFlags.isEmpty
@@ -304,7 +288,7 @@ extension SwiftPackageTool {
304288
}
305289
}.map { $0.pathString }
306290

307-
let args = [swiftFormat.pathString] + formatOptions + [rootManifest.path.pathString] + paths
291+
let args = [swiftFormat.pathString] + formatOptions + [packagePath.pathString] + paths
308292
print("Running:", args.map{ $0.spm_shellEscaped() }.joined(separator: " "))
309293

310294
let result = try Process.popen(arguments: args)

Sources/PackageLoading/ManifestLoader.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ public final class ManifestLoader: ManifestLoaderProtocol {
405405

406406
var validExtensions = [self.supportedArchiveExtension]
407407
if target.isLocal {
408-
validExtensions += BinaryTarget.Kind.allCases.map { $0.fileExtension }
408+
validExtensions += BinaryTarget.Kind.allCases.filter{ $0 != .unknown }.map { $0.fileExtension }
409409
}
410410

411411
if !validExtensions.contains(location.pathExtension) {

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public final class PackageBuilder {
263263
productFilter: ProductFilter,
264264
path: AbsolutePath,
265265
additionalFileRules: [FileRuleDescription] = [],
266-
binaryArtifacts: [BinaryArtifact] = [],
266+
binaryArtifacts: [BinaryArtifact],
267267
xcTestMinimumDeploymentTargets: [PackageModel.Platform:PlatformVersion],
268268
shouldCreateMultipleTestProducts: Bool = false,
269269
warnAboutImplicitExecutableTargets: Bool = true,
@@ -322,6 +322,7 @@ public final class PackageBuilder {
322322
manifest: manifest,
323323
productFilter: .everything,
324324
path: path,
325+
binaryArtifacts: [], // this will fail for packages with binary artifacts, but this API is deprecated and the replacement API was fixed
325326
xcTestMinimumDeploymentTargets: xcTestMinimumDeploymentTargets,
326327
fileSystem: localFileSystem,
327328
observabilityScope: ObservabilitySystem(diagnosticEngine: diagnostics).topScope

Sources/PackageModel/Target.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,13 +551,16 @@ public final class BinaryTarget: Target {
551551
public enum Kind: String, RawRepresentable, Codable, CaseIterable {
552552
case xcframework
553553
case artifactsArchive
554+
case unknown // for non-downloaded artifacts
554555

555556
public var fileExtension: String {
556557
switch self {
557558
case .xcframework:
558559
return "xcframework"
559560
case .artifactsArchive:
560561
return "artifactbundle"
562+
case .unknown:
563+
return "unknown"
561564
}
562565
}
563566

Sources/Workspace/Workspace.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,14 +1015,31 @@ extension Workspace {
10151015
observabilityScope: ObservabilityScope,
10161016
completion: @escaping(Result<Package, Error>) -> Void
10171017
) {
1018-
self.loadRootManifest(at: path, diagnostics: observabilityScope.makeDiagnosticsEngine()) { result in
1018+
self.loadRootManifest(at: path, observabilityScope: observabilityScope) { result in
10191019
let result = result.tryMap { manifest -> Package in
10201020
let identity = try self.identityResolver.resolveIdentity(for: manifest.packageKind)
1021+
1022+
// radar/82263304
1023+
// compute binary artifacts for the sake of constructing a project model
1024+
// note this does not actually download remote artifacts and as such does not have the artifact's type or path
1025+
let binaryArtifacts = try manifest.targets.filter{ $0.type == .binary }.map { target -> BinaryArtifact in
1026+
if let path = target.path {
1027+
let absolutePath = try manifest.path.parentDirectory.appending(RelativePath(validating: path))
1028+
return try BinaryArtifact(kind: .forFileExtension(absolutePath.extension ?? "unknown") , originURL: .none, path: absolutePath)
1029+
} else if let url = target.url.flatMap(URL.init(string:)) {
1030+
let fakePath = try manifest.path.parentDirectory.appending(components: "remote", "archive").appending(RelativePath(validating: url.lastPathComponent))
1031+
return BinaryArtifact(kind: .unknown, originURL: url.absoluteString, path: fakePath)
1032+
} else {
1033+
throw InternalError("a binary target should have either a path or a URL and a checksum")
1034+
}
1035+
}
1036+
10211037
let builder = PackageBuilder(
10221038
identity: identity,
10231039
manifest: manifest,
10241040
productFilter: .everything,
10251041
path: path,
1042+
binaryArtifacts: binaryArtifacts,
10261043
xcTestMinimumDeploymentTargets: MinimumDeploymentTarget.default.xcTestMinimumDeploymentTargets,
10271044
fileSystem: self.fileSystem,
10281045
observabilityScope: observabilityScope

0 commit comments

Comments
 (0)