Skip to content

Commit 5facaa5

Browse files
committed
Merge remote-tracking branch 'origin/main' into release/5.10
2 parents 408a97b + 6b0d8b7 commit 5facaa5

File tree

11 files changed

+140
-49
lines changed

11 files changed

+140
-49
lines changed

Package.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ let package = Package(
167167
.target(
168168
/** The llbuild manifest model */
169169
name: "LLBuildManifest",
170-
dependencies: ["Basics"],
170+
dependencies: [
171+
"Basics",
172+
"PackageLoading",
173+
],
171174
exclude: ["CMakeLists.txt"]
172175
),
173176

Sources/Build/BuildDescription/ClangTargetBuildDescription.swift

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,9 @@ public final class ClangTargetBuildDescription {
155155
if case .custom(let path) = clangTarget.moduleMapType {
156156
self.moduleMap = path
157157
}
158-
// If a generated module map is needed, generate one now in our temporary directory.
159-
else if let generatedModuleMapType = clangTarget.moduleMapType.generatedModuleMapType {
160-
let path = tempsPath.appending(component: moduleMapFilename)
161-
let moduleMapGenerator = ModuleMapGenerator(
162-
targetName: clangTarget.name,
163-
moduleName: clangTarget.c99name,
164-
publicHeadersDir: clangTarget.includeDir,
165-
fileSystem: fileSystem
166-
)
167-
try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType, at: path)
168-
self.moduleMap = path
158+
// If a generated module map is needed, set the path accordingly.
159+
else if clangTarget.moduleMapType.generatedModuleMapType != nil {
160+
self.moduleMap = tempsPath.appending(component: moduleMapFilename)
169161
}
170162
// Otherwise there is no module map, and we leave `moduleMap` unset.
171163
}

Sources/Build/BuildManifest/LLBuildManifestBuilder+Clang.swift

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,30 @@ extension LLBuildManifestBuilder {
3636
inputs.append(resourcesNode)
3737
}
3838

39+
var modulesReadyInputs = [Node]()
40+
41+
// If the given target needs a generated module map, set up the dependency and required task to write out the module map.
42+
if let type = target.clangTarget.moduleMapType.generatedModuleMapType, let moduleMapPath = target.moduleMap {
43+
modulesReadyInputs.append(.file(moduleMapPath))
44+
45+
self.manifest.addWriteClangModuleMapCommand(
46+
targetName: target.clangTarget.name,
47+
moduleName: target.clangTarget.c99name,
48+
publicHeadersDir: target.clangTarget.includeDir,
49+
type: type,
50+
outputPath: moduleMapPath
51+
)
52+
}
53+
54+
let modulesReady = self.addPhonyCommand(
55+
targetName: target.target.getLLBuildModulesReadyCmdName(config: self.buildConfig),
56+
inputs: modulesReadyInputs
57+
)
58+
inputs.append(modulesReady)
59+
3960
func addStaticTargetInputs(_ target: ResolvedTarget) {
61+
inputs.append(.virtual(target.getLLBuildModulesReadyCmdName(config: self.buildConfig)))
62+
4063
if case .swift(let desc)? = self.plan.targetMap[target], target.type == .library {
4164
inputs.append(file: desc.moduleOutputPath)
4265
}
@@ -116,14 +139,9 @@ extension LLBuildManifestBuilder {
116139
try addBuildToolPlugins(.clang(target))
117140

118141
// Create a phony node to represent the entire target.
119-
let targetName = target.target.getLLBuildTargetName(config: self.buildConfig)
120-
let output: Node = .virtual(targetName)
121-
122-
self.manifest.addNode(output, toTarget: targetName)
123-
self.manifest.addPhonyCmd(
124-
name: output.name,
125-
inputs: objectFileNodes,
126-
outputs: [output]
142+
let output = self.addPhonyCommand(
143+
targetName: target.target.getLLBuildTargetName(config: self.buildConfig),
144+
inputs: objectFileNodes
127145
)
128146

129147
if self.plan.graph.isInRootPackages(target.target, satisfying: self.buildEnvironment) {

Sources/Build/BuildManifest/LLBuildManifestBuilder+Resources.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ extension LLBuildManifestBuilder {
4545
outputs.append(output)
4646
}
4747

48-
let cmdName = target.target.getLLBuildResourcesCmdName(config: self.buildConfig)
49-
self.manifest.addPhonyCmd(name: cmdName, inputs: outputs, outputs: [.virtual(cmdName)])
50-
51-
return .virtual(cmdName)
48+
return self.addPhonyCommand(
49+
targetName: target.target.getLLBuildResourcesCmdName(config: self.buildConfig),
50+
inputs: outputs
51+
)
5252
}
5353
}

Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ extension LLBuildManifestBuilder {
431431
case .swift(let target)?:
432432
inputs.append(file: target.moduleOutputPath)
433433
case .clang(let target)?:
434+
inputs.append(.virtual(target.target.getLLBuildModulesReadyCmdName(config: self.buildConfig)))
434435
for object in try target.objects {
435436
inputs.append(file: object)
436437
}
@@ -487,15 +488,11 @@ extension LLBuildManifestBuilder {
487488
/// Adds a top-level phony command that builds the entire target.
488489
private func addTargetCmd(_ target: SwiftTargetBuildDescription, cmdOutputs: [Node]) {
489490
// Create a phony node to represent the entire target.
490-
let targetName = target.target.getLLBuildTargetName(config: self.buildConfig)
491-
let targetOutput: Node = .virtual(targetName)
492-
493-
self.manifest.addNode(targetOutput, toTarget: targetName)
494-
self.manifest.addPhonyCmd(
495-
name: targetOutput.name,
496-
inputs: cmdOutputs,
497-
outputs: [targetOutput]
491+
let targetOutput = self.addPhonyCommand(
492+
targetName: target.target.getLLBuildTargetName(config: self.buildConfig),
493+
inputs: cmdOutputs
498494
)
495+
499496
if self.plan.graph.isInRootPackages(target.target, satisfying: self.buildEnvironment) {
500497
if !target.isTestTarget {
501498
self.addNode(targetOutput, toTarget: .main)

Sources/Build/BuildManifest/LLBuildManifestBuilder.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ extension ResolvedTarget {
292292
public func getLLBuildResourcesCmdName(config: String) -> String {
293293
"\(name)-\(config).module-resources"
294294
}
295+
296+
public func getLLBuildModulesReadyCmdName(config: String) -> String {
297+
"\(name)-\(config).modules-ready"
298+
}
295299
}
296300

297301
extension ResolvedProduct {
@@ -345,6 +349,18 @@ extension LLBuildManifestBuilder {
345349
func destinationPath(forBinaryAt path: AbsolutePath) -> AbsolutePath {
346350
self.plan.buildParameters.buildPath.appending(component: path.basename)
347351
}
352+
353+
/// Adds a phony command and a corresponding virtual node as output.
354+
func addPhonyCommand(targetName: String, inputs: [Node]) -> Node {
355+
let output: Node = .virtual(targetName)
356+
self.manifest.addNode(output, toTarget: targetName)
357+
self.manifest.addPhonyCmd(
358+
name: output.name,
359+
inputs: inputs,
360+
outputs: [output]
361+
)
362+
return output
363+
}
348364
}
349365

350366
extension Sequence where Element: Hashable {

Sources/LLBuildManifest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_library(LLBuildManifest STATIC
1515
Tools.swift)
1616
target_link_libraries(LLBuildManifest PUBLIC
1717
TSCBasic
18+
PackageLoading
1819
Basics)
1920

2021
# NOTE(compnerd) workaround for CMake not setting up include flags yet

Sources/LLBuildManifest/LLBuildManifest.swift

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import Basics
1414
import Foundation
15+
import PackageLoading
1516

1617
import class TSCBasic.Process
1718

@@ -23,6 +24,7 @@ public protocol AuxiliaryFileType {
2324

2425
public enum WriteAuxiliary {
2526
public static let fileTypes: [AuxiliaryFileType.Type] = [
27+
ClangModuleMap.self,
2628
EntitlementPlist.self,
2729
LinkFileList.self,
2830
SourcesFileList.self,
@@ -54,6 +56,58 @@ public enum WriteAuxiliary {
5456
}
5557
}
5658

59+
public struct ClangModuleMap: AuxiliaryFileType {
60+
public static let name = "modulemap"
61+
62+
private enum GeneratedModuleMapType: String {
63+
case umbrellaDirectory
64+
case umbrellaHeader
65+
}
66+
67+
public static func computeInputs(
68+
targetName: String,
69+
moduleName: String,
70+
publicHeadersDir: AbsolutePath,
71+
type: PackageLoading.GeneratedModuleMapType
72+
) -> [Node] {
73+
let typeNodes: [Node]
74+
switch type {
75+
case .umbrellaDirectory(let path):
76+
typeNodes = [.virtual(GeneratedModuleMapType.umbrellaDirectory.rawValue), .directory(path)]
77+
case .umbrellaHeader(let path):
78+
typeNodes = [.virtual(GeneratedModuleMapType.umbrellaHeader.rawValue), .file(path)]
79+
}
80+
return [.virtual(Self.name), .virtual(targetName), .virtual(moduleName), .directory(publicHeadersDir)] + typeNodes
81+
}
82+
83+
public static func getFileContents(inputs: [Node]) throws -> String {
84+
guard inputs.count == 5 else {
85+
throw StringError("invalid module map generation task, inputs: \(inputs)")
86+
}
87+
88+
let generator = ModuleMapGenerator(
89+
targetName: inputs[0].extractedVirtualNodeName,
90+
moduleName: inputs[1].extractedVirtualNodeName,
91+
publicHeadersDir: try AbsolutePath(validating: inputs[2].name),
92+
fileSystem: localFileSystem
93+
)
94+
95+
let declaredType = inputs[3].extractedVirtualNodeName
96+
let path = try AbsolutePath(validating: inputs[4].name)
97+
let type: PackageLoading.GeneratedModuleMapType
98+
switch declaredType {
99+
case GeneratedModuleMapType.umbrellaDirectory.rawValue:
100+
type = .umbrellaDirectory(path)
101+
case GeneratedModuleMapType.umbrellaHeader.rawValue:
102+
type = .umbrellaHeader(path)
103+
default:
104+
throw StringError("invalid module map type in generation task: \(declaredType)")
105+
}
106+
107+
return try generator.generateModuleMap(type: type)
108+
}
109+
}
110+
57111
public struct LinkFileList: AuxiliaryFileType {
58112
public static let name = "link-file-list"
59113

@@ -280,6 +334,24 @@ public struct LLBuildManifest {
280334
commands[name] = Command(name: name, tool: tool)
281335
}
282336

337+
public mutating func addWriteClangModuleMapCommand(
338+
targetName: String,
339+
moduleName: String,
340+
publicHeadersDir: AbsolutePath,
341+
type: GeneratedModuleMapType,
342+
outputPath: AbsolutePath
343+
) {
344+
let inputs = WriteAuxiliary.ClangModuleMap.computeInputs(
345+
targetName: targetName,
346+
moduleName: moduleName,
347+
publicHeadersDir: publicHeadersDir,
348+
type: type
349+
)
350+
let tool = WriteAuxiliaryFile(inputs: inputs, outputFilePath: outputPath)
351+
let name = outputPath.pathString
352+
commands[name] = Command(name: name, tool: tool)
353+
}
354+
283355
public mutating func addPkgStructureCmd(
284356
name: String,
285357
inputs: [Node],

Sources/PackageLoading/ModuleMapGenerator.swift

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ public struct ModuleMapGenerator {
173173
return .umbrellaDirectory(publicHeadersDir)
174174
}
175175

176-
/// Generates a module map based of the specified type, throwing an error if anything goes wrong. Any diagnostics are added to the receiver's diagnostics engine.
177-
public func generateModuleMap(type: GeneratedModuleMapType, at path: AbsolutePath) throws {
176+
/// Generates a module map based of the specified type, throwing an error if anything goes wrong.
177+
public func generateModuleMap(type: GeneratedModuleMapType) throws -> String {
178178
var moduleMap = "module \(moduleName) {\n"
179179
switch type {
180180
case .umbrellaHeader(let hdr):
@@ -189,16 +189,7 @@ public struct ModuleMapGenerator {
189189
190190
"""
191191
)
192-
193-
// FIXME: This doesn't belong here.
194-
try fileSystem.createDirectory(path.parentDirectory, recursive: true)
195-
196-
// If the file exists with the identical contents, we don't need to rewrite it.
197-
// Otherwise, compiler will recompile even if nothing else has changed.
198-
if let contents = try? fileSystem.readFileContents(path).validDescription, contents == moduleMap {
199-
return
200-
}
201-
try fileSystem.writeFileContents(path, string: moduleMap)
192+
return moduleMap
202193
}
203194
}
204195

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4034,7 +4034,7 @@ final class BuildPlanTests: XCTestCase {
40344034
XCTAssertMatch(contents, .contains("""
40354035
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
40364036
tool: clang
4037-
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
4037+
inputs: ["<Bar-debug.modules-ready>","<Foo-debug.modules-ready>","\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
40384038
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
40394039
description: "Compiling Bar main.m"
40404040
"""))
@@ -4108,7 +4108,7 @@ final class BuildPlanTests: XCTestCase {
41084108
XCTAssertMatch(contents, .contains("""
41094109
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
41104110
tool: clang
4111-
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
4111+
inputs: ["<Bar-debug.modules-ready>","<Foo-debug.modules-ready>","\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
41124112
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
41134113
description: "Compiling Bar main.m"
41144114
"""))
@@ -4188,7 +4188,7 @@ final class BuildPlanTests: XCTestCase {
41884188
XCTAssertMatch(contents, .contains("""
41894189
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
41904190
tool: clang
4191-
inputs: ["\(buildPath.appending(components: "\(dynamicLibraryPrefix)Foo\(dynamicLibraryExtension)").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
4191+
inputs: ["<Bar-debug.modules-ready>","\(buildPath.appending(components: "\(dynamicLibraryPrefix)Foo\(dynamicLibraryExtension)").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
41924192
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
41934193
description: "Compiling Bar main.m"
41944194
"""))

Tests/PackageLoadingTests/ModuleMapGenerationTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,11 @@ func ModuleMapTester(_ targetName: String, includeDir: String = "include", in fi
190190
let generatedModuleMapPath = AbsolutePath.root.appending(components: "module.modulemap")
191191
observability.topScope.trap {
192192
if let generatedModuleMapType = moduleMapType.generatedModuleMapType {
193-
try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType, at: generatedModuleMapPath)
193+
let contents = try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType)
194+
try fileSystem.writeIfChanged(path: generatedModuleMapPath, string: contents)
194195
}
195196
}
196-
197+
197198
// Invoke the closure to check the results.
198199
let result = ModuleMapResult(diagnostics: observability.diagnostics, path: generatedModuleMapPath, fs: fileSystem)
199200
body(result)

0 commit comments

Comments
 (0)