Skip to content

Commit b3c8853

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 f882b3d commit b3c8853

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
@@ -692,7 +692,7 @@ extension Driver {
692692
input: nil,
693693
flag: "-emit-tbd-path")
694694

695-
if let abiDescriptorPath = abiDescriptorPath {
695+
if let abiDescriptorPath = moduleOutputPaths.abiDescriptorFilePath {
696696
try addOutputOfType(outputType: .jsonABIBaseline,
697697
finalOutputPath: abiDescriptorPath.fileHandle,
698698
input: nil,

Sources/SwiftDriver/Jobs/MergeModuleJob.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ extension Driver {
7575
commandLine.appendFlag(.o)
7676
commandLine.appendPath(outputPath)
7777

78-
if let abiPath = abiDescriptorPath {
78+
if let abiPath = moduleOutputPaths.abiDescriptorFilePath {
7979
commandLine.appendFlag(.emitAbiDescriptorPath)
8080
commandLine.appendPath(abiPath.file)
8181
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>")
@@ -1301,6 +1302,7 @@ extension Option {
13011302
Option.emitTbdPathEQ,
13021303
Option.emitTbdPath,
13031304
Option.emitTbd,
1305+
Option.emitVariantAbiDescriptorPath,
13041306
Option.emitVariantApiDescriptorPath,
13051307
Option.emitVariantModuleDocPath,
13061308
Option.emitVariantModuleInterfacePath,

Tests/SwiftDriverTests/SwiftDriverTests.swift

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

40914091
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.swiftdoc")))))
40924092
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.swiftsourceinfo")))))
4093+
XCTAssert(targetModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/target.abi.json")))))
40934094
XCTAssertTrue(targetModuleJob.commandLine.contains(subsequence: [.flag("-o"), .path(.relative(try .init(validating: "foo.swiftmodule/target.swiftmodule")))]))
40944095

40954096
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftdoc")))))
40964097
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftsourceinfo")))))
4098+
XCTAssert(variantModuleJob.commandLine.contains(.path(.relative(try .init(validating: "foo.swiftmodule/variant.abi.json")))))
40974099
XCTAssertTrue(variantModuleJob.commandLine.contains(subsequence: [.flag("-o"), .path(.relative(try .init(validating: "foo.swiftmodule/variant.swiftmodule")))]))
40984100
}
40994101

4102+
do {
4103+
// explicitly emit variant supplemental outputs
4104+
var driver = try Driver(args: ["swiftc",
4105+
"-target", "x86_64-apple-macosx10.14",
4106+
"-target-variant", "x86_64-apple-ios13.1-macabi",
4107+
"-enable-library-evolution",
4108+
"-package-name", "Susan",
4109+
"-emit-module",
4110+
"-emit-module-path", "target.swiftmodule",
4111+
"-emit-variant-module-path", "variant.swiftmodule",
4112+
"-Xfrontend", "-emit-module-doc-path", "-Xfrontend", "target.swiftdoc",
4113+
"-Xfrontend", "-emit-variant-module-doc-path", "variant.swiftdoc",
4114+
"-emit-module-source-info-path", "target.sourceinfo",
4115+
"-emit-variant-module-source-info-path", "variant.sourceinfo",
4116+
"-emit-package-module-interface-path", "target.package.swiftinterface",
4117+
"-emit-variant-package-module-interface-path", "variant.package.swiftinterface",
4118+
"-emit-private-module-interface-path", "target.private.swiftinterface",
4119+
"-emit-variant-private-module-interface-path", "variant.private.swiftinterface",
4120+
"-emit-module-interface-path", "target.swiftinterface",
4121+
"-emit-variant-module-interface-path", "variant.swiftinterface",
4122+
"foo.swift"])
4123+
4124+
let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs()
4125+
// emit module, emit module, compile foo.swift,
4126+
// verify target.swiftinterface,
4127+
// verify target.private.swiftinterface,
4128+
// verify target.package.swiftinterface,
4129+
XCTAssertEqual(plannedJobs.count, 6)
4130+
4131+
let targetModuleJob: Job = plannedJobs[0]
4132+
let variantModuleJob = plannedJobs[1]
4133+
4134+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftModule }.last!.file,
4135+
try toPath("target.swiftmodule"))
4136+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftModule }.last!.file,
4137+
try toPath("variant.swiftmodule"))
4138+
4139+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftDocumentation }.last!.file,
4140+
try toPath("target.swiftdoc"))
4141+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftDocumentation }.last!.file,
4142+
try toPath("variant.swiftdoc"))
4143+
4144+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftSourceInfoFile }.last!.file,
4145+
try toPath("target.sourceinfo"))
4146+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftSourceInfoFile }.last!.file,
4147+
try toPath("variant.sourceinfo"))
4148+
4149+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .swiftInterface}.last!.file,
4150+
try toPath("target.swiftinterface"))
4151+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .swiftInterface}.last!.file,
4152+
try toPath("variant.swiftinterface"))
4153+
4154+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .privateSwiftInterface}.last!.file,
4155+
try toPath("target.private.swiftinterface"))
4156+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .privateSwiftInterface}.last!.file,
4157+
try toPath("variant.private.swiftinterface"))
4158+
4159+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .packageSwiftInterface}.last!.file,
4160+
try toPath("target.package.swiftinterface"))
4161+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .packageSwiftInterface}.last!.file,
4162+
try toPath("variant.package.swiftinterface"))
4163+
4164+
XCTAssertEqual(targetModuleJob.outputs.filter { $0.type == .jsonABIBaseline }.last!.file,
4165+
try toPath("target.abi.json"))
4166+
XCTAssertEqual(variantModuleJob.outputs.filter { $0.type == .jsonABIBaseline}.last!.file,
4167+
try toPath("variant.abi.json"))
4168+
}
4169+
41004170
#if os(macOS)
41014171
do {
41024172
try withTemporaryDirectory { path in

0 commit comments

Comments
 (0)