diff --git a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift index 8bf3bb03..d120be22 100644 --- a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift +++ b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift @@ -1311,9 +1311,9 @@ open class CommandLineToolSpec : PropertyDomainSpec, SpecType, TaskTypeDescripti } /// Compute the list of additional linker arguments to use when this tool is used for building with the given scope. - public func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { + public func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?), inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { // FIXME: Optimize the list to search here. - return (args: producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes) }, inputPaths: []) + return (args: producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes) }, inputPaths: []) } // Creates and returns the environment from the specification. This includes both the 'EnvironmentVariables' property for this tool spec, and any build options which define that their value should be exported via their 'SetValueInEnvironmentVariable' property. diff --git a/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift b/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift index b8fa1092..af2f0063 100644 --- a/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift +++ b/Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift @@ -1567,7 +1567,7 @@ private let buildOptionTypes: [String: any BuildOptionType] = [ } /// Get the command line arguments to use for this option in the given scope. - func getAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec]) -> [String] { + func getAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?), inputFileTypes: [FileTypeSpec]) -> [String] { // Filter by (any) supported file type. func supportsAnyFileType() -> Bool { for fileType in inputFileTypes { @@ -1582,7 +1582,7 @@ private let buildOptionTypes: [String: any BuildOptionType] = [ } // Filter by macro condition expression. If we don't have one, or we do have one and it evaluates to true, then we can proceed with argument generation. - guard condition == nil || condition!.evaluateAsBoolean(scope) else { + guard condition == nil || condition!.evaluateAsBoolean(scope, lookup: lookup) else { return [] } @@ -1594,16 +1594,16 @@ private let buildOptionTypes: [String: any BuildOptionType] = [ guard let valueDefnOpt = scope.evaluate(self.macro as! BooleanMacroDeclaration) ? otherValueDefn : emptyValueDefn else { return [] } guard let expr = valueDefnOpt.additionalLinkerArgs else { return [] } - return scope.evaluate(expr) + return scope.evaluate(expr, lookup: lookup) } // Handle list typed options. guard !type.isListType else { let values = switch self.macro { case let macro as StringListMacroDeclaration: - scope.evaluate(macro) + scope.evaluate(macro, lookup: lookup) case let macro as PathListMacroDeclaration: - scope.evaluate(macro) + scope.evaluate(macro, lookup: lookup) default: fatalError("invalid macro type for List option") } @@ -1612,11 +1612,11 @@ private let buildOptionTypes: [String: any BuildOptionType] = [ let valueDefnOpt = values.isEmpty ? emptyValueDefn : otherValueDefn guard let expr = valueDefnOpt?.additionalLinkerArgs else { return [] } - return scope.evaluate(expr) + return scope.evaluate(expr, lookup: lookup) } // Otherwise, we have a scalar option. - let value = scope.evaluateAsString(self.macro) + let value = scope.evaluateAsString(self.macro, lookup: lookup) // Get the value expression to use. let valueDefnOpt = valueDefns.flatMap { $0[value] } ?? (value.isEmpty ? emptyValueDefn : otherValueDefn) @@ -1627,6 +1627,9 @@ private let buildOptionTypes: [String: any BuildOptionType] = [ if macro === BuiltinMacros.value { return scope.table.namespace.parseLiteralString(value) } + if let lookupResult = lookup(macro) { + return lookupResult + } return nil } } diff --git a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift index 8d2580d0..c591ca8f 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift @@ -510,7 +510,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec let spec = info.key let inputFileTypes = info.value - let (args, inputs) = await spec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, inputFileTypes: [FileTypeSpec](inputFileTypes), optionContext: spec.discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate), delegate: delegate) + let (args, inputs) = await spec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, lookup: linkerDriverLookup, inputFileTypes: [FileTypeSpec](inputFileTypes), optionContext: spec.discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate), delegate: delegate) additionalLinkerArgsArray.append(contentsOf: args) inputPaths.append(contentsOf: inputs) } @@ -531,7 +531,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec for scope in depScopes { if scope.evaluate(BuiltinMacros.SWIFT_OBJC_INTEROP_MODE) == "objcxx" { let optionContext = await cbc.producer.swiftCompilerSpec.discoveredCommandLineToolSpecInfo(cbc.producer, scope, delegate) - additionalLinkerArgsArray.append(contentsOf: await cbc.producer.swiftCompilerSpec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, inputFileTypes: [FileTypeSpec](), optionContext: optionContext, delegate: delegate).args) + additionalLinkerArgsArray.append(contentsOf: await cbc.producer.swiftCompilerSpec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, lookup: linkerDriverLookup, inputFileTypes: [FileTypeSpec](), optionContext: optionContext, delegate: delegate).args) additionalLinkerArgsArray.append(["-l\(cbc.scope.evaluate(BuiltinMacros.SWIFT_STDLIB))"]) break } diff --git a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift index a4b8c377..eafcb553 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift @@ -2947,7 +2947,7 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi return (isEnabled, isExplicitlyEnabled) } - private func staticallyLinkSwiftStdlib(_ producer: any CommandProducer, scope: MacroEvaluationScope) -> Bool { + private func staticallyLinkSwiftStdlib(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?)) -> Bool { // Determine whether we should statically link the Swift stdlib, and determined // by the following logic in the following order: // @@ -2960,17 +2960,17 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi // // NOTE: With Swift in the OS, static libs aren't being supplied by the toolchains // so users of this flag will need to provide their own. - if scope.evaluate(BuiltinMacros.SWIFT_FORCE_STATIC_LINK_STDLIB) { + if scope.evaluate(BuiltinMacros.SWIFT_FORCE_STATIC_LINK_STDLIB, lookup: lookup) { return true } return false } - public override func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { - return await computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes, optionContext: optionContext, forTAPI: false, delegate: delegate) + public override func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?), inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { + return await computeAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes, optionContext: optionContext, forTAPI: false, delegate: delegate) } - func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, forTAPI: Bool = false, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { + func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?), inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, forTAPI: Bool = false, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) { guard let swiftToolSpec = optionContext as? DiscoveredSwiftCompilerToolSpecInfo else { // An error message would have already been emitted by this point return (args: [[]], inputPaths: []) @@ -2983,21 +2983,21 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi var inputPaths: [Path] = [] if !forTAPI { // TAPI can't use all of the additional linker options, and its spec has all of the build setting/option arguments that it can use. - args = producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes) }.filter { !$0.isEmpty } + args = producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes) }.filter { !$0.isEmpty } } // Determine if we are forced to use the standard system location; this is currently only for OS adopters of Swift, not any client. - let useSystemSwift = scope.evaluate(BuiltinMacros.SWIFT_FORCE_SYSTEM_LINK_STDLIB) + let useSystemSwift = scope.evaluate(BuiltinMacros.SWIFT_FORCE_SYSTEM_LINK_STDLIB, lookup: lookup) // Determine whether we should statically link the Swift stdlib. - let shouldStaticLinkStdlib = staticallyLinkSwiftStdlib(producer, scope: scope) + let shouldStaticLinkStdlib = staticallyLinkSwiftStdlib(producer, scope: scope, lookup: lookup) - let swiftStdlibName = scope.evaluate(BuiltinMacros.SWIFT_STDLIB) - var swiftLibraryPath = scope.evaluate(BuiltinMacros.SWIFT_LIBRARY_PATH) - let dynamicLibraryExtension = scope.evaluate(BuiltinMacros.DYNAMIC_LIBRARY_EXTENSION) + let swiftStdlibName = scope.evaluate(BuiltinMacros.SWIFT_STDLIB, lookup: lookup) + var swiftLibraryPath = scope.evaluate(BuiltinMacros.SWIFT_LIBRARY_PATH, lookup: lookup) + let dynamicLibraryExtension = scope.evaluate(BuiltinMacros.DYNAMIC_LIBRARY_EXTENSION, lookup: lookup) // If we weren't given an explicit library path, compute one - let platformName = scope.evaluate(BuiltinMacros.PLATFORM_NAME) + let platformName = scope.evaluate(BuiltinMacros.PLATFORM_NAME, lookup: lookup) if swiftLibraryPath.isEmpty { // Look next to the compiler and in the toolchains for one. if shouldStaticLinkStdlib { @@ -3015,13 +3015,13 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi } } - let isMacCatalystUnzippered = producer.sdkVariant?.isMacCatalyst == true && !scope.evaluate(BuiltinMacros.IS_ZIPPERED) + let isMacCatalystUnzippered = producer.sdkVariant?.isMacCatalyst == true && !scope.evaluate(BuiltinMacros.IS_ZIPPERED, lookup: lookup) var sdkPathArgument: [String] = [] var unzipperedSDKPathArgument: [String] = [] if forTAPI { // TAPI requires absolute paths. - let sdkroot = scope.evaluate(BuiltinMacros.SDKROOT) + let sdkroot = scope.evaluate(BuiltinMacros.SDKROOT, lookup: lookup) if !sdkroot.isEmpty { sdkPathArgument = ["-L" + sdkroot.join("usr/lib/swift").str] unzipperedSDKPathArgument = ["-L" + sdkroot.join("System/iOSSupport/usr/lib/swift").str] @@ -3072,24 +3072,24 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi // be a source-less target which just contains object files in it's framework phase. let currentPlatformFilter = PlatformFilter(scope) let containsSources = (producer.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.buildFiles.filter { currentPlatformFilter.matches($0.platformFilters) }.isEmpty == false - if containsSources && inputFileTypes.contains(where: { $0.conformsTo(identifier: "sourcecode.swift") }) && scope.evaluate(BuiltinMacros.GCC_GENERATE_DEBUGGING_SYMBOLS) && !scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_MODULEWRAP) { - let moduleName = scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME) - let moduleFileDir = scope.evaluate(BuiltinMacros.PER_ARCH_MODULE_FILE_DIR) + if containsSources && inputFileTypes.contains(where: { $0.conformsTo(identifier: "sourcecode.swift") }) && scope.evaluate(BuiltinMacros.GCC_GENERATE_DEBUGGING_SYMBOLS, lookup: lookup) && !scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_MODULEWRAP, lookup: lookup) { + let moduleName = scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME, lookup: lookup) + let moduleFileDir = scope.evaluate(BuiltinMacros.PER_ARCH_MODULE_FILE_DIR, lookup: lookup) let moduleFilePath = moduleFileDir.join(moduleName + ".swiftmodule") args += [["-Xlinker", "-add_ast_path", "-Xlinker", moduleFilePath.str]] - if scope.evaluate(BuiltinMacros.SWIFT_GENERATE_ADDITIONAL_LINKER_ARGS) { + if scope.evaluate(BuiltinMacros.SWIFT_GENERATE_ADDITIONAL_LINKER_ARGS, lookup: lookup) { args += [["@\(Path(moduleFilePath.appendingFileNameSuffix("-linker-args").withoutSuffix + ".resp").str)"]] } } } - if scope.evaluate(BuiltinMacros.SWIFT_ADD_TOOLCHAIN_SWIFTSYNTAX_SEARCH_PATHS) { + if scope.evaluate(BuiltinMacros.SWIFT_ADD_TOOLCHAIN_SWIFTSYNTAX_SEARCH_PATHS, lookup: lookup) { args += [["-L\(swiftToolSpec.hostLibraryDirectory.str)"]] } let containsSwiftSources = (producer.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.containsSwiftSources(producer, producer, scope, producer.filePathResolver) == true - if scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_AUTOLINK_EXTRACT) && containsSwiftSources { - let inputPath = scope.evaluate(BuiltinMacros.SWIFT_AUTOLINK_EXTRACT_OUTPUT_PATH) + if scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_AUTOLINK_EXTRACT, lookup: lookup) && containsSwiftSources { + let inputPath = scope.evaluate(BuiltinMacros.SWIFT_AUTOLINK_EXTRACT_OUTPUT_PATH, lookup: lookup) args += [["@\(inputPath.str)"]] inputPaths.append(inputPath) } diff --git a/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift b/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift index b58dbb03..c6dfad44 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift @@ -120,7 +120,7 @@ public final class TAPIToolSpec : GenericCommandLineToolSpec, GCCCompatibleCompi let producer = cbc.producer let swiftCompilerSpec = producer.swiftCompilerSpec let optionContext = await swiftCompilerSpec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - commandLine += await swiftCompilerSpec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, forTAPI: true, delegate: delegate).args.flatMap({ $0 }) + commandLine += await swiftCompilerSpec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, forTAPI: true, delegate: delegate).args.flatMap({ $0 }) if !scope.evaluate(BuiltinMacros.SWIFT_OBJC_INTERFACE_HEADER_NAME).isEmpty && scope.evaluate(BuiltinMacros.SWIFT_INSTALL_OBJC_HEADER) { let generatedHeaderPath = SwiftCompilerSpec.generatedObjectiveCHeaderOutputPath(scope).str diff --git a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec index 4f189ce3..d25ba9ec 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec @@ -2850,6 +2850,26 @@ Name = "CLANG_COVERAGE_MAPPING_LINKER_ARGS"; Type = Boolean; DefaultValue = "$(CLANG_COVERAGE_MAPPING)"; + }, + + { + Name = "SWIFTC_CLANG_COVERAGE_MAPPING_LINKER_ARGS"; + Type = Boolean; + DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)"; + Condition = "$(LINKER_DRIVER) == swiftc"; + AdditionalLinkerArgs = { + NO = (); + YES = ( + "-Xclang-linker", "-fprofile-instr-generate", + ); + }; + }, + + { + Name = "CLANG_CLANG_COVERAGE_MAPPING_LINKER_ARGS"; + Type = Boolean; + DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)"; + Condition = "$(LINKER_DRIVER) == clang"; AdditionalLinkerArgs = { NO = (); YES = ( diff --git a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec index 5d43e46b..d5f32b7d 100644 --- a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec @@ -1138,6 +1138,26 @@ Name = "CLANG_COVERAGE_MAPPING_LINKER_ARGS"; Type = Boolean; DefaultValue = "$(CLANG_COVERAGE_MAPPING)"; + }, + + { + Name = "SWIFTC_CLANG_COVERAGE_MAPPING_LINKER_ARGS"; + Type = Boolean; + DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)"; + Condition = "$(LINKER_DRIVER) == swiftc"; + AdditionalLinkerArgs = { + NO = (); + YES = ( + "-Xclang-linker", "-fprofile-instr-generate", + ); + }; + }, + + { + Name = "CLANG_CLANG_COVERAGE_MAPPING_LINKER_ARGS"; + Type = Boolean; + DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)"; + Condition = "$(LINKER_DRIVER) == clang"; AdditionalLinkerArgs = { NO = (); YES = ( diff --git a/Tests/SWBCoreTests/SwiftCompilerTests.swift b/Tests/SWBCoreTests/SwiftCompilerTests.swift index 0fb08d09..f37311db 100644 --- a/Tests/SWBCoreTests/SwiftCompilerTests.swift +++ b/Tests/SWBCoreTests/SwiftCompilerTests.swift @@ -142,7 +142,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda let scope = MacroEvaluationScope(table: table) let delegate = TestTaskPlanningDelegate(clientDelegate: MockTestTaskPlanningClientDelegate(), fs: localFS) let optionContext = await spec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) + try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) } // Check force static stdlib. @@ -157,7 +157,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda let scope = MacroEvaluationScope(table: table) let delegate = TestTaskPlanningDelegate(clientDelegate: MockTestTaskPlanningClientDelegate(), fs: localFS) let optionContext = await spec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == (additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) + [["-Xlinker", "-force_load_swift_libs"], ["-lc++", "-framework", "Foundation"]]) + try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == (additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) + [["-Xlinker", "-force_load_swift_libs"], ["-lc++", "-framework", "Foundation"]]) } // Check tool product type. @@ -171,7 +171,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda let scope = MacroEvaluationScope(table: table) let delegate = TestTaskPlanningDelegate(clientDelegate: MockTestTaskPlanningClientDelegate(), fs: localFS) let optionContext = await spec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) + try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) } // Check tool product type forced to dynamic link. @@ -186,7 +186,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda let scope = MacroEvaluationScope(table: table) let delegate = TestTaskPlanningDelegate(clientDelegate: MockTestTaskPlanningClientDelegate(), fs: localFS) let optionContext = await spec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) + try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath)) } // Check system stdlib option. @@ -201,7 +201,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda let scope = MacroEvaluationScope(table: table) let delegate = TestTaskPlanningDelegate(clientDelegate: MockTestTaskPlanningClientDelegate(), fs: localFS) let optionContext = await spec.discoveredCommandLineToolSpecInfo(producer, scope, delegate) - try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == ([["-L/usr/lib/swift"]] + additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath))) + try await #expect(spec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, delegate: CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)).args == ([["-L/usr/lib/swift"]] + additionalSwiftLinkerArgs(spec, producer, scope, stdlibPath))) } } } diff --git a/Tests/SWBTaskConstructionTests/CodeCoverageTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/CodeCoverageTaskConstructionTests.swift index bde27528..cc858d60 100644 --- a/Tests/SWBTaskConstructionTests/CodeCoverageTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/CodeCoverageTaskConstructionTests.swift @@ -113,5 +113,26 @@ fileprivate struct CodeCoverageTaskConstructionTests: CoreBasedTests { results.checkNoDiagnostics() } - } + + for linkerDriver in ["auto", "swiftc"] { + // Repeat the linker argument checks using alternate drivers + await tester.checkBuild(BuildParameters(configuration: "Debug", overrides: ["CLANG_COVERAGE_MAPPING": "YES", "LINKER_DRIVER": linkerDriver]), runDestination: .host) { results in + results.checkTarget("Target") { target in + // There should be one Ld task, which includes coverage options + results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in + task.checkCommandLineContains(["-Xclang-linker", "-fprofile-instr-generate"]) + } + } + + results.checkTarget("NoCoverageTarget") { target in + // There should be one Ld task, which includes coverage options + results.checkTask(.matchTarget(target), .matchRuleType("Ld")) { task in + task.checkCommandLineContains(["-Xclang-linker", "-fprofile-instr-generate"]) + } + } + + results.checkNoDiagnostics() + } + } + } }