Skip to content

Commit 0876a15

Browse files
committed
Add a multiArg -scanner-prefix-map-paths option and fix multiArg option parsing
1 parent def5462 commit 0876a15

File tree

10 files changed

+75
-26
lines changed

10 files changed

+75
-26
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ public struct Driver {
296296
return ($0.key, $0.value)
297297
}
298298
do {
299-
guard isFrontendArgSupported(.scannerPrefixMap) else {
299+
guard isFrontendArgSupported(.cacheReplayPrefixMap) else {
300300
return []
301301
}
302302
if let sdkMapping = scannerPrefixMapSDK,
@@ -4007,14 +4007,20 @@ extension Driver {
40074007

40084008
static func computeScanningPrefixMapper(_ parsedOptions: inout ParsedOptions) throws -> [AbsolutePath: AbsolutePath] {
40094009
var mapping: [AbsolutePath: AbsolutePath] = [:]
4010-
for opt in parsedOptions.arguments(for: .scannerPrefixMap) {
4011-
let pluginArg = opt.argument.asSingle.split(separator: "=", maxSplits: 1)
4012-
if pluginArg.count != 2 {
4013-
throw Error.invalidArgumentValue(Option.scannerPrefixMap.spelling, opt.argument.asSingle)
4010+
for opt in parsedOptions.arguments(for: .scannerPrefixMapPaths, .scannerPrefixMap) {
4011+
if opt.option == .scannerPrefixMapPaths {
4012+
let key = try AbsolutePath(validating: opt.argument.asMultiple[0])
4013+
let value = try AbsolutePath(validating: opt.argument.asMultiple[1])
4014+
mapping[key] = value
4015+
} else {
4016+
let pluginArg = opt.argument.asSingle.split(separator: "=", maxSplits: 1)
4017+
if pluginArg.count != 2 {
4018+
throw Error.invalidArgumentValue(Option.scannerPrefixMap.spelling, opt.argument.asSingle)
4019+
}
4020+
let key = try AbsolutePath(validating: String(pluginArg[0]))
4021+
let value = try AbsolutePath(validating: String(pluginArg[1]))
4022+
mapping[key] = value
40144023
}
4015-
let key = try AbsolutePath(validating: String(pluginArg[0]))
4016-
let value = try AbsolutePath(validating: String(pluginArg[1]))
4017-
mapping[key] = value
40184024
}
40194025
return mapping
40204026
}

Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
6262
/// Does this compile support `.explicitInterfaceModuleBuild`
6363
private let supportsExplicitInterfaceBuild: Bool
6464

65+
/// status of the scanner prefix mapping option supported by the frontend
66+
private let supportsScannerPrefixMapPaths: Bool
67+
6568
/// Cached command-line additions for all main module compile jobs
6669
private struct ResolvedModuleDependenciesCommandLineComponents {
6770
let inputs: [TypedVirtualPath]
@@ -88,14 +91,16 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
8891
supportsExplicitInterfaceBuild: Bool = false,
8992
cas: SwiftScanCAS? = nil,
9093
prefixMap: [(AbsolutePath, AbsolutePath)] = [],
91-
supportsBridgingHeaderPCHCommand: Bool = false) throws {
94+
supportsBridgingHeaderPCHCommand: Bool = false,
95+
supportsScannerPrefixMapPaths: Bool = false) throws {
9296
self.dependencyGraph = dependencyGraph
9397
self.toolchain = toolchain
9498
self.integratedDriver = integratedDriver
9599
self.mainModuleName = dependencyGraph.mainModuleName
96100
self.reachabilityMap = try dependencyGraph.computeTransitiveClosure()
97101
self.supportsExplicitInterfaceBuild = supportsExplicitInterfaceBuild
98102
self.supportsBridgingHeaderPCHCommand = supportsBridgingHeaderPCHCommand
103+
self.supportsScannerPrefixMapPaths = supportsScannerPrefixMapPaths
99104
self.cas = cas
100105
self.prefixMap = prefixMap
101106
let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName)
@@ -216,7 +221,12 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
216221
// Add prefix mapping. The option is cache invariant so it can be added without affecting cache key.
217222
for (key, value) in prefixMap {
218223
commandLine.appendFlag("-cache-replay-prefix-map")
219-
commandLine.appendFlag(value.pathString + "=" + key.pathString)
224+
if supportsScannerPrefixMapPaths {
225+
commandLine.appendFlag(value.pathString)
226+
commandLine.appendFlag(key.pathString)
227+
} else {
228+
commandLine.appendFlag(value.pathString + "=" + key.pathString)
229+
}
220230
}
221231

222232
jobs.append(Job(
@@ -277,7 +287,12 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
277287
// Add prefix mapping. The option is cache invariant so it can be added without affecting cache key.
278288
for (key, value) in prefixMap {
279289
commandLine.appendFlag("-cache-replay-prefix-map")
280-
commandLine.appendFlag(value.pathString + "=" + key.pathString)
290+
if supportsScannerPrefixMapPaths {
291+
commandLine.appendFlag(value.pathString)
292+
commandLine.appendFlag(key.pathString)
293+
} else {
294+
commandLine.appendFlag(value.pathString + "=" + key.pathString)
295+
}
281296
}
282297

283298
jobs.append(Job(

Sources/SwiftDriver/ExplicitModuleBuilds/ModuleDependencyScanning.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,14 @@ public extension Driver {
125125
commandLine.appendFlag(.scannerModuleValidation)
126126
}
127127

128-
if isFrontendArgSupported(.scannerPrefixMap) {
129-
// construct `-scanner-prefix-mapper` for scanner.
128+
if isFrontendArgSupported(.scannerPrefixMapPaths) {
129+
// construct `-scanner-prefix-map-paths` for scanner.
130+
for (key, value) in prefixMapping {
131+
commandLine.appendFlag(.scannerPrefixMapPaths)
132+
commandLine.appendFlag(key.pathString)
133+
commandLine.appendFlag(value.pathString)
134+
}
135+
} else if isFrontendArgSupported(.scannerPrefixMap) {
130136
for (key, value) in prefixMapping {
131137
commandLine.appendFlag(.scannerPrefixMap)
132138
commandLine.appendFlag(key.pathString + "=" + value.pathString)

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,10 +1031,15 @@ extension Driver {
10311031
}
10321032

10331033
public mutating func addCacheReplayMapping(to commandLine: inout [Job.ArgTemplate]) {
1034-
if isCachingEnabled && isFrontendArgSupported(.scannerPrefixMap) {
1034+
if isCachingEnabled && isFrontendArgSupported(.cacheReplayPrefixMap) {
10351035
for (key, value) in prefixMapping {
10361036
commandLine.appendFlag("-cache-replay-prefix-map")
1037-
commandLine.appendFlag(value.pathString + "=" + key.pathString)
1037+
if isFrontendArgSupported(.scannerPrefixMapPaths) {
1038+
commandLine.appendFlag(value.pathString)
1039+
commandLine.appendFlag(key.pathString)
1040+
} else {
1041+
commandLine.appendFlag(value.pathString + "=" + key.pathString)
1042+
}
10381043
}
10391044
}
10401045
}

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ extension Driver {
122122
cas: cas,
123123
prefixMap: prefixMapping,
124124
supportsBridgingHeaderPCHCommand:
125-
interModuleDependencyOracle.supportsBridgingHeaderPCHCommand)
125+
interModuleDependencyOracle.supportsBridgingHeaderPCHCommand,
126+
supportsScannerPrefixMapPaths:
127+
isFrontendArgSupported(.scannerPrefixMapPaths))
126128
} else {
127129
return nil
128130
}

Sources/SwiftOptions/OptionParsing.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,8 @@ extension OptionTable {
182182
throw OptionParseError.missingArgument(
183183
index: index - 1, argument: argument)
184184
}
185-
parsedOptions.addOption(option, argument: .multiple(Array()))
186-
arguments[index..<endIdx].map { String($0) }.forEach { parsedOptions.addInput($0) }
185+
parsedOptions.addOption(option, argument: .multiple(arguments[index..<endIdx].map { String($0) }))
187186
index = endIdx
188-
189187
}
190188
}
191189
parsedOptions.buildIndex()

Sources/SwiftOptions/Options.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ extension Option {
7070
public static let bypassResilience: Option = Option("-bypass-resilience-checks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Ignore all checks for module resilience.")
7171
public static let cacheCompileJob: Option = Option("-cache-compile-job", .flag, attributes: [.frontend], helpText: "Enable compiler caching")
7272
public static let cacheDisableReplay: Option = Option("-cache-disable-replay", .flag, attributes: [.frontend, .cacheInvariant], helpText: "Skip loading the compilation result from cache")
73-
public static let cacheReplayPrefixMap: Option = Option("-cache-replay-prefix-map", .separate, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "<prefix=replacement>", helpText: "Remap paths when replaying outputs from cache")
73+
public static let cacheReplayPrefixMap: Option = Option("-cache-replay-prefix-map", .multiArg, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "<prefix> <replacement>", helpText: "Remap paths when replaying outputs from cache", numArgs: 2)
7474
public static let candidateModuleFile: Option = Option("-candidate-module-file", .separate, attributes: [.helpHidden, .frontend, .noDriver], metaVar: "<path>", helpText: "Specify Swift module may be ready to use for an interface")
7575
public static let casBackendMode: Option = Option("-cas-backend-mode=", .joined, attributes: [.frontend, .noDriver], metaVar: "native|casid|verify", helpText: "CASBackendMode for output kind")
7676
public static let casBackend: Option = Option("-cas-backend", .flag, attributes: [.frontend, .noDriver], helpText: "Enable using CASBackend for object file output")
@@ -833,7 +833,8 @@ extension Option {
833833
public static let scannerOutputDir: Option = Option("-scanner-output-dir", .separate, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Directory for generated files from swift dependency scanner")
834834
public static let scannerPrefixMapSdk: Option = Option("-scanner-prefix-map-sdk", .separate, attributes: [], metaVar: "<path>", helpText: "Remap paths within SDK reported by dependency scanner")
835835
public static let scannerPrefixMapToolchain: Option = Option("-scanner-prefix-map-toolchain", .separate, attributes: [], metaVar: "<path>", helpText: "Remap paths within toolchain directory reported by dependency scanner")
836-
public static let scannerPrefixMap: Option = Option("-scanner-prefix-map", .separate, attributes: [.frontend], metaVar: "<prefix=replacement>", helpText: "Remap paths reported by dependency scanner")
836+
public static let scannerPrefixMap: Option = Option("-scanner-prefix-map", .separate, attributes: [], metaVar: "<prefix=replacement>", helpText: "Remap paths reported by dependency scanner")
837+
public static let scannerPrefixMapPaths: Option = Option("-scanner-prefix-map-paths", .multiArg, attributes: [.frontend], metaVar: "<prefix> <replacement>", helpText: "Remap paths reported by dependency scanner", numArgs: 2)
837838
public static let sdkModuleCachePath: Option = Option("-sdk-module-cache-path", .separate, attributes: [.frontend, .doesNotAffectIncrementalBuild, .argumentIsPath], helpText: "Specifies the module cache path for explicitly-built SDK modules")
838839
public static let sdk: Option = Option("-sdk", .separate, attributes: [.frontend, .synthesizeInterface, .argumentIsPath], metaVar: "<sdk>", helpText: "Compile against <sdk>")
839840
public static let serializeBreakingChangesPath: Option = Option("-serialize-breaking-changes-path", .separate, attributes: [.noInteractive, .argumentIsPath], metaVar: "<path>", helpText: "Serialize breaking changes found by the API digester to <path>")
@@ -1801,6 +1802,7 @@ extension Option {
18011802
Option.scannerPrefixMapSdk,
18021803
Option.scannerPrefixMapToolchain,
18031804
Option.scannerPrefixMap,
1805+
Option.scannerPrefixMapPaths,
18041806
Option.sdkModuleCachePath,
18051807
Option.sdk,
18061808
Option.serializeBreakingChangesPath,

Tests/SwiftDriverTests/CachingBuildTests.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,16 +895,17 @@ final class CachingBuildTests: XCTestCase {
895895
main.nativePathString(escaped: true)] + sdkArgumentsForTesting,
896896
env: env,
897897
interModuleDependencyOracle: dependencyOracle)
898-
guard driver.isFrontendArgSupported(.scannerPrefixMap) else {
898+
guard driver.isFrontendArgSupported(.scannerPrefixMapPaths) else {
899899
throw XCTSkip("frontend doesn't support prefix map")
900900
}
901901
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
902902
try dependencyOracle.verifyOrCreateScannerInstance(swiftScanLibPath: scanLibPath)
903903
let resolver = try ArgsResolver(fileSystem: localFileSystem)
904904
let scannerCommand = try driver.dependencyScannerInvocationCommand().1.map { try resolver.resolve($0) }
905905

906-
XCTAssertTrue(scannerCommand.contains("-scanner-prefix-map"))
907-
XCTAssertTrue(scannerCommand.contains(try testInputsPath.description + "=/^src"))
906+
XCTAssertTrue(scannerCommand.contains("-scanner-prefix-map-paths"))
907+
XCTAssertTrue(scannerCommand.contains(try testInputsPath.description))
908+
XCTAssertTrue(scannerCommand.contains("/^src"))
908909

909910
let jobs = try driver.planBuild()
910911
for job in jobs {

Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ final class ExplicitModuleBuildTests: XCTestCase {
174174
from: ModuleDependenciesInputs.fastDependencyScannerOutput.data(using: .utf8)!)
175175
var explicitDependencyBuildPlanner =
176176
try ExplicitDependencyBuildPlanner(dependencyGraph: moduleDependencyGraph,
177-
toolchain: driver.toolchain)
177+
toolchain: driver.toolchain,
178+
supportsScannerPrefixMapPaths: driver.isFrontendArgSupported(.scannerPrefixMapPaths))
178179
let modulePrebuildJobs =
179180
try explicitDependencyBuildPlanner.generateExplicitModuleDependenciesBuildJobs()
180181
XCTAssertEqual(modulePrebuildJobs.count, 4)

Tests/SwiftOptionsTests/OptionParsingTests.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,21 @@ final class SwiftDriverTests: XCTestCase {
4242
let three = Option("-three", .multiArg, attributes: [], numArgs: 3)
4343
options.addNewOption(two)
4444
options.addNewOption(three)
45-
let results = try options.parse(["-two", "1", "2", "-three", "1", "2", "3", "-two", "2", "3"], for: .batch)
45+
var results = try options.parse(["-two", "1", "2", "-three", "1", "2", "3", "-two", "2", "3"], for: .batch)
4646
XCTAssertEqual(results.description, "-two 1 2 -three 1 2 3 -two 2 3")
47+
// test that the arguments are assigned to their corresponding flag correctly
48+
XCTAssertEqual(results.allInputs.count, 0)
49+
let twoOpts = results.arguments(for: two)
50+
XCTAssertEqual(twoOpts.count, 2)
51+
XCTAssertEqual(twoOpts[0].argument.asMultiple[0], "1")
52+
XCTAssertEqual(twoOpts[0].argument.asMultiple[1], "2")
53+
XCTAssertEqual(twoOpts[1].argument.asMultiple[0], "2")
54+
XCTAssertEqual(twoOpts[1].argument.asMultiple[1], "3")
55+
let threeOpts = results.arguments(for: three)
56+
XCTAssertEqual(threeOpts.count, 1)
57+
XCTAssertEqual(threeOpts[0].argument.asMultiple[0], "1")
58+
XCTAssertEqual(threeOpts[0].argument.asMultiple[1], "2")
59+
XCTAssertEqual(threeOpts[0].argument.asMultiple[2], "3")
4760
// Check not enough arguments are passed.
4861
XCTAssertThrowsError(try options.parse(["-two", "1"], for: .batch)) { error in
4962
XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-two"))

0 commit comments

Comments
 (0)