Skip to content

[6.2][SwiftCaching] Don't leak output path in the explicit module map JSON #1885

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

Open
wants to merge 1 commit into
base: release/6.2
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,9 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
// SwiftModuleArtifactInfo
guard moduleId == .swift(dependencyGraph.mainModuleName) else { return }
let dependencyFileContent =
try serializeModuleDependencies(for: moduleId,
swiftDependencyArtifacts: swiftDependencyArtifacts,
clangDependencyArtifacts: clangDependencyArtifacts)
try serializeModuleDependencies(swiftDependencyArtifacts: swiftDependencyArtifacts,
clangDependencyArtifacts: clangDependencyArtifacts,
cachingEnabled: cas != nil)
if let cas = self.cas {
// When using a CAS, write JSON into CAS and pass the ID on command-line.
let casID = try cas.store(data: dependencyFileContent)
Expand Down Expand Up @@ -534,9 +534,9 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
"-Xcc", "-fno-implicit-module-maps")

let dependencyFileContent =
try serializeModuleDependencies(for: mainModuleId,
swiftDependencyArtifacts: swiftDependencyArtifacts,
clangDependencyArtifacts: clangDependencyArtifacts)
try serializeModuleDependencies(swiftDependencyArtifacts: swiftDependencyArtifacts,
clangDependencyArtifacts: clangDependencyArtifacts,
cachingEnabled: false)

let dependencyFile =
try VirtualPath.createUniqueTemporaryFileWithKnownContents(.init(validating: "\(mainModuleId.moduleName)-dependencies.json"),
Expand All @@ -548,15 +548,43 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
}

/// Serialize the output file artifacts for a given module in JSON format.
private func serializeModuleDependencies(for moduleId: ModuleDependencyId,
swiftDependencyArtifacts: Set<SwiftModuleArtifactInfo>,
clangDependencyArtifacts: Set<ClangModuleArtifactInfo>
private func serializeModuleDependencies(swiftDependencyArtifacts: Set<SwiftModuleArtifactInfo>,
clangDependencyArtifacts: Set<ClangModuleArtifactInfo>,
cachingEnabled: Bool
) throws -> Data {
// Helper function to abstract the path.
func abstractPath(_ module: String, suffix: String) throws -> TextualVirtualPath {
let path = try VirtualPath(path: module + suffix)
return TextualVirtualPath(path: path.intern())
}
// The module dependency map in CAS needs to be stable.
// Sort the dependencies by name.
// For caching build, updated the dependency info to exclude paths that are compiler outputs from the mapping.
// Use abstract names and paths because caching build loads modules directly from CAS.
let allDependencyArtifacts: [ModuleDependencyArtifactInfo] =
swiftDependencyArtifacts.sorted().map {ModuleDependencyArtifactInfo.swift($0)} +
clangDependencyArtifacts.sorted().map {ModuleDependencyArtifactInfo.clang($0)}
try swiftDependencyArtifacts.sorted().map { info in
if !cachingEnabled {
return ModuleDependencyArtifactInfo.swift(info)
}
let updatedInfo = try SwiftModuleArtifactInfo(name: info.moduleName,
modulePath: abstractPath(info.moduleName, suffix: ".swiftmodule"),
docPath: nil,
sourceInfoPath: nil,
headerDependencies: info.prebuiltHeaderDependencyPaths,
isFramework: info.isFramework,
moduleCacheKey: info.moduleCacheKey)
return ModuleDependencyArtifactInfo.swift(updatedInfo)
} +
clangDependencyArtifacts.sorted().map { info in
if !cachingEnabled {
return ModuleDependencyArtifactInfo.clang(info)
}
let updatedInfo = try ClangModuleArtifactInfo(name: info.moduleName,
modulePath: abstractPath(info.moduleName, suffix: ".pcm"),
moduleMapPath: info.clangModuleMapPath,
moduleCacheKey: info.clangModuleCacheKey,
isBridgingHeaderDependency: info.isBridgingHeaderDependency)
return ModuleDependencyArtifactInfo.clang(updatedInfo)
}
let encoder = JSONEncoder()
// Use sorted key to ensure the order of the keys is stable.
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
Expand Down