Skip to content
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
2 changes: 1 addition & 1 deletion Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public struct Driver {
case malformedModuleDependency(String, String)
case missingPCMArguments(String)
case missingModuleDependency(String)
case missingContextHashOnSwiftDependency(String)
case dependencyScanningFailure(Int, String)
case missingExternalDependency(String)

Expand Down Expand Up @@ -88,6 +89,8 @@ public struct Driver {
return "Missing extraPcmArgs to build Clang module: \(moduleName)"
case .missingModuleDependency(let moduleName):
return "Missing Module Dependency Info: \(moduleName)"
case .missingContextHashOnSwiftDependency(let moduleName):
return "Missing Context Hash for Swift dependency: \(moduleName)"
case .dependencyScanningFailure(let code, let error):
return "Module Dependency Scanner returned with non-zero exit status: \(code), \(error)"
case .unableToLoadOutputFileMap(let path):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ public struct SwiftModuleDetails: Codable {
/// Options to the compile command
public var commandLine: [String]? = []

/// The context hash for this module that encodes the producing interface's path,
/// target triple, etc. This field is optional because it is absent for the ModuleInfo
/// corresponding to the main module being built.
public var contextHash: String?

/// To build a PCM to be used by this Swift module, we need to append these
/// arguments to the generic PCM build arguments reported from the dependency
/// graph.
Expand Down
78 changes: 55 additions & 23 deletions Sources/SwiftDriver/Jobs/Planning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ extension Driver {
try resolveVersionedClangDependencies(dependencyGraph: &dependencyGraph)

// Set dependency modules' paths to be saved in the module cache.
try updateDependencyModulesWithModuleCachePath(dependencyGraph: &dependencyGraph)
try resolveDependencyModulePaths(dependencyGraph: &dependencyGraph)

// Update the dependency oracle, adding this new dependency graph to its store
try interModuleDependencyOracle.mergeModules(from: dependencyGraph)
Expand All @@ -536,29 +536,61 @@ extension Driver {
}

/// Update the given inter-module dependency graph to set module paths to be within the module cache,
/// if one is present.
private mutating func updateDependencyModulesWithModuleCachePath(dependencyGraph:
inout InterModuleDependencyGraph)
/// if one is present, and for Swift modules to use the context hash in the file name.
private mutating func resolveDependencyModulePaths(dependencyGraph: inout InterModuleDependencyGraph)
throws {
let moduleCachePath = parsedOptions.getLastArgument(.moduleCachePath)?.asSingle
if moduleCachePath != nil {
for (moduleId, moduleInfo) in dependencyGraph.modules {
// Output path on the main module is determined by the invocation arguments.
guard moduleId.moduleName != dependencyGraph.mainModuleName else {
continue
}
let modulePath = VirtualPath.lookup(moduleInfo.modulePath.path)
// Only update paths on modules which do not already specify a path beyond their module name
// and a file extension.
if modulePath.description == moduleId.moduleName + ".swiftmodule" ||
modulePath.description == moduleId.moduleName + ".pcm" {
// Use VirtualPath to get the OS-specific path separators right.
let modulePathInCache =
try VirtualPath(path: moduleCachePath!)
.appending(component: modulePath.description)
dependencyGraph.modules[moduleId]!.modulePath =
TextualVirtualPath(path: modulePathInCache.intern())
}
// For Swift module dependencies, set the output path to include
// the module's context hash
try resolveSwiftDependencyModuleFileNames(dependencyGraph: &dependencyGraph)

// If a module cache path is specified, update all module dependencies
// to be output into it.
if let moduleCachePath = parsedOptions.getLastArgument(.moduleCachePath)?.asSingle {
try resolveDependencyModulePathsRelativeToModuleCache(dependencyGraph: &dependencyGraph,
moduleCachePath: moduleCachePath)
}
}

/// For Swift module dependencies, set the output path to include the module's context hash
private mutating func resolveSwiftDependencyModuleFileNames(dependencyGraph: inout InterModuleDependencyGraph)
throws {
for (moduleId, moduleInfo) in dependencyGraph.modules {
// Output path on the main module is determined by the invocation arguments.
guard moduleId.moduleName != dependencyGraph.mainModuleName else {
continue
}
guard case .swift(let swiftDetails) = moduleInfo.details else {
continue
}
guard let contextHash = swiftDetails.contextHash else {
throw Driver.Error.missingContextHashOnSwiftDependency(moduleId.moduleName)
}
let plainPath = VirtualPath.lookup(dependencyGraph.modules[moduleId]!.modulePath.path)
let updatedPath = plainPath.parentDirectory.appending(component: "\(plainPath.basenameWithoutExt)-\(contextHash).\(plainPath.extension!)")
dependencyGraph.modules[moduleId]!.modulePath = TextualVirtualPath(path: updatedPath.intern())
}
}

/// Resolve all paths to dependency binary module files to be relative to the module cache path.
private mutating func resolveDependencyModulePathsRelativeToModuleCache(dependencyGraph: inout InterModuleDependencyGraph,
moduleCachePath: String)
throws {
for (moduleId, moduleInfo) in dependencyGraph.modules {
// Output path on the main module is determined by the invocation arguments.
guard moduleId.moduleName != dependencyGraph.mainModuleName else {
continue
}
let modulePath = VirtualPath.lookup(moduleInfo.modulePath.path)
// Only update paths on modules which do not already specify a path beyond their module name
// and a file extension.
if modulePath.description == moduleId.moduleName + ".swiftmodule" ||
modulePath.description == moduleId.moduleName + ".pcm" {
// Use VirtualPath to get the OS-specific path separators right.
let modulePathInCache =
try VirtualPath(path: moduleCachePath)
.appending(component: modulePath.description)
dependencyGraph.modules[moduleId]!.modulePath =
TextualVirtualPath(path: modulePathInCache.intern())
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions Sources/SwiftDriver/SwiftScan/DependencyGraphBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,17 @@ private extension SwiftScan {
try getStringArrayDetail(from: moduleDetailsRef,
using: api.swiftscan_swift_textual_detail_get_extra_pcm_args,
fieldName: "extraPCMArgs")
let contextHash =
try getOptionalStringDetail(from: moduleDetailsRef,
using: api.swiftscan_swift_textual_detail_get_context_hash)
let isFramework = api.swiftscan_swift_textual_detail_get_is_framework(moduleDetailsRef)

return SwiftModuleDetails(moduleInterfacePath: moduleInterfacePath,
compiledModuleCandidates: compiledModuleCandidates,
bridgingHeaderPath: bridgingHeaderPath,
bridgingSourceFiles: bridgingSourceFiles,
commandLine: commandLine,
contextHash: contextHash,
extraPcmArgs: extraPcmArgs,
isFramework: isFramework)
}
Expand Down
Loading