Skip to content

Commit c1dc6cb

Browse files
committed
Add target variant ABI digester file
Now teaching the compiler to emit the ABI JSON file for the target variant module.
1 parent 3abe69f commit c1dc6cb

File tree

7 files changed

+112
-23
lines changed

7 files changed

+112
-23
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ public struct Driver {
398398

399399
/// Path to the emitted API descriptor file.
400400
let apiDescriptorFilePath: VirtualPath.Handle?
401+
402+
/// Path to the emitted ABI descriptor file.
403+
let abiDescriptorFilePath: TypedVirtualPath?
401404
}
402405

403406
private static func computeModuleOutputPaths(
@@ -411,12 +414,14 @@ public struct Driver {
411414
outputFileMap: OutputFileMap?,
412415
projectDirectory: VirtualPath.Handle?,
413416
apiDescriptorDirectory: VirtualPath?,
417+
supportedFrontendFeatures: Set<String>,
414418
target: FrontendTargetInfo.Target,
415419
isVariant: Bool) throws -> SupplementalModuleTargetOutputPaths {
416420
struct SupplementalPathOptions {
417421
let moduleDocPath: Option
418422
let sourceInfoPath: Option
419423
let apiDescriptorPath: Option
424+
let abiDescriptorPath: Option
420425
let moduleInterfacePath: Option
421426
let privateInterfacePath: Option
422427
let packageInterfacePath: Option
@@ -425,6 +430,7 @@ public struct Driver {
425430
moduleDocPath: .emitModuleDocPath,
426431
sourceInfoPath: .emitModuleSourceInfoPath,
427432
apiDescriptorPath: .emitApiDescriptorPath,
433+
abiDescriptorPath: .emitAbiDescriptorPath,
428434
moduleInterfacePath: .emitModuleInterfacePath,
429435
privateInterfacePath: .emitPrivateModuleInterfacePath,
430436
packageInterfacePath: .emitPackageModuleInterfacePath)
@@ -433,6 +439,7 @@ public struct Driver {
433439
moduleDocPath: .emitVariantModuleDocPath,
434440
sourceInfoPath: .emitVariantModuleSourceInfoPath,
435441
apiDescriptorPath: .emitVariantApiDescriptorPath,
442+
abiDescriptorPath: .emitVariantAbiDescriptorPath,
436443
moduleInterfacePath: .emitVariantModuleInterfacePath,
437444
privateInterfacePath: .emitVariantPrivateModuleInterfacePath,
438445
packageInterfacePath: .emitVariantPackageModuleInterfacePath)
@@ -459,6 +466,31 @@ public struct Driver {
459466
moduleName: moduleOutputInfo.name,
460467
projectDirectory: projectDirectory)
461468

469+
// ---------------------
470+
// ABI Descriptor Path
471+
func computeABIDescriptorFilePath(target: FrontendTargetInfo.Target,
472+
features: Set<String>) -> TypedVirtualPath? {
473+
guard features.contains(KnownCompilerFeature.emit_abi_descriptor.rawValue) else {
474+
return nil
475+
}
476+
// Emit the descriptor only on platforms where Library Evolution is
477+
// supported
478+
guard target.triple.isDarwin || parsedOptions.hasArgument(.enableLibraryEvolution) else {
479+
return nil
480+
}
481+
guard let moduleOutput = moduleOutputInfo.output else {
482+
return nil
483+
}
484+
485+
guard let path = try? VirtualPath.lookup(moduleOutput.outputPath)
486+
.replacingExtension(with: .jsonABIBaseline) else {
487+
return nil
488+
}
489+
return TypedVirtualPath(file: path.intern(), type: .jsonABIBaseline)
490+
}
491+
let abiDescriptorFilePath = computeABIDescriptorFilePath(target: target,
492+
features: supportedFrontendFeatures)
493+
462494
// ---------------------
463495
// API Descriptor Path
464496
let apiDescriptorFilePath: VirtualPath.Handle?
@@ -545,7 +577,8 @@ public struct Driver {
545577
swiftPrivateInterfacePath: swiftPrivateInterfacePath,
546578
swiftPackageInterfacePath: swiftPackageInterfacePath,
547579
moduleSourceInfoPath: moduleSourceInfoPath,
548-
apiDescriptorFilePath: apiDescriptorFilePath)
580+
apiDescriptorFilePath: apiDescriptorFilePath,
581+
abiDescriptorFilePath: abiDescriptorFilePath)
549582
}
550583

551584
/// Structure storing paths to supplemental outputs for the target module
@@ -622,24 +655,6 @@ public struct Driver {
622655
.appending(component: "Frameworks")
623656
} ()
624657

625-
lazy var abiDescriptorPath: TypedVirtualPath? = {
626-
guard isFeatureSupported(.emit_abi_descriptor) else {
627-
return nil
628-
}
629-
// Emit the descriptor only on platforms where Library Evolution is supported,
630-
// or opted-into explicitly.
631-
guard targetTriple.isDarwin || parsedOptions.hasArgument(.enableLibraryEvolution) else {
632-
return nil
633-
}
634-
guard let moduleOutput = moduleOutputInfo.output else {
635-
return nil
636-
}
637-
guard let path = try? VirtualPath.lookup(moduleOutput.outputPath).replacingExtension(with: .jsonABIBaseline) else {
638-
return nil
639-
}
640-
return TypedVirtualPath(file: path.intern(), type: .jsonABIBaseline)
641-
}()
642-
643658
public static func isOptionFound(_ opt: String, allOpts: Set<String>) -> Bool {
644659
var current = opt
645660
while(true) {
@@ -1221,6 +1236,7 @@ public struct Driver {
12211236
outputFileMap: self.outputFileMap,
12221237
projectDirectory: projectDirectory,
12231238
apiDescriptorDirectory: apiDescriptorDirectory,
1239+
supportedFrontendFeatures: self.supportedFrontendFeatures,
12241240
target: frontendTargetInfo.target,
12251241
isVariant: false)
12261242

@@ -1237,6 +1253,7 @@ public struct Driver {
12371253
outputFileMap: self.outputFileMap,
12381254
projectDirectory: projectDirectory,
12391255
apiDescriptorDirectory: apiDescriptorDirectory,
1256+
supportedFrontendFeatures: self.supportedFrontendFeatures,
12401257
target: targetVariant,
12411258
isVariant: true)
12421259
} else {

Sources/SwiftDriver/Jobs/APIDigesterJobs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extension Driver {
7272
case .api:
7373
return nil
7474
case .abi:
75-
return abiDescriptorPath
75+
return moduleOutputPaths.abiDescriptorFilePath
7676
}
7777
}
7878
guard let currentABI = getDescriptorPath(for: mode) else {

Sources/SwiftDriver/Jobs/EmitModuleJob.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ extension Driver {
125125
let outputPath = VirtualPath.lookup(moduleOutputPath)
126126
commandLine.appendFlag(.o)
127127
commandLine.appendPath(outputPath)
128-
if let abiPath = abiDescriptorPath {
128+
if let abiPath = moduleOutputPaths.abiDescriptorFilePath {
129129
commandLine.appendFlag(.emitAbiDescriptorPath)
130130
commandLine.appendPath(abiPath.file)
131131
outputs.append(abiPath)

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ extension Driver {
697697
input: nil,
698698
flag: "-emit-tbd-path")
699699

700-
if let abiDescriptorPath = abiDescriptorPath {
700+
if let abiDescriptorPath = moduleOutputPaths.abiDescriptorFilePath {
701701
try addOutputOfType(outputType: .jsonABIBaseline,
702702
finalOutputPath: abiDescriptorPath.fileHandle,
703703
input: nil,

Sources/SwiftDriver/Jobs/MergeModuleJob.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extension Driver {
6565
commandLine.appendFlag(.o)
6666
commandLine.appendPath(outputPath)
6767

68-
if let abiPath = abiDescriptorPath {
68+
if let abiPath = moduleOutputPaths.abiDescriptorFilePath {
6969
commandLine.appendFlag(.emitAbiDescriptorPath)
7070
commandLine.appendPath(abiPath.file)
7171
outputs.append(abiPath)

Sources/SwiftOptions/Options.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ extension Option {
384384
public static let emitTbdPathEQ: Option = Option("-emit-tbd-path=", .joined, alias: Option.emitTbdPath, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant])
385385
public static let emitTbdPath: Option = Option("-emit-tbd-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "<path>", helpText: "Emit the TBD file to <path>")
386386
public static let emitTbd: Option = Option("-emit-tbd", .flag, attributes: [.frontend, .noInteractive, .supplementaryOutput], helpText: "Emit a TBD file")
387+
public static let emitVariantAbiDescriptorPath: Option = Option("-emit-variant-abi-descriptor-path", .separate, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "<path>", helpText: "Output the ABI descriptor of current target variant module to <path>")
387388
public static let emitVariantApiDescriptorPath: Option = Option("-emit-variant-api-descriptor-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "<path>", helpText: "Output a JSON file describing the target variant module's API to <path>")
388389
public static let emitVariantModuleDocPath: Option = Option("-emit-variant-module-doc-path", .separate, attributes: [.frontend, .noDriver, .cacheInvariant], metaVar: "<path>", helpText: "Output module documentation file for the target variant to <path>")
389390
public static let emitVariantModuleInterfacePath: Option = Option("-emit-variant-module-interface-path", .separate, attributes: [.frontend, .noInteractive, .argumentIsPath, .supplementaryOutput, .cacheInvariant], metaVar: "<path>", helpText: "Output module interface file for the target variant to <path>")
@@ -1304,6 +1305,7 @@ extension Option {
13041305
Option.emitTbdPathEQ,
13051306
Option.emitTbdPath,
13061307
Option.emitTbd,
1308+
Option.emitVariantAbiDescriptorPath,
13071309
Option.emitVariantApiDescriptorPath,
13081310
Option.emitVariantModuleDocPath,
13091311
Option.emitVariantModuleInterfacePath,

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4112,13 +4112,83 @@ final class SwiftDriverTests: XCTestCase {
41124112

41134113
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.swiftdoc")))))
41144114
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.swiftsourceinfo")))))
4115+
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.abi.json")))))
41154116
XCTAssertTrue(targetModuleJob.commandLine.contains(subsequence: [.flag("-o"), .path(.relative(try .init(validating: "foo.swiftmodule/target.swiftmodule")))]))
41164117

41174118
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftdoc")))))
41184119
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftsourceinfo")))))
4120+
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.abi.json")))))
41194121
XCTAssertTrue(variantModuleJob.commandLine.contains(subsequence: [.flag("-o"), .path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftmodule")))]))
41204122
}
41214123

4124+
do {
4125+
// explicitly emit variant supplemental outputs
4126+
var driver = try Driver(args: ["swiftc",
4127+
"-target", "x86_64-apple-macosx10.14",
4128+
"-target-variant", "x86_64-apple-ios13.1-macabi",
4129+
"-enable-library-evolution",
4130+
"-package-name", "Susan",
4131+
"-emit-module",
4132+
"-emit-module-path", "target.swiftmodule",
4133+
"-emit-variant-module-path", "variant.swiftmodule",
4134+
"-Xfrontend", "-emit-module-doc-path", "-Xfrontend", "target.swiftdoc",
4135+
"-Xfrontend", "-emit-variant-module-doc-path", "variant.swiftdoc",
4136+
"-emit-module-source-info-path", "target.sourceinfo",
4137+
"-emit-variant-module-source-info-path", "variant.sourceinfo",
4138+
"-emit-package-module-interface-path", "target.package.swiftinterface",
4139+
"-emit-variant-package-module-interface-path", "variant.package.swiftinterface",
4140+
"-emit-private-module-interface-path", "target.private.swiftinterface",
4141+
"-emit-variant-private-module-interface-path", "variant.private.swiftinterface",
4142+
"-emit-module-interface-path", "target.swiftinterface",
4143+
"-emit-variant-module-interface-path", "variant.swiftinterface",
4144+
"foo.swift"])
4145+
4146+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
4147+
// emit module, emit module, compile foo.swift,
4148+
// verify target.swiftinterface,
4149+
// verify target.private.swiftinterface,
4150+
// verify target.package.swiftinterface,
4151+
XCTAssertEqual(plannedJobs.count, 6)
4152+
4153+
let targetModuleJob: Job = plannedJobs[0]
4154+
let variantModuleJob = plannedJobs[1]
4155+
4156+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftModule }.last!.file,
4157+
try toPath("target.swiftmodule"))
4158+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftModule }.last!.file,
4159+
try toPath("variant.swiftmodule"))
4160+
4161+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftDocumentation }.last!.file,
4162+
try toPath("target.swiftdoc"))
4163+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftDocumentation }.last!.file,
4164+
try toPath("variant.swiftdoc"))
4165+
4166+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftSourceInfoFile }.last!.file,
4167+
try toPath("target.sourceinfo"))
4168+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftSourceInfoFile }.last!.file,
4169+
try toPath("variant.sourceinfo"))
4170+
4171+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftInterface}.last!.file,
4172+
try toPath("target.swiftinterface"))
4173+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftInterface}.last!.file,
4174+
try toPath("variant.swiftinterface"))
4175+
4176+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .privateSwiftInterface}.last!.file,
4177+
try toPath("target.private.swiftinterface"))
4178+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .privateSwiftInterface}.last!.file,
4179+
try toPath("variant.private.swiftinterface"))
4180+
4181+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .packageSwiftInterface}.last!.file,
4182+
try toPath("target.package.swiftinterface"))
4183+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .packageSwiftInterface}.last!.file,
4184+
try toPath("variant.package.swiftinterface"))
4185+
4186+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .jsonABIBaseline }.last!.file,
4187+
try toPath("target.abi.json"))
4188+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .jsonABIBaseline}.last!.file,
4189+
try toPath("variant.abi.json"))
4190+
}
4191+
41224192
#if os(macOS)
41234193
do {
41244194
try withTemporaryDirectory { path in

0 commit comments

Comments
 (0)