Skip to content

Commit 9c866f6

Browse files
committed
Added functionality to -register-module-dependency flag
rdar://164596852 This flag tells the driver to include the module in the dependency scanning, but not load it. Added test case for the flag.
1 parent b77c2db commit 9c866f6

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,14 @@ public extension Driver {
145145
commandLine.appendFlag(.dependencyScanCacheRemarks)
146146
}
147147

148+
// command-line flag registers a dependency with the dependency scanner
149+
// without causing it to be implicitly imported in compilation tasks
150+
for moduleNameArg in parsedOptions.arguments(for: .registerModuleDependency) {
151+
let moduleName = moduleNameArg.argument.asSingle
152+
commandLine.appendFlag(.importModule)
153+
commandLine.appendFlag(moduleName)
154+
}
155+
148156
if shouldAttemptIncrementalCompilation &&
149157
parsedOptions.contains(.incrementalDependencyScan) {
150158
if let serializationPath = buildRecordInfo?.dependencyScanSerializedResultPath {

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,82 @@ final class ExplicitModuleBuildTests: XCTestCase {
803803
}
804804
}
805805

806+
func testRegisterModuleDependencyFlag() throws {
807+
let (stdlibPath, shimsPath, _, _) = try getDriverArtifactsForScanning()
808+
try withTemporaryDirectory { path in
809+
try localFileSystem.changeCurrentWorkingDirectory(to: path)
810+
let moduleCachePath = path.appending(component: "ModuleCache")
811+
try localFileSystem.createDirectory(moduleCachePath)
812+
let main = path.appending(component: "testRegisterModuleDependency.swift")
813+
// Note: We're NOT importing module E in the source code
814+
try localFileSystem.writeFileContents(main, bytes:
815+
"""
816+
import A;
817+
"""
818+
)
819+
let cHeadersPath: AbsolutePath =
820+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
821+
.appending(component: "CHeaders")
822+
let swiftModuleInterfacesPath: AbsolutePath =
823+
try testInputsPath.appending(component: "ExplicitModuleBuilds")
824+
.appending(component: "Swift")
825+
let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? []
826+
827+
var driver = try Driver(args: ["swiftc",
828+
"-I", cHeadersPath.nativePathString(escaped: true),
829+
"-I", swiftModuleInterfacesPath.nativePathString(escaped: true),
830+
"-I", stdlibPath.nativePathString(escaped: true),
831+
"-I", shimsPath.nativePathString(escaped: true),
832+
"-explicit-module-build",
833+
"-module-cache-path", moduleCachePath.nativePathString(escaped: true),
834+
"-working-directory", path.nativePathString(escaped: true),
835+
"-disable-implicit-concurrency-module-import",
836+
"-disable-implicit-string-processing-module-import",
837+
"-register-module-dependency", "E",
838+
"-register-module-dependency", "G",
839+
"-emit-loaded-module-trace",
840+
main.nativePathString(escaped: true)] + sdkArgumentsForTesting)
841+
let dependencyGraph = try driver.scanModuleDependencies()
842+
let jobs = try driver.planBuild()
843+
// E and G SHOULD be in the dependency graph (registered for scanning)
844+
XCTAssertTrue(dependencyGraph.modules.keys.contains(.swift("E")),
845+
"Module E should be in dependency graph when registered via -register-module-dependency")
846+
XCTAssertTrue(dependencyGraph.modules.keys.contains(.swift("G")),
847+
"Module G should be in dependency graph when registered via -register-module-dependency")
848+
// Checking that registered module compiled
849+
let moduleEJobs = jobs.filter { job in
850+
job.outputs.contains { output in
851+
output.file.basename.contains("E") && output.file.extension == "swiftmodule"
852+
}
853+
}
854+
XCTAssertFalse(moduleEJobs.isEmpty,
855+
"Module E should have a build job when registered via -register-module-dependency")
856+
let moduleGJobs = jobs.filter { job in
857+
job.outputs.contains { output in
858+
output.file.basename.contains("G") && output.file.extension == "swiftmodule"
859+
}
860+
}
861+
XCTAssertFalse(moduleGJobs.isEmpty,
862+
"Module G should have a build job when registered via -register-module-dependency")
863+
// Checking that registered module is not loaded for the main compilation
864+
try driver.run(jobs: jobs)
865+
XCTAssertFalse(driver.diagnosticEngine.hasErrors)
866+
// Checking the output given by the -emit-loaded-module-trace flag
867+
let traceFile = path.appending(component: "testRegisterModuleDependency.trace.json")
868+
XCTAssertTrue(localFileSystem.exists(traceFile), "Module trace file should exist")
869+
let traceData = try localFileSystem.readFileContents(traceFile)
870+
let traceJSON = try traceData.withData { data in
871+
try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
872+
}
873+
let jsonString = String(decoding: traceData.contents, as: UTF8.self)
874+
XCTAssertFalse(jsonString.contains("\"name\":\"E\""),
875+
"Module E should not be loaded in the final compilation since it's not imported")
876+
XCTAssertFalse(jsonString.contains("\"name\":\"G\""),
877+
"Module G should not be loaded in the final compilation since it's not imported")
878+
879+
}
880+
}
881+
806882
// Ensure that (even when not in '-incremental' mode) up-to-date module dependencies
807883
// do not get re-built
808884
func testExplicitModuleBuildIncrementalEndToEnd() throws {

0 commit comments

Comments
 (0)