Skip to content

Commit 7aea4ee

Browse files
authored
Merge pull request #844 from owenv/owenv/linker-coverage
Fix coverage mapping linker args when using swiftc linker driver
2 parents 064809d + 4ea2c19 commit 7aea4ee

File tree

9 files changed

+103
-39
lines changed

9 files changed

+103
-39
lines changed

Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,9 +1311,9 @@ open class CommandLineToolSpec : PropertyDomainSpec, SpecType, TaskTypeDescripti
13111311
}
13121312

13131313
/// Compute the list of additional linker arguments to use when this tool is used for building with the given scope.
1314-
public func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) {
1314+
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]) {
13151315
// FIXME: Optimize the list to search here.
1316-
return (args: producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes) }, inputPaths: [])
1316+
return (args: producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes) }, inputPaths: [])
13171317
}
13181318

13191319
// 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.

Sources/SWBCore/SpecImplementations/PropertyDomainSpec.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,7 +1567,7 @@ private let buildOptionTypes: [String: any BuildOptionType] = [
15671567
}
15681568

15691569
/// Get the command line arguments to use for this option in the given scope.
1570-
func getAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec]) -> [String] {
1570+
func getAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?), inputFileTypes: [FileTypeSpec]) -> [String] {
15711571
// Filter by (any) supported file type.
15721572
func supportsAnyFileType() -> Bool {
15731573
for fileType in inputFileTypes {
@@ -1582,7 +1582,7 @@ private let buildOptionTypes: [String: any BuildOptionType] = [
15821582
}
15831583

15841584
// 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.
1585-
guard condition == nil || condition!.evaluateAsBoolean(scope) else {
1585+
guard condition == nil || condition!.evaluateAsBoolean(scope, lookup: lookup) else {
15861586
return []
15871587
}
15881588

@@ -1594,16 +1594,16 @@ private let buildOptionTypes: [String: any BuildOptionType] = [
15941594
guard let valueDefnOpt = scope.evaluate(self.macro as! BooleanMacroDeclaration) ? otherValueDefn : emptyValueDefn else { return [] }
15951595

15961596
guard let expr = valueDefnOpt.additionalLinkerArgs else { return [] }
1597-
return scope.evaluate(expr)
1597+
return scope.evaluate(expr, lookup: lookup)
15981598
}
15991599

16001600
// Handle list typed options.
16011601
guard !type.isListType else {
16021602
let values = switch self.macro {
16031603
case let macro as StringListMacroDeclaration:
1604-
scope.evaluate(macro)
1604+
scope.evaluate(macro, lookup: lookup)
16051605
case let macro as PathListMacroDeclaration:
1606-
scope.evaluate(macro)
1606+
scope.evaluate(macro, lookup: lookup)
16071607
default:
16081608
fatalError("invalid macro type for List option")
16091609
}
@@ -1612,11 +1612,11 @@ private let buildOptionTypes: [String: any BuildOptionType] = [
16121612
let valueDefnOpt = values.isEmpty ? emptyValueDefn : otherValueDefn
16131613

16141614
guard let expr = valueDefnOpt?.additionalLinkerArgs else { return [] }
1615-
return scope.evaluate(expr)
1615+
return scope.evaluate(expr, lookup: lookup)
16161616
}
16171617

16181618
// Otherwise, we have a scalar option.
1619-
let value = scope.evaluateAsString(self.macro)
1619+
let value = scope.evaluateAsString(self.macro, lookup: lookup)
16201620

16211621
// Get the value expression to use.
16221622
let valueDefnOpt = valueDefns.flatMap { $0[value] } ?? (value.isEmpty ? emptyValueDefn : otherValueDefn)
@@ -1627,6 +1627,9 @@ private let buildOptionTypes: [String: any BuildOptionType] = [
16271627
if macro === BuiltinMacros.value {
16281628
return scope.table.namespace.parseLiteralString(value)
16291629
}
1630+
if let lookupResult = lookup(macro) {
1631+
return lookupResult
1632+
}
16301633
return nil
16311634
}
16321635
}

Sources/SWBCore/SpecImplementations/Tools/LinkerTools.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec
510510

511511
let spec = info.key
512512
let inputFileTypes = info.value
513-
let (args, inputs) = await spec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, inputFileTypes: [FileTypeSpec](inputFileTypes), optionContext: spec.discoveredCommandLineToolSpecInfo(cbc.producer, cbc.scope, delegate), delegate: delegate)
513+
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)
514514
additionalLinkerArgsArray.append(contentsOf: args)
515515
inputPaths.append(contentsOf: inputs)
516516
}
@@ -531,7 +531,7 @@ public final class LdLinkerSpec : GenericLinkerSpec, SpecIdentifierType, @unchec
531531
for scope in depScopes {
532532
if scope.evaluate(BuiltinMacros.SWIFT_OBJC_INTEROP_MODE) == "objcxx" {
533533
let optionContext = await cbc.producer.swiftCompilerSpec.discoveredCommandLineToolSpecInfo(cbc.producer, scope, delegate)
534-
additionalLinkerArgsArray.append(contentsOf: await cbc.producer.swiftCompilerSpec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, inputFileTypes: [FileTypeSpec](), optionContext: optionContext, delegate: delegate).args)
534+
additionalLinkerArgsArray.append(contentsOf: await cbc.producer.swiftCompilerSpec.computeAdditionalLinkerArgs(cbc.producer, scope: cbc.scope, lookup: linkerDriverLookup, inputFileTypes: [FileTypeSpec](), optionContext: optionContext, delegate: delegate).args)
535535
additionalLinkerArgsArray.append(["-l\(cbc.scope.evaluate(BuiltinMacros.SWIFT_STDLIB))"])
536536
break
537537
}

Sources/SWBCore/SpecImplementations/Tools/SwiftCompiler.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,7 +2947,7 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
29472947
return (isEnabled, isExplicitlyEnabled)
29482948
}
29492949

2950-
private func staticallyLinkSwiftStdlib(_ producer: any CommandProducer, scope: MacroEvaluationScope) -> Bool {
2950+
private func staticallyLinkSwiftStdlib(_ producer: any CommandProducer, scope: MacroEvaluationScope, lookup: @escaping ((MacroDeclaration) -> MacroStringExpression?)) -> Bool {
29512951
// Determine whether we should statically link the Swift stdlib, and determined
29522952
// by the following logic in the following order:
29532953
//
@@ -2960,17 +2960,17 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
29602960
//
29612961
// NOTE: With Swift in the OS, static libs aren't being supplied by the toolchains
29622962
// so users of this flag will need to provide their own.
2963-
if scope.evaluate(BuiltinMacros.SWIFT_FORCE_STATIC_LINK_STDLIB) {
2963+
if scope.evaluate(BuiltinMacros.SWIFT_FORCE_STATIC_LINK_STDLIB, lookup: lookup) {
29642964
return true
29652965
}
29662966
return false
29672967
}
29682968

2969-
public override func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) {
2970-
return await computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes, optionContext: optionContext, forTAPI: false, delegate: delegate)
2969+
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]) {
2970+
return await computeAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes, optionContext: optionContext, forTAPI: false, delegate: delegate)
29712971
}
29722972

2973-
func computeAdditionalLinkerArgs(_ producer: any CommandProducer, scope: MacroEvaluationScope, inputFileTypes: [FileTypeSpec], optionContext: (any BuildOptionGenerationContext)?, forTAPI: Bool = false, delegate: any TaskGenerationDelegate) async -> (args: [[String]], inputPaths: [Path]) {
2973+
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]) {
29742974
guard let swiftToolSpec = optionContext as? DiscoveredSwiftCompilerToolSpecInfo else {
29752975
// An error message would have already been emitted by this point
29762976
return (args: [[]], inputPaths: [])
@@ -2983,21 +2983,21 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
29832983
var inputPaths: [Path] = []
29842984
if !forTAPI {
29852985
// 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.
2986-
args = producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: inputFileTypes) }.filter { !$0.isEmpty }
2986+
args = producer.effectiveFlattenedOrderedBuildOptions(self).map { $0.getAdditionalLinkerArgs(producer, scope: scope, lookup: lookup, inputFileTypes: inputFileTypes) }.filter { !$0.isEmpty }
29872987
}
29882988

29892989
// Determine if we are forced to use the standard system location; this is currently only for OS adopters of Swift, not any client.
2990-
let useSystemSwift = scope.evaluate(BuiltinMacros.SWIFT_FORCE_SYSTEM_LINK_STDLIB)
2990+
let useSystemSwift = scope.evaluate(BuiltinMacros.SWIFT_FORCE_SYSTEM_LINK_STDLIB, lookup: lookup)
29912991

29922992
// Determine whether we should statically link the Swift stdlib.
2993-
let shouldStaticLinkStdlib = staticallyLinkSwiftStdlib(producer, scope: scope)
2993+
let shouldStaticLinkStdlib = staticallyLinkSwiftStdlib(producer, scope: scope, lookup: lookup)
29942994

2995-
let swiftStdlibName = scope.evaluate(BuiltinMacros.SWIFT_STDLIB)
2996-
var swiftLibraryPath = scope.evaluate(BuiltinMacros.SWIFT_LIBRARY_PATH)
2997-
let dynamicLibraryExtension = scope.evaluate(BuiltinMacros.DYNAMIC_LIBRARY_EXTENSION)
2995+
let swiftStdlibName = scope.evaluate(BuiltinMacros.SWIFT_STDLIB, lookup: lookup)
2996+
var swiftLibraryPath = scope.evaluate(BuiltinMacros.SWIFT_LIBRARY_PATH, lookup: lookup)
2997+
let dynamicLibraryExtension = scope.evaluate(BuiltinMacros.DYNAMIC_LIBRARY_EXTENSION, lookup: lookup)
29982998

29992999
// If we weren't given an explicit library path, compute one
3000-
let platformName = scope.evaluate(BuiltinMacros.PLATFORM_NAME)
3000+
let platformName = scope.evaluate(BuiltinMacros.PLATFORM_NAME, lookup: lookup)
30013001
if swiftLibraryPath.isEmpty {
30023002
// Look next to the compiler and in the toolchains for one.
30033003
if shouldStaticLinkStdlib {
@@ -3015,13 +3015,13 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
30153015
}
30163016
}
30173017

3018-
let isMacCatalystUnzippered = producer.sdkVariant?.isMacCatalyst == true && !scope.evaluate(BuiltinMacros.IS_ZIPPERED)
3018+
let isMacCatalystUnzippered = producer.sdkVariant?.isMacCatalyst == true && !scope.evaluate(BuiltinMacros.IS_ZIPPERED, lookup: lookup)
30193019

30203020
var sdkPathArgument: [String] = []
30213021
var unzipperedSDKPathArgument: [String] = []
30223022
if forTAPI {
30233023
// TAPI requires absolute paths.
3024-
let sdkroot = scope.evaluate(BuiltinMacros.SDKROOT)
3024+
let sdkroot = scope.evaluate(BuiltinMacros.SDKROOT, lookup: lookup)
30253025
if !sdkroot.isEmpty {
30263026
sdkPathArgument = ["-L" + sdkroot.join("usr/lib/swift").str]
30273027
unzipperedSDKPathArgument = ["-L" + sdkroot.join("System/iOSSupport/usr/lib/swift").str]
@@ -3072,24 +3072,24 @@ public final class SwiftCompilerSpec : CompilerSpec, SpecIdentifierType, SwiftDi
30723072
// be a source-less target which just contains object files in it's framework phase.
30733073
let currentPlatformFilter = PlatformFilter(scope)
30743074
let containsSources = (producer.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.buildFiles.filter { currentPlatformFilter.matches($0.platformFilters) }.isEmpty == false
3075-
if containsSources && inputFileTypes.contains(where: { $0.conformsTo(identifier: "sourcecode.swift") }) && scope.evaluate(BuiltinMacros.GCC_GENERATE_DEBUGGING_SYMBOLS) && !scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_MODULEWRAP) {
3076-
let moduleName = scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME)
3077-
let moduleFileDir = scope.evaluate(BuiltinMacros.PER_ARCH_MODULE_FILE_DIR)
3075+
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) {
3076+
let moduleName = scope.evaluate(BuiltinMacros.SWIFT_MODULE_NAME, lookup: lookup)
3077+
let moduleFileDir = scope.evaluate(BuiltinMacros.PER_ARCH_MODULE_FILE_DIR, lookup: lookup)
30783078
let moduleFilePath = moduleFileDir.join(moduleName + ".swiftmodule")
30793079
args += [["-Xlinker", "-add_ast_path", "-Xlinker", moduleFilePath.str]]
3080-
if scope.evaluate(BuiltinMacros.SWIFT_GENERATE_ADDITIONAL_LINKER_ARGS) {
3080+
if scope.evaluate(BuiltinMacros.SWIFT_GENERATE_ADDITIONAL_LINKER_ARGS, lookup: lookup) {
30813081
args += [["@\(Path(moduleFilePath.appendingFileNameSuffix("-linker-args").withoutSuffix + ".resp").str)"]]
30823082
}
30833083
}
30843084
}
30853085

3086-
if scope.evaluate(BuiltinMacros.SWIFT_ADD_TOOLCHAIN_SWIFTSYNTAX_SEARCH_PATHS) {
3086+
if scope.evaluate(BuiltinMacros.SWIFT_ADD_TOOLCHAIN_SWIFTSYNTAX_SEARCH_PATHS, lookup: lookup) {
30873087
args += [["-L\(swiftToolSpec.hostLibraryDirectory.str)"]]
30883088
}
30893089

30903090
let containsSwiftSources = (producer.configuredTarget?.target as? StandardTarget)?.sourcesBuildPhase?.containsSwiftSources(producer, producer, scope, producer.filePathResolver) == true
3091-
if scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_AUTOLINK_EXTRACT) && containsSwiftSources {
3092-
let inputPath = scope.evaluate(BuiltinMacros.SWIFT_AUTOLINK_EXTRACT_OUTPUT_PATH)
3091+
if scope.evaluate(BuiltinMacros.PLATFORM_REQUIRES_SWIFT_AUTOLINK_EXTRACT, lookup: lookup) && containsSwiftSources {
3092+
let inputPath = scope.evaluate(BuiltinMacros.SWIFT_AUTOLINK_EXTRACT_OUTPUT_PATH, lookup: lookup)
30933093
args += [["@\(inputPath.str)"]]
30943094
inputPaths.append(inputPath)
30953095
}

Sources/SWBCore/SpecImplementations/Tools/TAPITools.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public final class TAPIToolSpec : GenericCommandLineToolSpec, GCCCompatibleCompi
120120
let producer = cbc.producer
121121
let swiftCompilerSpec = producer.swiftCompilerSpec
122122
let optionContext = await swiftCompilerSpec.discoveredCommandLineToolSpecInfo(producer, scope, delegate)
123-
commandLine += await swiftCompilerSpec.computeAdditionalLinkerArgs(producer, scope: scope, inputFileTypes: [], optionContext: optionContext, forTAPI: true, delegate: delegate).args.flatMap({ $0 })
123+
commandLine += await swiftCompilerSpec.computeAdditionalLinkerArgs(producer, scope: scope, lookup: { _ in nil }, inputFileTypes: [], optionContext: optionContext, forTAPI: true, delegate: delegate).args.flatMap({ $0 })
124124

125125
if !scope.evaluate(BuiltinMacros.SWIFT_OBJC_INTERFACE_HEADER_NAME).isEmpty && scope.evaluate(BuiltinMacros.SWIFT_INSTALL_OBJC_HEADER) {
126126
let generatedHeaderPath = SwiftCompilerSpec.generatedObjectiveCHeaderOutputPath(scope).str

Sources/SWBUniversalPlatform/Specs/Clang.xcspec

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2850,6 +2850,26 @@
28502850
Name = "CLANG_COVERAGE_MAPPING_LINKER_ARGS";
28512851
Type = Boolean;
28522852
DefaultValue = "$(CLANG_COVERAGE_MAPPING)";
2853+
},
2854+
2855+
{
2856+
Name = "SWIFTC_CLANG_COVERAGE_MAPPING_LINKER_ARGS";
2857+
Type = Boolean;
2858+
DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)";
2859+
Condition = "$(LINKER_DRIVER) == swiftc";
2860+
AdditionalLinkerArgs = {
2861+
NO = ();
2862+
YES = (
2863+
"-Xclang-linker", "-fprofile-instr-generate",
2864+
);
2865+
};
2866+
},
2867+
2868+
{
2869+
Name = "CLANG_CLANG_COVERAGE_MAPPING_LINKER_ARGS";
2870+
Type = Boolean;
2871+
DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)";
2872+
Condition = "$(LINKER_DRIVER) == clang";
28532873
AdditionalLinkerArgs = {
28542874
NO = ();
28552875
YES = (

Sources/SWBUniversalPlatform/Specs/Swift.xcspec

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,26 @@
11381138
Name = "CLANG_COVERAGE_MAPPING_LINKER_ARGS";
11391139
Type = Boolean;
11401140
DefaultValue = "$(CLANG_COVERAGE_MAPPING)";
1141+
},
1142+
1143+
{
1144+
Name = "SWIFTC_CLANG_COVERAGE_MAPPING_LINKER_ARGS";
1145+
Type = Boolean;
1146+
DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)";
1147+
Condition = "$(LINKER_DRIVER) == swiftc";
1148+
AdditionalLinkerArgs = {
1149+
NO = ();
1150+
YES = (
1151+
"-Xclang-linker", "-fprofile-instr-generate",
1152+
);
1153+
};
1154+
},
1155+
1156+
{
1157+
Name = "CLANG_CLANG_COVERAGE_MAPPING_LINKER_ARGS";
1158+
Type = Boolean;
1159+
DefaultValue = "$(CLANG_COVERAGE_MAPPING_LINKER_ARGS)";
1160+
Condition = "$(LINKER_DRIVER) == clang";
11411161
AdditionalLinkerArgs = {
11421162
NO = ();
11431163
YES = (

0 commit comments

Comments
 (0)