Skip to content

Add -scanner-prefix-map-paths option and fix multiArg option parsing #1949

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: main
Choose a base branch
from
Open
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
22 changes: 14 additions & 8 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public struct Driver {
return ($0.key, $0.value)
}
do {
guard isFrontendArgSupported(.scannerPrefixMap) else {
guard isFrontendArgSupported(.scannerPrefixMapPaths) else {
return []
}
if let sdkMapping = scannerPrefixMapSDK,
Expand Down Expand Up @@ -4007,14 +4007,20 @@ extension Driver {

static func computeScanningPrefixMapper(_ parsedOptions: inout ParsedOptions) throws -> [AbsolutePath: AbsolutePath] {
var mapping: [AbsolutePath: AbsolutePath] = [:]
for opt in parsedOptions.arguments(for: .scannerPrefixMap) {
let pluginArg = opt.argument.asSingle.split(separator: "=", maxSplits: 1)
if pluginArg.count != 2 {
throw Error.invalidArgumentValue(Option.scannerPrefixMap.spelling, opt.argument.asSingle)
for opt in parsedOptions.arguments(for: .scannerPrefixMapPaths, .scannerPrefixMap) {
if opt.option == .scannerPrefixMapPaths {
let key = try AbsolutePath(validating: opt.argument.asMultiple[0])
let value = try AbsolutePath(validating: opt.argument.asMultiple[1])
mapping[key] = value
} else {
let pluginArg = opt.argument.asSingle.split(separator: "=", maxSplits: 1)
if pluginArg.count != 2 {
throw Error.invalidArgumentValue(Option.scannerPrefixMap.spelling, opt.argument.asSingle)
}
let key = try AbsolutePath(validating: String(pluginArg[0]))
let value = try AbsolutePath(validating: String(pluginArg[1]))
mapping[key] = value
}
let key = try AbsolutePath(validating: String(pluginArg[0]))
let value = try AbsolutePath(validating: String(pluginArg[1]))
mapping[key] = value
}
return mapping
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
// Add prefix mapping. The option is cache invariant so it can be added without affecting cache key.
for (key, value) in prefixMap {
commandLine.appendFlag("-cache-replay-prefix-map")
commandLine.appendFlag(value.pathString + "=" + key.pathString)
commandLine.appendFlag(value.pathString)
commandLine.appendFlag(key.pathString)
}

jobs.append(Job(
Expand Down Expand Up @@ -277,7 +278,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
// Add prefix mapping. The option is cache invariant so it can be added without affecting cache key.
for (key, value) in prefixMap {
commandLine.appendFlag("-cache-replay-prefix-map")
commandLine.appendFlag(value.pathString + "=" + key.pathString)
commandLine.appendFlag(value.pathString)
commandLine.appendFlag(key.pathString)
}

jobs.append(Job(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,12 @@ public extension Driver {
commandLine.appendFlag(.scannerModuleValidation)
}

if isFrontendArgSupported(.scannerPrefixMap) {
// construct `-scanner-prefix-mapper` for scanner.
if isFrontendArgSupported(.scannerPrefixMapPaths) {
// construct `-scanner-prefix-map-paths` for scanner.
for (key, value) in prefixMapping {
commandLine.appendFlag(.scannerPrefixMap)
commandLine.appendFlag(key.pathString + "=" + value.pathString)
commandLine.appendFlag(.scannerPrefixMapPaths)
commandLine.appendFlag(key.pathString)
commandLine.appendFlag(value.pathString)
}
}

Expand Down
5 changes: 3 additions & 2 deletions Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1031,10 +1031,11 @@ extension Driver {
}

public mutating func addCacheReplayMapping(to commandLine: inout [Job.ArgTemplate]) {
if isCachingEnabled && isFrontendArgSupported(.scannerPrefixMap) {
if isCachingEnabled && isFrontendArgSupported(.scannerPrefixMapPaths) {
for (key, value) in prefixMapping {
commandLine.appendFlag("-cache-replay-prefix-map")
commandLine.appendFlag(value.pathString + "=" + key.pathString)
commandLine.appendFlag(value.pathString)
commandLine.appendFlag(key.pathString)
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions Sources/SwiftOptions/OptionParsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,8 @@ extension OptionTable {
throw OptionParseError.missingArgument(
index: index - 1, argument: argument)
}
parsedOptions.addOption(option, argument: .multiple(Array()))
arguments[index..<endIdx].map { String($0) }.forEach { parsedOptions.addInput($0) }
parsedOptions.addOption(option, argument: .multiple(arguments[index..<endIdx].map { String($0) }))
index = endIdx

}
}
parsedOptions.buildIndex()
Expand Down
6 changes: 4 additions & 2 deletions Sources/SwiftOptions/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ extension Option {
public static let bypassResilience: Option = Option("-bypass-resilience-checks", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Ignore all checks for module resilience.")
public static let cacheCompileJob: Option = Option("-cache-compile-job", .flag, attributes: [.frontend], helpText: "Enable compiler caching")
public static let cacheDisableReplay: Option = Option("-cache-disable-replay", .flag, attributes: [.frontend, .cacheInvariant], helpText: "Skip loading the compilation result from cache")
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")
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)
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")
public static let casBackendMode: Option = Option("-cas-backend-mode=", .joined, attributes: [.frontend, .noDriver], metaVar: "native|casid|verify", helpText: "CASBackendMode for output kind")
public static let casBackend: Option = Option("-cas-backend", .flag, attributes: [.frontend, .noDriver], helpText: "Enable using CASBackend for object file output")
Expand Down Expand Up @@ -833,7 +833,8 @@ extension Option {
public static let scannerOutputDir: Option = Option("-scanner-output-dir", .separate, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Directory for generated files from swift dependency scanner")
public static let scannerPrefixMapSdk: Option = Option("-scanner-prefix-map-sdk", .separate, attributes: [], metaVar: "<path>", helpText: "Remap paths within SDK reported by dependency scanner")
public static let scannerPrefixMapToolchain: Option = Option("-scanner-prefix-map-toolchain", .separate, attributes: [], metaVar: "<path>", helpText: "Remap paths within toolchain directory reported by dependency scanner")
public static let scannerPrefixMap: Option = Option("-scanner-prefix-map", .separate, attributes: [.frontend], metaVar: "<prefix=replacement>", helpText: "Remap paths reported by dependency scanner")
public static let scannerPrefixMap: Option = Option("-scanner-prefix-map", .separate, attributes: [], metaVar: "<prefix=replacement>", helpText: "Remap paths reported by dependency scanner")
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)
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")
public static let sdk: Option = Option("-sdk", .separate, attributes: [.frontend, .synthesizeInterface, .argumentIsPath], metaVar: "<sdk>", helpText: "Compile against <sdk>")
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>")
Expand Down Expand Up @@ -1801,6 +1802,7 @@ extension Option {
Option.scannerPrefixMapSdk,
Option.scannerPrefixMapToolchain,
Option.scannerPrefixMap,
Option.scannerPrefixMapPaths,
Option.sdkModuleCachePath,
Option.sdk,
Option.serializeBreakingChangesPath,
Expand Down
7 changes: 4 additions & 3 deletions Tests/SwiftDriverTests/CachingBuildTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -895,16 +895,17 @@ final class CachingBuildTests: XCTestCase {
main.nativePathString(escaped: true)] + sdkArgumentsForTesting,
env: env,
interModuleDependencyOracle: dependencyOracle)
guard driver.isFrontendArgSupported(.scannerPrefixMap) else {
guard driver.isFrontendArgSupported(.scannerPrefixMapPaths) else {
throw XCTSkip("frontend doesn't support prefix map")
}
let scanLibPath = try XCTUnwrap(driver.getSwiftScanLibPath())
try dependencyOracle.verifyOrCreateScannerInstance(swiftScanLibPath: scanLibPath)
let resolver = try ArgsResolver(fileSystem: localFileSystem)
let scannerCommand = try driver.dependencyScannerInvocationCommand().1.map { try resolver.resolve($0) }

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

let jobs = try driver.planBuild()
for job in jobs {
Expand Down