diff --git a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift index 917c56bfa..ab4cfe0f4 100644 --- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift @@ -32,8 +32,14 @@ extension Toolchain { if platform == "android" { platform = "linux" } + + // NOTE(compnerd) Windows uses the per-target runtime directory for the + // Windows runtimes. This should also be done for the other platforms, but + // is not critical. This is done to allow for the Windows runtimes to be + // co-located for all the currently supported architectures: x86, x64, arm64. + let bIsWindows = targetInfo.target.triple.isWindows return VirtualPath.lookup(targetInfo.runtimeResourcePath.path) - .appending(components: "clang", "lib", platform) + .appending(components: "clang", "lib", bIsWindows ? targetInfo.target.triple.triple : platform) } func runtimeLibraryPaths( diff --git a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift index 9e34e8db4..eae53e381 100644 --- a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift @@ -223,7 +223,10 @@ extension WindowsToolchain { commandLine.appendFlag(optArg) } - // FIXME(compnerd) render asan/ubsan runtime link for executables + if !sanitizers.isEmpty { + let sanitize = sanitizers.map(\.rawValue).sorted().joined(separator: ",") + commandLine.appendFlag("-fsanitize=\(sanitize)") + } if parsedOptions.contains(.profileGenerate) { assert(bForceLLD, diff --git a/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift b/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift index 1d529ded6..43cb1aafc 100644 --- a/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/WindowsToolchain.swift @@ -130,6 +130,11 @@ extension WindowsToolchain.ToolchainValidationError { public func runtimeLibraryName(for sanitizer: Sanitizer, targetTriple: Triple, isShared: Bool) throws -> String { // TODO(compnerd) handle shared linking + + // FIXME(compnerd) when should `clang_rt.ubsan_standalone_cxx` be used? + if sanitizer == .undefinedBehavior { + return "clang_rt.ubsan_standalone.lib" + } return "clang_rt.\(sanitizer.libraryName).lib" } diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index eee05a75d..72ffd89b6 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -2708,56 +2708,39 @@ final class SwiftDriverTests: XCTestCase { func testSanitizerArgs() throws { let commonArgs = [ - "swiftc", "foo.swift", "bar.swift", - "-emit-executable", "-target", "x86_64-apple-macosx10.9", - "-module-name", "Test" + "swiftc", "foo.swift", "bar.swift", "-emit-executable", "-module-name", "Test", "-use-ld=lld" ] - // FIXME: This doesn't work on Linux. - #if os(macOS) + do { // address sanitizer var driver = try Driver(args: commonArgs + ["-sanitize=address"]) - let plannedJobs = try driver.planBuild() - - XCTAssertEqual(plannedJobs.count, 3) - - let compileJob = plannedJobs[0] - let compileCmd = compileJob.commandLine - XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address"))) + let jobs = try driver.planBuild().removingAutolinkExtractJobs() - let linkJob = plannedJobs[2] - let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) + XCTAssertEqual(jobs.count, 3) + XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address")) + XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address")) } do { // address sanitizer on a dylib var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library"]) - let plannedJobs = try driver.planBuild() - - XCTAssertEqual(plannedJobs.count, 3) - - let compileJob = plannedJobs[0] - let compileCmd = compileJob.commandLine - XCTAssertTrue(compileCmd.contains(.flag("-sanitize=address"))) + let jobs = try driver.planBuild().removingAutolinkExtractJobs() - let linkJob = plannedJobs[2] - let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) + XCTAssertEqual(jobs.count, 3) + XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=address")) + XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=address")) } do { // *no* address sanitizer on a static lib var driver = try Driver(args: commonArgs + ["-sanitize=address", "-emit-library", "-static"]) - let plannedJobs = try driver.planBuild() - - XCTAssertEqual(plannedJobs.count, 3) + let jobs = try driver.planBuild().removingAutolinkExtractJobs() - let linkJob = plannedJobs[2] - let linkCmd = linkJob.commandLine - XCTAssertFalse(linkCmd.contains(.flag("-fsanitize=address"))) + XCTAssertEqual(jobs.count, 3) + XCTAssertFalse(jobs[2].commandLine.contains(.flag("-fsanitize=address"))) } +#if !os(Windows) do { // thread sanitizer var driver = try Driver(args: commonArgs + ["-sanitize=thread"]) @@ -2773,21 +2756,16 @@ final class SwiftDriverTests: XCTestCase { let linkCmd = linkJob.commandLine XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=thread"))) } +#endif do { // undefined behavior sanitizer var driver = try Driver(args: commonArgs + ["-sanitize=undefined"]) - let plannedJobs = try driver.planBuild() - - XCTAssertEqual(plannedJobs.count, 3) - - let compileJob = plannedJobs[0] - let compileCmd = compileJob.commandLine - XCTAssertTrue(compileCmd.contains(.flag("-sanitize=undefined"))) + let jobs = try driver.planBuild().removingAutolinkExtractJobs() - let linkJob = plannedJobs[2] - let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=undefined"))) + XCTAssertEqual(jobs.count, 3) + XCTAssertJobInvocationMatches(jobs[0], .flag("-sanitize=undefined")) + XCTAssertJobInvocationMatches(jobs[2], .flag("-fsanitize=undefined")) } // FIXME: This test will fail when run on macOS, because the driver uses @@ -2838,7 +2816,6 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=scudo"))) } #endif - #endif // FIXME: This test will fail when not run on Android, because the driver uses // the existence of the runtime support libraries to determine if @@ -7223,7 +7200,7 @@ final class SwiftDriverTests: XCTestCase { } func testSanitizerArgsForTargets() throws { - let targets = ["x86_64-unknown-freebsd", "x86_64-unknown-linux", "x86_64-apple-macosx10.9"] + let targets = ["x86_64-unknown-freebsd", "x86_64-unknown-linux", "x86_64-apple-macosx10.9", "x86_64-unknown-windows-msvc"] try targets.forEach { var driver = try Driver(args: ["swiftc", "-emit-module", "-target", $0, "foo.swift"]) _ = try driver.planBuild()