Skip to content

Commit 3f65655

Browse files
committed
Handle generated resources from plugins
rdar://89693335
1 parent e78566f commit 3f65655

File tree

9 files changed

+185
-81
lines changed

9 files changed

+185
-81
lines changed

Sources/Build/BuildOperation.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Basics
1414
import LLBuildManifest
1515
import PackageGraph
16+
import PackageLoading
1617
import PackageModel
1718
import SPMBuildCore
1819
import SPMLLBuild
@@ -78,10 +79,14 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
7879
(try? getBuildDescription())?.builtTestProducts ?? []
7980
}
8081

82+
/// File rules to determine resource handling behavior.
83+
private let additionalFileRules: [FileRuleDescription]
84+
8185
public init(
8286
buildParameters: BuildParameters,
8387
cacheBuildManifest: Bool,
8488
packageGraphLoader: @escaping () throws -> PackageGraph,
89+
additionalFileRules: [FileRuleDescription],
8590
pluginScriptRunner: PluginScriptRunner,
8691
pluginWorkDirectory: AbsolutePath,
8792
disableSandboxForPluginCommands: Bool = false,
@@ -97,6 +102,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
97102
self.buildParameters = buildParameters
98103
self.cacheBuildManifest = cacheBuildManifest
99104
self.packageGraphLoader = packageGraphLoader
105+
self.additionalFileRules = additionalFileRules
100106
self.pluginScriptRunner = pluginScriptRunner
101107
self.pluginWorkDirectory = pluginWorkDirectory
102108
self.disableSandboxForPluginCommands = disableSandboxForPluginCommands
@@ -351,6 +357,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
351357
let plan = try BuildPlan(
352358
buildParameters: buildParameters,
353359
graph: graph,
360+
additionalFileRules: additionalFileRules,
354361
buildToolPluginInvocationResults: buildToolPluginInvocationResults,
355362
prebuildCommandResults: prebuildCommandResults,
356363
fileSystem: self.fileSystem,
@@ -443,7 +450,7 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
443450
return try pluginResults.map { pluginResult in
444451
// As we go we will collect a list of prebuild output directories whose contents should be input to the build,
445452
// and a list of the files in those directories after running the commands.
446-
var derivedSourceFiles: [AbsolutePath] = []
453+
var derivedFiles: [AbsolutePath] = []
447454
var prebuildOutputDirs: [AbsolutePath] = []
448455
for command in pluginResult.prebuildCommands {
449456
self.observabilityScope.emit(info: "Running" + (command.configuration.displayName ?? command.configuration.executable.basename))
@@ -463,15 +470,15 @@ public final class BuildOperation: PackageStructureDelegate, SPMBuildCore.BuildS
463470
// Add any files found in the output directory declared for the prebuild command after the command ends.
464471
let outputFilesDir = command.outputFilesDirectory
465472
if let swiftFiles = try? self.fileSystem.getDirectoryContents(outputFilesDir).sorted() {
466-
derivedSourceFiles.append(contentsOf: swiftFiles.map{ outputFilesDir.appending(component: $0) })
473+
derivedFiles.append(contentsOf: swiftFiles.map{ outputFilesDir.appending(component: $0) })
467474
}
468475

469476
// Add the output directory to the list of directories whose structure should affect the build plan.
470477
prebuildOutputDirs.append(outputFilesDir)
471478
}
472479

473480
// Add the results of running any prebuild commands for this invocation.
474-
return PrebuildCommandResult(derivedSourceFiles: derivedSourceFiles, outputDirectories: prebuildOutputDirs)
481+
return PrebuildCommandResult(derivedFiles: derivedFiles, outputDirectories: prebuildOutputDirs)
475482
}
476483
}
477484

Sources/Build/BuildPlan.swift

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ public enum TargetBuildDescription {
174174
}
175175
}
176176

177+
/// The resources in this target.
178+
var resources: [Resource] {
179+
switch self {
180+
case .swift(let target):
181+
return target.resources
182+
case .clang(let target):
183+
// TODO: Clang targets should support generated resources in the future.
184+
return target.target.underlyingTarget.resources
185+
}
186+
}
187+
177188
/// Path to the bundle generated for this module (if any).
178189
var bundlePath: AbsolutePath? {
179190
switch self {
@@ -239,7 +250,7 @@ public final class ClangTargetBuildDescription {
239250

240251
/// Path to the bundle generated for this module (if any).
241252
var bundlePath: AbsolutePath? {
242-
buildParameters.bundlePath(for: target)
253+
target.underlyingTarget.bundleName.map(buildParameters.bundlePath(named:))
243254
}
244255

245256
/// The modulemap file for this target, if any.
@@ -542,16 +553,28 @@ public final class SwiftTargetBuildDescription {
542553
/// These are the source files derived from plugins.
543554
private var pluginDerivedSources: Sources
544555

556+
/// These are the resource files derived from plugins.
557+
private var pluginDerivedResources: [Resource]
558+
545559
/// Path to the bundle generated for this module (if any).
546560
var bundlePath: AbsolutePath? {
547-
buildParameters.bundlePath(for: target)
561+
if let bundleName = target.underlyingTarget.potentialBundleName, !resources.isEmpty {
562+
return buildParameters.bundlePath(named: bundleName)
563+
} else {
564+
return nil
565+
}
548566
}
549567

550568
/// The list of all source files in the target, including the derived ones.
551569
public var sources: [AbsolutePath] {
552570
target.sources.paths + derivedSources.paths + pluginDerivedSources.paths
553571
}
554572

573+
/// The list of all resource files in the target, including the derived ones.
574+
public var resources: [Resource] {
575+
target.underlyingTarget.resources + pluginDerivedResources
576+
}
577+
555578
/// The objects in this target.
556579
public var objects: [AbsolutePath] {
557580
let relativePaths = target.sources.relativePaths + derivedSources.relativePaths + pluginDerivedSources.relativePaths
@@ -633,16 +656,21 @@ public final class SwiftTargetBuildDescription {
633656
/// The results of running any prebuild commands for this target.
634657
public let prebuildCommandResults: [PrebuildCommandResult]
635658

659+
/// ObservabilityScope with which to emit diagnostics
660+
private let observabilityScope: ObservabilityScope
661+
636662
/// Create a new target description with target and build parameters.
637663
init(
638664
target: ResolvedTarget,
639665
toolsVersion: ToolsVersion,
666+
additionalFileRules: [FileRuleDescription] = [],
640667
buildParameters: BuildParameters,
641668
buildToolPluginInvocationResults: [BuildToolPluginInvocationResult] = [],
642669
prebuildCommandResults: [PrebuildCommandResult] = [],
643670
isTestTarget: Bool? = nil,
644671
isTestDiscoveryTarget: Bool = false,
645-
fileSystem: FileSystem
672+
fileSystem: FileSystem,
673+
observabilityScope: ObservabilityScope
646674
) throws {
647675
guard target.underlyingTarget is SwiftTarget else {
648676
throw InternalError("underlying target type mismatch \(target)")
@@ -659,25 +687,31 @@ public final class SwiftTargetBuildDescription {
659687
self.pluginDerivedSources = Sources(paths: [], root: buildParameters.dataPath)
660688
self.buildToolPluginInvocationResults = buildToolPluginInvocationResults
661689
self.prebuildCommandResults = prebuildCommandResults
690+
self.observabilityScope = observabilityScope
662691

663-
// Add any derived source files that were declared for any commands from plugin invocations.
692+
// Add any derived files that were declared for any commands from plugin invocations.
693+
var pluginDerivedFiles = [AbsolutePath]()
664694
for command in buildToolPluginInvocationResults.reduce([], { $0 + $1.buildCommands }) {
665-
// TODO: What should we do if we find non-Swift sources here?
666695
for absPath in command.outputFiles {
667-
let relPath = absPath.relative(to: self.pluginDerivedSources.root)
668-
self.pluginDerivedSources.relativePaths.append(relPath)
696+
pluginDerivedFiles.append(absPath)
669697
}
670698
}
671699

672-
// Add any derived source files that were discovered from output directories of prebuild commands.
700+
// Add any derived files that were discovered from output directories of prebuild commands.
673701
for result in self.prebuildCommandResults {
674-
// TODO: What should we do if we find non-Swift sources here?
675-
for path in result.derivedSourceFiles {
676-
let relPath = path.relative(to: self.pluginDerivedSources.root)
677-
self.pluginDerivedSources.relativePaths.append(relPath)
702+
for path in result.derivedFiles {
703+
pluginDerivedFiles.append(path)
678704
}
679705
}
680706

707+
// Let `TargetSourcesBuilder` compute the treatment of plugin generated files.
708+
let (derivedSources, derivedResources) = TargetSourcesBuilder.computeContents(for: pluginDerivedFiles, toolsVersion: toolsVersion, additionalFileRules: additionalFileRules, defaultLocalization: target.defaultLocalization, targetName: target.name, targetPath: target.underlyingTarget.path, observabilityScope: observabilityScope)
709+
self.pluginDerivedResources = derivedResources
710+
derivedSources.forEach { absPath in
711+
let relPath = absPath.relative(to: self.pluginDerivedSources.root)
712+
self.pluginDerivedSources.relativePaths.append(relPath)
713+
}
714+
681715
if shouldEmitObjCCompatibilityHeader {
682716
self.moduleMap = try self.generateModuleMap()
683717
}
@@ -1585,7 +1619,8 @@ public class BuildPlan {
15851619
toolsVersion: toolsVersion,
15861620
buildParameters: buildParameters,
15871621
isTestTarget: true,
1588-
fileSystem: fileSystem
1622+
fileSystem: fileSystem,
1623+
observabilityScope: observabilityScope
15891624
)
15901625

15911626
result.append((testProduct, desc))
@@ -1621,7 +1656,8 @@ public class BuildPlan {
16211656
buildParameters: buildParameters,
16221657
isTestTarget: true,
16231658
isTestDiscoveryTarget: true,
1624-
fileSystem: fileSystem
1659+
fileSystem: fileSystem,
1660+
observabilityScope: observabilityScope
16251661
)
16261662

16271663
result.append((testProduct, target))
@@ -1635,28 +1671,11 @@ public class BuildPlan {
16351671
return result
16361672
}
16371673

1638-
@available(*, deprecated, message: "use observability system instead")
1639-
public convenience init(
1640-
buildParameters: BuildParameters,
1641-
graph: PackageGraph,
1642-
buildToolPluginInvocationResults: [ResolvedTarget: [BuildToolPluginInvocationResult]] = [:],
1643-
prebuildCommandResults: [ResolvedTarget: [PrebuildCommandResult]] = [:],
1644-
diagnostics: DiagnosticsEngine,
1645-
fileSystem: FileSystem
1646-
) throws {
1647-
let observabilitySystem = ObservabilitySystem(diagnosticEngine: diagnostics)
1648-
try self.init(
1649-
buildParameters: buildParameters,
1650-
graph: graph,
1651-
fileSystem: fileSystem,
1652-
observabilityScope: observabilitySystem.topScope
1653-
)
1654-
}
1655-
16561674
/// Create a build plan with build parameters and a package graph.
16571675
public init(
16581676
buildParameters: BuildParameters,
16591677
graph: PackageGraph,
1678+
additionalFileRules: [FileRuleDescription] = [],
16601679
buildToolPluginInvocationResults: [ResolvedTarget: [BuildToolPluginInvocationResult]] = [:],
16611680
prebuildCommandResults: [ResolvedTarget: [PrebuildCommandResult]] = [:],
16621681
fileSystem: FileSystem,
@@ -1700,10 +1719,12 @@ public class BuildPlan {
17001719
targetMap[target] = try .swift(SwiftTargetBuildDescription(
17011720
target: target,
17021721
toolsVersion: toolsVersion,
1722+
additionalFileRules: additionalFileRules,
17031723
buildParameters: buildParameters,
17041724
buildToolPluginInvocationResults: buildToolPluginInvocationResults[target] ?? [],
17051725
prebuildCommandResults: prebuildCommandResults[target] ?? [],
1706-
fileSystem: fileSystem)
1726+
fileSystem: fileSystem,
1727+
observabilityScope: observabilityScope)
17071728
)
17081729
case is ClangTarget:
17091730
targetMap[target] = try .clang(ClangTargetBuildDescription(
@@ -2236,11 +2257,9 @@ private extension Basics.Diagnostic {
22362257
}
22372258

22382259
extension BuildParameters {
2239-
/// Returns a target's bundle path inside the build directory.
2240-
fileprivate func bundlePath(for target: ResolvedTarget) -> AbsolutePath? {
2241-
target.underlyingTarget.bundleName
2242-
.map{ $0 + triple.nsbundleExtension }
2243-
.map(buildPath.appending(component:))
2260+
/// Returns a named bundle's path inside the build directory.
2261+
fileprivate func bundlePath(named name: String) -> AbsolutePath {
2262+
return buildPath.appending(component: name + triple.nsbundleExtension)
22442263
}
22452264
}
22462265

Sources/Build/LLBuildManifestBuilder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ extension LLBuildManifestBuilder {
171171
let infoPlistDestination = RelativePath("Info.plist")
172172

173173
// Create a copy command for each resource file.
174-
for resource in target.target.underlyingTarget.resources {
174+
for resource in target.resources {
175175
let destination = bundlePath.appending(resource.destination)
176176
let (_, output) = addCopyCommand(from: resource.path, to: destination)
177177
outputs.append(output)

Sources/Commands/SwiftTool.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ public class SwiftTool {
752752
buildParameters: customBuildParameters ?? self.buildParameters(),
753753
cacheBuildManifest: cacheBuildManifest && self.canUseCachedBuildManifest(),
754754
packageGraphLoader: customPackageGraphLoader ?? graphLoader,
755+
additionalFileRules: FileRuleDescription.swiftpmFileTypes,
755756
pluginScriptRunner: self.getPluginScriptRunner(),
756757
pluginWorkDirectory: try self.getActiveWorkspace().location.pluginWorkingDirectory,
757758
disableSandboxForPluginCommands: self.options.security.shouldDisableSandbox,

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ public final class PackageBuilder {
767767

768768
// FIXME: use identity instead?
769769
// The name of the bundle, if one is being generated.
770-
let bundleName = resources.isEmpty ? nil : self.manifest.displayName + "_" + potentialModule.name
770+
let potentialBundleName = self.manifest.displayName + "_" + potentialModule.name
771771

772772
if sources.relativePaths.isEmpty && resources.isEmpty {
773773
return nil
@@ -808,8 +808,9 @@ public final class PackageBuilder {
808808
if sources.hasSwiftSources {
809809
return SwiftTarget(
810810
name: potentialModule.name,
811-
bundleName: bundleName,
811+
potentialBundleName: potentialBundleName,
812812
type: targetType,
813+
path: potentialModule.path,
813814
sources: sources,
814815
resources: resources,
815816
ignored: ignored,
@@ -836,13 +837,14 @@ public final class PackageBuilder {
836837

837838
return try ClangTarget(
838839
name: potentialModule.name,
839-
bundleName: bundleName,
840+
potentialBundleName: potentialBundleName,
840841
cLanguageStandard: manifest.cLanguageStandard,
841842
cxxLanguageStandard: manifest.cxxLanguageStandard,
842843
includeDir: publicHeadersPath,
843844
moduleMapType: moduleMapType,
844845
headers: headers,
845846
type: targetType,
847+
path: potentialModule.path,
846848
sources: sources,
847849
resources: resources,
848850
ignored: ignored,
@@ -1362,6 +1364,7 @@ extension PackageBuilder {
13621364
return SwiftTarget(
13631365
name: name,
13641366
type: .snippet,
1367+
path: .root,
13651368
sources: sources,
13661369
dependencies: dependencies,
13671370
swiftVersion: try swiftVersion(),

0 commit comments

Comments
 (0)