Skip to content

Commit 47eabce

Browse files
authored
Merge pull request #1979 from ahoppen/multi-file-indexing
Allow multiple files to be indexed in a single invocation using the `-index-file` driver mode
2 parents bff22ba + d8f9756 commit 47eabce

File tree

3 files changed

+52
-18
lines changed

3 files changed

+52
-18
lines changed

Sources/SwiftDriver/Jobs/CompileJob.swift

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ extension Driver {
107107
/// corresponding primary set of outputs and, if not identical, the output
108108
/// paths to record in the index data (empty otherwise).
109109
mutating func addCompileInputs(primaryInputs: [TypedVirtualPath],
110-
indexFilePath: TypedVirtualPath?,
110+
indexFilePaths: [TypedVirtualPath],
111111
inputs: inout [TypedVirtualPath],
112112
inputOutputMap: inout [TypedVirtualPath: [TypedVirtualPath]],
113113
outputType: FileType?,
@@ -149,11 +149,11 @@ extension Driver {
149149
assert(!primaryInputs.isEmpty)
150150
usesPrimaryFileInputs = true
151151
primaryInputFiles = primaryInputs
152-
} else if let path = indexFilePath {
152+
} else if !indexFilePaths.isEmpty {
153153
// If -index-file is used, we perform a single compile but pass the
154154
// -index-file-path as a primary input file.
155155
usesPrimaryFileInputs = true
156-
primaryInputFiles = [path]
156+
primaryInputFiles = indexFilePaths
157157
} else {
158158
usesPrimaryFileInputs = false
159159
primaryInputFiles = []
@@ -244,17 +244,14 @@ extension Driver {
244244
commandLine.appendFlag("-frontend")
245245
addCompileModeOption(outputType: outputType, commandLine: &commandLine)
246246

247-
let indexFilePath: TypedVirtualPath?
248-
if let indexFileArg = parsedOptions.getLastArgument(.indexFilePath)?.asSingle {
249-
let path = try VirtualPath(path: indexFileArg)
250-
indexFilePath = inputFiles.first { $0.file == path }
251-
} else {
252-
indexFilePath = nil
253-
}
247+
let indexFileArgs = try Set(
248+
parsedOptions.arguments(for: .indexFilePath).map { try VirtualPath(path: $0.argument.asSingle) }
249+
)
250+
let indexFilePaths = inputFiles.filter { indexFileArgs.contains($0.file) }
254251

255252
let (primaryOutputs, primaryIndexUnitOutputs) =
256253
try addCompileInputs(primaryInputs: primaryInputs,
257-
indexFilePath: indexFilePath,
254+
indexFilePaths: indexFilePaths,
258255
inputs: &inputs,
259256
inputOutputMap: &inputOutputMap,
260257
outputType: outputType,
@@ -282,7 +279,7 @@ extension Driver {
282279
moduleOutputInfo: self.moduleOutputInfo,
283280
moduleOutputPaths: self.moduleOutputPaths,
284281
includeModuleTracePath: emitModuleTrace,
285-
indexFilePath: indexFilePath)
282+
indexFilePaths: indexFilePaths)
286283

287284
// Forward migrator flags.
288285
try commandLine.appendLast(.apiDiffDataFile, from: &parsedOptions)

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ extension Driver {
665665
moduleOutputInfo: ModuleOutputInfo,
666666
moduleOutputPaths: SupplementalModuleTargetOutputPaths,
667667
includeModuleTracePath: Bool,
668-
indexFilePath: TypedVirtualPath?) throws -> [TypedVirtualPath] {
668+
indexFilePaths: [TypedVirtualPath]) throws -> [TypedVirtualPath] {
669669
var flaggedInputOutputPairs: [(flag: String, input: TypedVirtualPath?, output: TypedVirtualPath)] = []
670670

671671
/// Add output of a particular type, if needed.
@@ -879,7 +879,10 @@ extension Driver {
879879
}
880880
// To match the legacy driver behavior, make sure we add an entry for the
881881
// file under indexing and the primary output file path.
882-
if let indexFilePath = indexFilePath, let idxOutput = inputOutputMap[indexFilePath]?.first {
882+
for indexFilePath in indexFilePaths {
883+
guard let idxOutput = inputOutputMap[indexFilePath]?.first else {
884+
continue
885+
}
883886
entries[indexFilePath.fileHandle] = [.indexData: idxOutput.fileHandle]
884887
}
885888
let outputFileMap = OutputFileMap(entries: entries)

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,40 @@ final class SwiftDriverTests: XCTestCase {
484484
}
485485
}
486486

487+
func testIndexMultipleFilesInSingleCommandLineInvocation() throws {
488+
try withTemporaryFile { outputFileMap in
489+
let outputMapContents = ByteString("""
490+
{
491+
"first.swift": {
492+
"index-unit-output-path": "first.o"
493+
},
494+
"second.swift": {
495+
"index-unit-output-path": "second.o"
496+
}
497+
}
498+
""".utf8)
499+
try localFileSystem.writeFileContents(outputFileMap.path, bytes: outputMapContents)
500+
try assertNoDriverDiagnostics(args:
501+
"swiftc", "-index-file",
502+
"first.swift", "second.swift", "third.swift",
503+
"-index-file-path", "first.swift",
504+
"-index-file-path", "second.swift",
505+
"-index-store-path", "/tmp/idx",
506+
"-output-file-map", outputFileMap.path.pathString
507+
) { driver in
508+
let jobs = try driver.planBuild()
509+
XCTAssertEqual(jobs.count, 1)
510+
let commandLine = jobs[0].commandLine
511+
XCTAssertJobInvocationMatches(jobs[0], .flag("-index-unit-output-path"), .path(.relative(try RelativePath(validating: "first.o"))))
512+
XCTAssertJobInvocationMatches(jobs[0], .flag("-index-unit-output-path"), .path(.relative(try RelativePath(validating: "second.o"))))
513+
XCTAssertEqual(commandLine.filter { $0 == .flag("-index-unit-output-path") }.count, 2)
514+
XCTAssertJobInvocationMatches(jobs[0], .flag("-primary-file"), .path(.relative(try RelativePath(validating: "first.swift"))))
515+
XCTAssertJobInvocationMatches(jobs[0], .flag("-primary-file"), .path(.relative(try RelativePath(validating: "second.swift"))))
516+
XCTAssertEqual(commandLine.filter { $0 == .flag("-primary-file") }.count, 2)
517+
}
518+
}
519+
}
520+
487521
func testMultiThreadingOutputs() throws {
488522
try assertDriverDiagnostics(args: "swiftc", "-c", "foo.swift", "bar.swift", "-o", "bar.ll", "-o", "foo.ll", "-num-threads", "2", "-whole-module-optimization") {
489523
$1.expect(.error("cannot specify -o when generating multiple output files"))
@@ -4649,7 +4683,7 @@ final class SwiftDriverTests: XCTestCase {
46494683
// in addition to the usual flag.
46504684
try withTemporaryDirectory { path in
46514685
let completePath: AbsolutePath = path.appending(component: "profile.profdata")
4652-
4686+
46534687
try localFileSystem.writeFileContents(completePath, bytes: .init())
46544688
var driver = try Driver(args: ["swiftc", "foo.swift",
46554689
"-working-directory", path.pathString,
@@ -7437,7 +7471,7 @@ final class SwiftDriverTests: XCTestCase {
74377471
XCTAssertEqual(try getLibraryLevel(flags), .spi)
74387472
}
74397473
try withTemporaryFile { file in
7440-
try localFileSystem.writeFileContents(file.path, bytes:
7474+
try localFileSystem.writeFileContents(file.path, bytes:
74417475
"// swift-module-flags: -target arm64e-apple-macos12.0"
74427476
)
74437477
let flags = try getAllModuleFlags(VirtualPath.absolute(file.path))
@@ -8253,7 +8287,7 @@ final class SwiftDriverTests: XCTestCase {
82538287
XCTAssertTrue(plannedJobs[0].commandLine.contains(.flag("-load-pass-plugin=/path/to/plugin")))
82548288
#endif
82558289
}
8256-
8290+
82578291
func testSupplementaryOutputFileMapUsage() throws {
82588292
// Ensure filenames are escaped properly when using a supplementary output file map
82598293
try withTemporaryDirectory { path in
@@ -8284,7 +8318,7 @@ final class SwiftDriverTests: XCTestCase {
82848318
struct D {}
82858319
"""
82868320
)
8287-
8321+
82888322
let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? []
82898323
let invocationArguments = ["swiftc",
82908324
"-parse-as-library",

0 commit comments

Comments
 (0)