Skip to content

Commit c302c3e

Browse files
committed
wip
1 parent 1ccff62 commit c302c3e

File tree

9 files changed

+150
-6
lines changed

9 files changed

+150
-6
lines changed

Sources/Build/BuildDelegate.swift

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ public struct BuildDescription: Codable {
195195
/// The map of test discovery commands.
196196
let testDiscoveryCommands: [CommandName: TestDiscoveryTool]
197197

198+
let copyCommands: [CommandName: CopyTool]
199+
198200
/// The built test products.
199201
public let builtTestProducts: [BuiltTestProduct]
200202

@@ -204,7 +206,11 @@ public struct BuildDescription: Codable {
204206
/// The list of executable products in the root package.
205207
public let rootExecutables: [String]
206208

207-
public init(plan: BuildPlan, testDiscoveryCommands: [CommandName: TestDiscoveryTool]) {
209+
public init(
210+
plan: BuildPlan,
211+
testDiscoveryCommands: [CommandName: TestDiscoveryTool],
212+
copyCommands: [CommandName: CopyTool]
213+
) {
208214
let buildConfig = plan.buildParameters.configuration.dirname
209215

210216
swiftTargetMap = Dictionary(uniqueKeysWithValues: plan.targetMap.values.compactMap{
@@ -213,6 +219,7 @@ public struct BuildDescription: Codable {
213219
})
214220

215221
self.testDiscoveryCommands = testDiscoveryCommands
222+
self.copyCommands = copyCommands
216223

217224
self.builtTestProducts = plan.buildProducts.filter{ $0.product.type == .test }.map { desc in
218225
// FIXME(perf): Provide faster lookups.
@@ -309,6 +316,32 @@ final class PackageStructureCommand: CustomLLBuildCommand {
309316
}
310317
}
311318

319+
final class CopyCommand: CustomLLBuildCommand {
320+
override func execute(_ command: SPMLLBuild.Command) -> Bool {
321+
// This tool will never run without the build description.
322+
let buildDescription = ctx.buildDescription!
323+
guard let tool = buildDescription.copyCommands[command.name] else {
324+
print("command \(command.name) not registered")
325+
return false
326+
}
327+
328+
do {
329+
let input = tool.inputs[0]
330+
let output = tool.outputs[0]
331+
try localFileSystem.createDirectory(AbsolutePath(output).parentDirectory, recursive: true)
332+
333+
// FIXME: We should shim this through our FileSystem APIs.
334+
try? FileManager.default.removeItem(atPath: output)
335+
try FileManager.default.copyItem(atPath: input, toPath: output)
336+
} catch {
337+
// FIXME: Shouldn't use "print" here.
338+
print("error:", error)
339+
return false
340+
}
341+
return true
342+
}
343+
}
344+
312345
private let newLineByte: UInt8 = 10
313346
public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParserDelegate {
314347
private let diagnostics: DiagnosticsEngine
@@ -352,6 +385,8 @@ public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParser
352385
return InProcessTool(buildExecutionContext, type: TestDiscoveryCommand.self)
353386
case PackageStructureTool.name:
354387
return InProcessTool(buildExecutionContext, type: PackageStructureCommand.self)
388+
case CopyTool.name:
389+
return InProcessTool(buildExecutionContext, type: CopyCommand.self)
355390
default:
356391
return nil
357392
}

Sources/Build/BuildPlan.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,9 @@ public final class SwiftTargetBuildDescription {
504504
/// These are the source files generated during the build.
505505
private var derivedSources: Sources
506506

507+
/// Path to the bundle generated for this module (if any).
508+
let bundlePath: AbsolutePath?
509+
507510
/// The list of all source files in the target, including the derived ones.
508511
var sources: [AbsolutePath] { target.sources.paths + derivedSources.paths }
509512

@@ -567,6 +570,9 @@ public final class SwiftTargetBuildDescription {
567570
self.fs = fs
568571
self.tempsPath = buildParameters.buildPath.appending(component: target.c99name + ".build")
569572
self.derivedSources = Sources(paths: [], root: tempsPath.appending(component: "DerivedSources"))
573+
self.bundlePath = target.underlyingTarget.bundleName
574+
.map{ $0 + buildParameters.triple.nsbundleExtension }
575+
.map(buildParameters.buildPath.appending(component:))
570576

571577
if shouldEmitObjCCompatibilityHeader {
572578
self.moduleMap = try self.generateModuleMap()
@@ -578,10 +584,10 @@ public final class SwiftTargetBuildDescription {
578584
/// Generate the resource bundle accessor, if appropriate.
579585
private func generateResourceAccessor() throws {
580586
// Do nothing if we're not generating a bundle.
581-
guard let bundleName = target.underlyingTarget.bundleName else { return }
587+
guard let bundlePath = self.bundlePath else { return }
582588

583589
// Compute the basename of the bundle.
584-
let bundleBasename = bundleName + buildParameters.triple.nsbundleExtension
590+
let bundleBasename = bundlePath.basename
585591

586592
let stream = BufferedOutputByteStream()
587593
stream <<< """
@@ -602,8 +608,13 @@ public final class SwiftTargetBuildDescription {
602608
// Write this file out.
603609
// FIXME: We should generate this file during the actual build.
604610
let path = derivedSources.root.appending(subpath)
605-
606611
try fs.createDirectory(path.parentDirectory, recursive: true)
612+
613+
// Return early if the contents are identical.
614+
if fs.isFile(path), try fs.readFileContents(path) == stream.bytes {
615+
return
616+
}
617+
607618
try fs.writeFileContents(path, bytes: stream.bytes)
608619
}
609620

Sources/Build/ToolProtocol.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ public struct TestDiscoveryTool: ToolProtocol, Codable {
5252
}
5353
}
5454

55+
public struct CopyTool: ToolProtocol, Codable {
56+
static let name: String = "copy-tool"
57+
58+
public let inputs: [String]
59+
public let outputs: [String]
60+
61+
public func append(to stream: OutputByteStream) {
62+
stream <<< " tool: \(Self.name)\n"
63+
stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n"
64+
stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n"
65+
}
66+
}
67+
5568
/// Package strcuture tool is used to determine if the package has changed in some way
5669
/// that requires regenerating the build manifest file. This allows us to skip a lot of
5770
/// redundent work (package graph loading, build planning, manifest generation) during

Sources/Build/llbuild.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ public final class LLBuildManifestGenerator {
210210
/// Map of command -> tool that is used during the build for in-process tools.
211211
public private(set) var testDiscoveryCommands: [String: TestDiscoveryTool] = [:]
212212

213+
public private(set) var copyCommands: [String: CopyTool] = [:]
214+
213215
/// Create a llbuild target for a product description.
214216
private func createProductTarget(_ buildProduct: ProductBuildDescription) -> Target {
215217
let tool: ToolProtocol
@@ -310,9 +312,34 @@ public final class LLBuildManifestGenerator {
310312
buildTarget.cmds.insert(Command(name: target.wrappedModuleOutputPath.pathString, tool: modulewrapTool))
311313
}
312314

315+
createResourcesBundle(for: target, buildTarget: &buildTarget)
316+
313317
return buildTarget
314318
}
315319

320+
private func createResourcesBundle(
321+
for target: SwiftTargetBuildDescription,
322+
buildTarget: inout Target
323+
) {
324+
guard let bundlePath = target.bundlePath else { return }
325+
326+
var cmds: [Command] = []
327+
328+
for item in target.target.underlyingTarget.resources {
329+
switch item.rule {
330+
case .copy, .process:
331+
let output = bundlePath.appending(component: item.path.basename)
332+
let tool = CopyTool(inputs: [item.path.pathString], outputs: [output.pathString])
333+
let cmd = Command(name: output.pathString, tool: tool)
334+
copyCommands[cmd.name] = tool
335+
cmds.append(cmd)
336+
}
337+
}
338+
339+
buildTarget.cmds += cmds
340+
buildTarget.outputs += cmds.flatMap{ $0.tool.outputs }
341+
}
342+
316343
/// Create a llbuild target for a Clang target description.
317344
private func createClangCompileTarget(_ target: ClangTargetBuildDescription) throws -> Target {
318345

Sources/Commands/SwiftTool.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,11 @@ public class SwiftTool<Options: ToolOptions> {
674674
try llbuild.generateManifest(at: plan.buildParameters.llbuildManifest)
675675

676676
// Create the build description.
677-
let buildDescription = BuildDescription(plan: plan, testDiscoveryCommands: llbuild.testDiscoveryCommands)
677+
let buildDescription = BuildDescription(
678+
plan: plan,
679+
testDiscoveryCommands: llbuild.testDiscoveryCommands,
680+
copyCommands: llbuild.copyCommands
681+
)
678682
try localFileSystem.createDirectory(plan.buildParameters.buildDescriptionPath.parentDirectory, recursive: true)
679683
try buildDescription.write(to: plan.buildParameters.buildDescriptionPath)
680684
return buildDescription

Sources/PackageLoading/PackageBuilder.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ public final class PackageBuilder {
718718

719719
// Create the build setting assignment table for this target.
720720
let buildSettings = try self.buildSettings(for: manifestTarget, targetRoot: potentialModule.path)
721+
let resources = self.computeResources(for: manifestTarget, targetRoot: potentialModule.path)
721722

722723
// Create and return the right kind of target depending on what kind of sources we found.
723724
if clangSources.isEmpty {
@@ -729,7 +730,7 @@ public final class PackageBuilder {
729730
var bundleName: String?
730731
// FIXME: This needs to depend on if we have *any* resources, not just explicitly
731732
// declared ones.
732-
if manifestTarget?.resources.isEmpty == false {
733+
if !resources.isEmpty {
733734
bundleName = manifest.name + "_" + potentialModule.name
734735
}
735736

@@ -740,6 +741,7 @@ public final class PackageBuilder {
740741
platforms: self.platforms(),
741742
isTest: potentialModule.isTest,
742743
sources: Sources(paths: swiftSources, root: potentialModule.path),
744+
resources: resources,
743745
dependencies: moduleDependencies,
744746
productDependencies: productDeps,
745747
swiftVersion: try swiftVersion(),
@@ -768,6 +770,23 @@ public final class PackageBuilder {
768770
}
769771
}
770772

773+
/// Compute the resources in the target.
774+
// FIXME: This is prelimary logic just to get things started.
775+
func computeResources(
776+
for target: TargetDescription?,
777+
targetRoot: AbsolutePath
778+
) -> [Resource] {
779+
guard let target = target else { return [] }
780+
var result: [Resource] = []
781+
782+
for resource in target.resources {
783+
let path = targetRoot.appending(RelativePath(resource.path))
784+
result += [Resource(rule: resource.rule, path: path)]
785+
}
786+
787+
return result
788+
}
789+
771790
/// Creates build setting assignment table for the given target.
772791
func buildSettings(for target: TargetDescription?, targetRoot: AbsolutePath) throws -> BuildSettings.AssignmentTable {
773792
var table = BuildSettings.AssignmentTable()

Sources/PackageModel/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_library(PackageModel
1414
Platform.swift
1515
Product.swift
1616
ResolvedModels.swift
17+
Resources.swift
1718
Sources.swift
1819
Target.swift
1920
ToolsVersion.swift)

Sources/PackageModel/Resource.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import TSCBasic
12+
13+
/// An individual resource file and its corresponding rule.
14+
public struct Resource {
15+
public typealias Rule = TargetDescription.Resource.Rule
16+
17+
/// The rule associated with this resource.
18+
public let rule: Rule
19+
20+
/// The path of the resource file.
21+
public let path: AbsolutePath
22+
23+
public init(rule: Rule, path: AbsolutePath) {
24+
self.rule = rule
25+
self.path = path
26+
}
27+
}

Sources/PackageModel/Target.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public class Target: ObjectIdentifierProtocol {
4646
/// The sources for the target.
4747
public let sources: Sources
4848

49+
/// The resource files in the target.
50+
public let resources: [Resource]
51+
4952
/// The list of platforms that are supported by this target.
5053
public let platforms: [SupportedPlatform]
5154

@@ -63,6 +66,7 @@ public class Target: ObjectIdentifierProtocol {
6366
platforms: [SupportedPlatform],
6467
type: Kind,
6568
sources: Sources,
69+
resources: [Resource] = [],
6670
dependencies: [Target],
6771
productDependencies: [(name: String, package: String?)] = [],
6872
buildSettings: BuildSettings.AssignmentTable
@@ -72,6 +76,7 @@ public class Target: ObjectIdentifierProtocol {
7276
self.platforms = platforms
7377
self.type = type
7478
self.sources = sources
79+
self.resources = resources
7580
self.dependencies = dependencies
7681
self.productDependencies = productDependencies
7782
self.c99name = self.name.spm_mangledToC99ExtendedIdentifier()
@@ -136,6 +141,7 @@ public class SwiftTarget: Target {
136141
platforms: [SupportedPlatform] = [],
137142
isTest: Bool = false,
138143
sources: Sources,
144+
resources: [Resource] = [],
139145
dependencies: [Target] = [],
140146
productDependencies: [(name: String, package: String?)] = [],
141147
swiftVersion: SwiftLanguageVersion,
@@ -149,6 +155,7 @@ public class SwiftTarget: Target {
149155
platforms: platforms,
150156
type: type,
151157
sources: sources,
158+
resources: resources,
152159
dependencies: dependencies,
153160
productDependencies: productDependencies,
154161
buildSettings: buildSettings

0 commit comments

Comments
 (0)