Skip to content

Revert "Generate Clang module maps during the build" #7046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,7 @@ let package = Package(
.target(
/** The llbuild manifest model */
name: "LLBuildManifest",
dependencies: [
"Basics",
"PackageLoading",
],
dependencies: ["Basics"],
exclude: ["CMakeLists.txt"]
),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,17 @@ public final class ClangTargetBuildDescription {
if case .custom(let path) = clangTarget.moduleMapType {
self.moduleMap = path
}
// If a generated module map is needed, set the path accordingly.
else if clangTarget.moduleMapType.generatedModuleMapType != nil {
self.moduleMap = tempsPath.appending(component: moduleMapFilename)
// If a generated module map is needed, generate one now in our temporary directory.
else if let generatedModuleMapType = clangTarget.moduleMapType.generatedModuleMapType {
let path = tempsPath.appending(component: moduleMapFilename)
let moduleMapGenerator = ModuleMapGenerator(
targetName: clangTarget.name,
moduleName: clangTarget.c99name,
publicHeadersDir: clangTarget.includeDir,
fileSystem: fileSystem
)
try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType, at: path)
self.moduleMap = path
}
// Otherwise there is no module map, and we leave `moduleMap` unset.
}
Expand Down
34 changes: 8 additions & 26 deletions Sources/Build/BuildManifest/LLBuildManifestBuilder+Clang.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,7 @@ extension LLBuildManifestBuilder {
inputs.append(resourcesNode)
}

var modulesReadyInputs = [Node]()

// If the given target needs a generated module map, set up the dependency and required task to write out the module map.
if let type = target.clangTarget.moduleMapType.generatedModuleMapType, let moduleMapPath = target.moduleMap {
modulesReadyInputs.append(.file(moduleMapPath))

self.manifest.addWriteClangModuleMapCommand(
targetName: target.clangTarget.name,
moduleName: target.clangTarget.c99name,
publicHeadersDir: target.clangTarget.includeDir,
type: type,
outputPath: moduleMapPath
)
}

let modulesReady = self.addPhonyCommand(
targetName: target.target.getLLBuildModulesReadyCmdName(config: self.buildConfig),
inputs: modulesReadyInputs
)
inputs.append(modulesReady)

func addStaticTargetInputs(_ target: ResolvedTarget) {
inputs.append(.virtual(target.getLLBuildModulesReadyCmdName(config: self.buildConfig)))

if case .swift(let desc)? = self.plan.targetMap[target], target.type == .library {
inputs.append(file: desc.moduleOutputPath)
}
Expand Down Expand Up @@ -139,9 +116,14 @@ extension LLBuildManifestBuilder {
try addBuildToolPlugins(.clang(target))

// Create a phony node to represent the entire target.
let output = self.addPhonyCommand(
targetName: target.target.getLLBuildTargetName(config: self.buildConfig),
inputs: objectFileNodes
let targetName = target.target.getLLBuildTargetName(config: self.buildConfig)
let output: Node = .virtual(targetName)

self.manifest.addNode(output, toTarget: targetName)
self.manifest.addPhonyCmd(
name: output.name,
inputs: objectFileNodes,
outputs: [output]
)

if self.plan.graph.isInRootPackages(target.target, satisfying: self.buildEnvironment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ extension LLBuildManifestBuilder {
outputs.append(output)
}

return self.addPhonyCommand(
targetName: target.target.getLLBuildResourcesCmdName(config: self.buildConfig),
inputs: outputs
)
let cmdName = target.target.getLLBuildResourcesCmdName(config: self.buildConfig)
self.manifest.addPhonyCmd(name: cmdName, inputs: outputs, outputs: [.virtual(cmdName)])

return .virtual(cmdName)
}
}
13 changes: 8 additions & 5 deletions Sources/Build/BuildManifest/LLBuildManifestBuilder+Swift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ extension LLBuildManifestBuilder {
case .swift(let target)?:
inputs.append(file: target.moduleOutputPath)
case .clang(let target)?:
inputs.append(.virtual(target.target.getLLBuildModulesReadyCmdName(config: self.buildConfig)))
for object in try target.objects {
inputs.append(file: object)
}
Expand Down Expand Up @@ -488,11 +487,15 @@ extension LLBuildManifestBuilder {
/// Adds a top-level phony command that builds the entire target.
private func addTargetCmd(_ target: SwiftTargetBuildDescription, cmdOutputs: [Node]) {
// Create a phony node to represent the entire target.
let targetOutput = self.addPhonyCommand(
targetName: target.target.getLLBuildTargetName(config: self.buildConfig),
inputs: cmdOutputs
let targetName = target.target.getLLBuildTargetName(config: self.buildConfig)
let targetOutput: Node = .virtual(targetName)

self.manifest.addNode(targetOutput, toTarget: targetName)
self.manifest.addPhonyCmd(
name: targetOutput.name,
inputs: cmdOutputs,
outputs: [targetOutput]
)

if self.plan.graph.isInRootPackages(target.target, satisfying: self.buildEnvironment) {
if !target.isTestTarget {
self.addNode(targetOutput, toTarget: .main)
Expand Down
16 changes: 0 additions & 16 deletions Sources/Build/BuildManifest/LLBuildManifestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,6 @@ extension ResolvedTarget {
public func getLLBuildResourcesCmdName(config: String) -> String {
"\(name)-\(config).module-resources"
}

public func getLLBuildModulesReadyCmdName(config: String) -> String {
"\(name)-\(config).modules-ready"
}
}

extension ResolvedProduct {
Expand Down Expand Up @@ -349,18 +345,6 @@ extension LLBuildManifestBuilder {
func destinationPath(forBinaryAt path: AbsolutePath) -> AbsolutePath {
self.plan.buildParameters.buildPath.appending(component: path.basename)
}

/// Adds a phony command and a corresponding virtual node as output.
func addPhonyCommand(targetName: String, inputs: [Node]) -> Node {
let output: Node = .virtual(targetName)
self.manifest.addNode(output, toTarget: targetName)
self.manifest.addPhonyCmd(
name: output.name,
inputs: inputs,
outputs: [output]
)
return output
}
}

extension Sequence where Element: Hashable {
Expand Down
1 change: 0 additions & 1 deletion Sources/LLBuildManifest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ add_library(LLBuildManifest STATIC
Tools.swift)
target_link_libraries(LLBuildManifest PUBLIC
TSCBasic
PackageLoading
Basics)

# NOTE(compnerd) workaround for CMake not setting up include flags yet
Expand Down
72 changes: 0 additions & 72 deletions Sources/LLBuildManifest/LLBuildManifest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import Basics
import Foundation
import PackageLoading

import class TSCBasic.Process

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

public enum WriteAuxiliary {
public static let fileTypes: [AuxiliaryFileType.Type] = [
ClangModuleMap.self,
EntitlementPlist.self,
LinkFileList.self,
SourcesFileList.self,
Expand Down Expand Up @@ -56,58 +54,6 @@ public enum WriteAuxiliary {
}
}

public struct ClangModuleMap: AuxiliaryFileType {
public static let name = "modulemap"

private enum GeneratedModuleMapType: String {
case umbrellaDirectory
case umbrellaHeader
}

public static func computeInputs(
targetName: String,
moduleName: String,
publicHeadersDir: AbsolutePath,
type: PackageLoading.GeneratedModuleMapType
) -> [Node] {
let typeNodes: [Node]
switch type {
case .umbrellaDirectory(let path):
typeNodes = [.virtual(GeneratedModuleMapType.umbrellaDirectory.rawValue), .directory(path)]
case .umbrellaHeader(let path):
typeNodes = [.virtual(GeneratedModuleMapType.umbrellaHeader.rawValue), .file(path)]
}
return [.virtual(Self.name), .virtual(targetName), .virtual(moduleName), .directory(publicHeadersDir)] + typeNodes
}

public static func getFileContents(inputs: [Node]) throws -> String {
guard inputs.count == 5 else {
throw StringError("invalid module map generation task, inputs: \(inputs)")
}

let generator = ModuleMapGenerator(
targetName: inputs[0].extractedVirtualNodeName,
moduleName: inputs[1].extractedVirtualNodeName,
publicHeadersDir: try AbsolutePath(validating: inputs[2].name),
fileSystem: localFileSystem
)

let declaredType = inputs[3].extractedVirtualNodeName
let path = try AbsolutePath(validating: inputs[4].name)
let type: PackageLoading.GeneratedModuleMapType
switch declaredType {
case GeneratedModuleMapType.umbrellaDirectory.rawValue:
type = .umbrellaDirectory(path)
case GeneratedModuleMapType.umbrellaHeader.rawValue:
type = .umbrellaHeader(path)
default:
throw StringError("invalid module map type in generation task: \(declaredType)")
}

return try generator.generateModuleMap(type: type)
}
}

public struct LinkFileList: AuxiliaryFileType {
public static let name = "link-file-list"

Expand Down Expand Up @@ -334,24 +280,6 @@ public struct LLBuildManifest {
commands[name] = Command(name: name, tool: tool)
}

public mutating func addWriteClangModuleMapCommand(
targetName: String,
moduleName: String,
publicHeadersDir: AbsolutePath,
type: GeneratedModuleMapType,
outputPath: AbsolutePath
) {
let inputs = WriteAuxiliary.ClangModuleMap.computeInputs(
targetName: targetName,
moduleName: moduleName,
publicHeadersDir: publicHeadersDir,
type: type
)
let tool = WriteAuxiliaryFile(inputs: inputs, outputFilePath: outputPath)
let name = outputPath.pathString
commands[name] = Command(name: name, tool: tool)
}

public mutating func addPkgStructureCmd(
name: String,
inputs: [Node],
Expand Down
15 changes: 12 additions & 3 deletions Sources/PackageLoading/ModuleMapGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ public struct ModuleMapGenerator {
return .umbrellaDirectory(publicHeadersDir)
}

/// Generates a module map based of the specified type, throwing an error if anything goes wrong.
public func generateModuleMap(type: GeneratedModuleMapType) throws -> String {
/// 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.
public func generateModuleMap(type: GeneratedModuleMapType, at path: AbsolutePath) throws {
var moduleMap = "module \(moduleName) {\n"
switch type {
case .umbrellaHeader(let hdr):
Expand All @@ -189,7 +189,16 @@ public struct ModuleMapGenerator {

"""
)
return moduleMap

// FIXME: This doesn't belong here.
try fileSystem.createDirectory(path.parentDirectory, recursive: true)

// If the file exists with the identical contents, we don't need to rewrite it.
// Otherwise, compiler will recompile even if nothing else has changed.
if let contents = try? fileSystem.readFileContents(path).validDescription, contents == moduleMap {
return
}
try fileSystem.writeFileContents(path, string: moduleMap)
}
}

Expand Down
6 changes: 3 additions & 3 deletions Tests/BuildTests/BuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4034,7 +4034,7 @@ final class BuildPlanTests: XCTestCase {
XCTAssertMatch(contents, .contains("""
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
tool: clang
inputs: ["<Bar-debug.modules-ready>","<Foo-debug.modules-ready>","\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
description: "Compiling Bar main.m"
"""))
Expand Down Expand Up @@ -4108,7 +4108,7 @@ final class BuildPlanTests: XCTestCase {
XCTAssertMatch(contents, .contains("""
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
tool: clang
inputs: ["<Bar-debug.modules-ready>","<Foo-debug.modules-ready>","\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
inputs: ["\(buildPath.appending(components: "Foo.swiftmodule").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
description: "Compiling Bar main.m"
"""))
Expand Down Expand Up @@ -4188,7 +4188,7 @@ final class BuildPlanTests: XCTestCase {
XCTAssertMatch(contents, .contains("""
"\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)":
tool: clang
inputs: ["<Bar-debug.modules-ready>","\(buildPath.appending(components: "\(dynamicLibraryPrefix)Foo\(dynamicLibraryExtension)").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
inputs: ["\(buildPath.appending(components: "\(dynamicLibraryPrefix)Foo\(dynamicLibraryExtension)").escapedPathString)","\(PkgA.appending(components: "Sources", "Bar", "main.m").escapedPathString)"]
outputs: ["\(buildPath.appending(components: "Bar.build", "main.m.o").escapedPathString)"]
description: "Compiling Bar main.m"
"""))
Expand Down
5 changes: 2 additions & 3 deletions Tests/PackageLoadingTests/ModuleMapGenerationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,10 @@ func ModuleMapTester(_ targetName: String, includeDir: String = "include", in fi
let generatedModuleMapPath = AbsolutePath.root.appending(components: "module.modulemap")
observability.topScope.trap {
if let generatedModuleMapType = moduleMapType.generatedModuleMapType {
let contents = try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType)
try fileSystem.writeIfChanged(path: generatedModuleMapPath, string: contents)
try moduleMapGenerator.generateModuleMap(type: generatedModuleMapType, at: generatedModuleMapPath)
}
}

// Invoke the closure to check the results.
let result = ModuleMapResult(diagnostics: observability.diagnostics, path: generatedModuleMapPath, fs: fileSystem)
body(result)
Expand Down