diff --git a/Sources/SWBTestSupport/SwiftTestingExtensions.swift b/Sources/SWBTestSupport/SwiftTestingExtensions.swift index 51290bad..e89625e7 100644 --- a/Sources/SWBTestSupport/SwiftTestingExtensions.swift +++ b/Sources/SWBTestSupport/SwiftTestingExtensions.swift @@ -17,3 +17,14 @@ package import Testing package func expectEqual(_ lhs: T, _ rhs: T, sourceLocation: SourceLocation = #_sourceLocation) { #expect(lhs == rhs, sourceLocation: sourceLocation) } + + +package extension Tag { + enum TestSize {} +} + +package extension Tag.TestSize { + @Tag static var small: Tag + @Tag static var medium: Tag + @Tag static var large: Tag +} diff --git a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec index d99b24d8..48b8be95 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec @@ -2896,7 +2896,7 @@ }; AdditionalLinkerArgs = { YES = ( - "-fsanitize=address", + "$(LD_ADDRESS_SANITIZER)", ); NO = (); }; diff --git a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec index 2a31927e..40022fee 100644 --- a/Sources/SWBUniversalPlatform/Specs/Ld.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Ld.xcspec @@ -582,17 +582,37 @@ DefaultValue = YES; }, + // Address Sanitizer options + { + Name = LD_ADDRESS_SANITIZER; + DefaultValue = "$(LD_ADDRESS_SANITIZER_$(LINKER_DRIVER))"; + }, + { + Name = LD_ADDRESS_SANITIZER_clang; + DefaultValue = "-fsanitize=address"; + }, + { + Name = LD_ADDRESS_SANITIZER_swiftc; + DefaultValue = "-sanitize=address"; + }, + // Thread Sanitizer options { Name = "LD_THREAD_SANITIZER"; Type = Boolean; DefaultValue = "$(ENABLE_THREAD_SANITIZER)"; + }, + { + Name = "CLANG_LD_THREAD_SANITIZER"; + Type = Boolean; + DefaultValue = "$(LD_THREAD_SANITIZER)"; Architectures = ( x86_64, x86_64h, arm64, arm64e, ); + Condition = "$(LINKER_DRIVER) == clang"; CommandLineArgs = { YES = ( "-fsanitize=thread", @@ -601,6 +621,25 @@ }; // Not visible in the build settings editor }, + { + Name = "SWIFTC_LD_THREAD_SANITIZER"; + Type = Boolean; + DefaultValue = "$(LD_THREAD_SANITIZER)"; + Architectures = ( + x86_64, + x86_64h, + arm64, + arm64e, + ); + Condition = "$(LINKER_DRIVER) == swiftc"; + CommandLineArgs = { + YES = ( + "-sanitize=thread", + ); + NO = (); + }; + // Not visible in the build settings editor + }, { Name = "LD_DEBUG_VARIANT"; diff --git a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec index 76b7cb1f..ba60e9b1 100644 --- a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec @@ -1225,7 +1225,7 @@ }; AdditionalLinkerArgs = { YES = ( - "-fsanitize=address", + "$(LD_ADDRESS_SANITIZER)", ); NO = (); }; diff --git a/Tests/SWBTaskConstructionTests/LinkerTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/LinkerTaskConstructionTests.swift index f19e8e39..09c66faf 100644 --- a/Tests/SWBTaskConstructionTests/LinkerTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/LinkerTaskConstructionTests.swift @@ -141,4 +141,89 @@ fileprivate struct LinkerTaskConstructionTests: CoreBasedTests { } } } + + @Test( + .tags( + .TestSize.medium, + ), + .requireSDKs(.host), + arguments: [ + ( + buildSettingNameUT: "ENABLE_ADDRESS_SANITIZER", + linkerDriverUT: "clang", + expectedArgument: "-fsanitize=address", + ), + ( + buildSettingNameUT: "ENABLE_ADDRESS_SANITIZER", + linkerDriverUT: "swiftc", + expectedArgument: "-sanitize=address", + ), + ( + buildSettingNameUT: "ENABLE_THREAD_SANITIZER", + linkerDriverUT: "clang", + expectedArgument: "-fsanitize=thread", + ), + ( + buildSettingNameUT: "ENABLE_THREAD_SANITIZER", + linkerDriverUT: "swiftc", + expectedArgument: "-sanitize=thread", + ), + ] + ) + func ldSanitizerArgumentsAppearsOnCommandLine( + buildSettingNameUT: String, + linkerDriverUT: String, + expectedArgument: String, + ) async throws { + let testProject = TestProject( + "aProject", + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("c.c"), + TestFile("cxx.cpp"), + TestFile("s.swift"), + ]), + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "PRODUCT_NAME": "$(TARGET_NAME)", + "SWIFT_EXEC": try await swiftCompilerPath.str, + "SWIFT_VERSION": try await swiftVersion + ]), + ], + targets: [ + TestStandardTarget( + "Library", + type: .dynamicLibrary, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [:]), + ], + buildPhases: [ + TestSourcesBuildPhase(["c.c", "cxx.cpp", "s.swift"]), + ] + ), + ], + ) + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + let buildOverrides = [ + "LINKER_DRIVER": linkerDriverUT, + buildSettingNameUT: "YES", + ] + + await tester.checkBuild( + BuildParameters( + configuration: "Debug", + overrides: buildOverrides, + ), + runDestination: .host, + ) { results in + results.checkNoDiagnostics() + results.checkTask(.matchRuleType("Ld")) { task in + task.checkCommandLineContains([expectedArgument]) + } + } + + } + } diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 244c4949..dbedb79a 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -4061,8 +4061,17 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } /// Test that we properly generate commands for the compiler sanitizer features. - @Test(.requireSDKs(.macOS)) - func sanitizers() async throws { + @Test( + .requireSDKs(.macOS), + arguments:[ + (linkerDriver: "clang", expectedArgument: "-fsanitize=address"), + (linkerDriver: "swiftc", expectedArgument: "-sanitize=address"), + ], + ) + func sanitizers( + linkerDriver: String, + expectedArgument: String, + ) async throws { try await withTemporaryDirectory { tmpDir in let targetName = "AppTarget" let testProject = try await TestProject( @@ -4115,7 +4124,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } // Check the LibSystem address sanitizer. - await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["ENABLE_ADDRESS_SANITIZER": "YES","ENABLE_SYSTEM_SANITIZERS": "YES" ]), runDestination: .macOS, fs: fs) { results in + await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["LINKER_DRIVER": linkerDriver,"ENABLE_ADDRESS_SANITIZER": "YES","ENABLE_SYSTEM_SANITIZERS": "YES" ]), runDestination: .macOS, fs: fs) { results in results.checkTarget(targetName) { target in // There should be one CompileC task, which includes the ASan option, and which puts its output in a -asan directory. results.checkTask(.matchTarget(target), .matchRuleType("CompileC")) { task in @@ -4129,8 +4138,12 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in task.checkCommandLineContains( - ["-fsanitize=address", "-fsanitize-stable-abi", "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)" - ]) + [ + expectedArgument, + "-fsanitize-stable-abi", + "\(SRCROOT)/build/Debug/\(targetName).app/Contents/MacOS/\(targetName)", + ] + ) } } }