Skip to content

Commit 903ef0c

Browse files
committed
ABIChecking: use the always-generated-abi-descriptor to diagnose ABI breakages
rdar://84595482
1 parent b1ffa49 commit 903ef0c

File tree

7 files changed

+64
-16
lines changed

7 files changed

+64
-16
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,17 @@ public struct Driver {
353353
.appending(component: "Frameworks")
354354
} ()
355355

356+
lazy var abiDescriptorPath: TypedVirtualPath? = {
357+
guard isFeatureSupported(.emit_abi_descriptor) else {
358+
return nil
359+
}
360+
guard let moduleOutput = moduleOutputInfo.output else {
361+
return nil
362+
}
363+
return TypedVirtualPath(file: VirtualPath.lookup(moduleOutput.outputPath)
364+
.replacingExtension(with: .jsonABIBaseline).intern(), type: .jsonABIBaseline)
365+
}()
366+
356367
public func isFrontendArgSupported(_ opt: Option) -> Bool {
357368
var current = opt.spelling
358369
while(true) {
@@ -690,6 +701,7 @@ public struct Driver {
690701
compilerMode: compilerMode,
691702
outputFileMap: self.outputFileMap,
692703
moduleName: moduleOutputInfo.name)
704+
693705
let projectDirectory = Self.computeProjectDirectoryPath(
694706
moduleOutputPath: self.moduleOutputInfo.output?.outputPath,
695707
fileSystem: self.fileSystem)
@@ -717,7 +729,6 @@ public struct Driver {
717729
compilerMode: compilerMode,
718730
outputFileMap: self.outputFileMap,
719731
moduleName: moduleOutputInfo.name)
720-
721732
self.swiftPrivateInterfacePath = try Self.computeSupplementaryOutputPath(
722733
&parsedOptions, type: .privateSwiftInterface, isOutputOptions: [],
723734
outputPath: .emitPrivateModuleInterfacePath,

Sources/SwiftDriver/Jobs/APIDigesterJobs.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,50 @@ extension Driver {
6565
)
6666
}
6767

68+
mutating func digesterDiagnosticsJob(modulePath: VirtualPath.Handle, baselinePath:
69+
VirtualPath.Handle, mode: DigesterMode) throws -> Job {
70+
func getDescriptorPath(for mode: DigesterMode) -> TypedVirtualPath? {
71+
switch mode {
72+
case .api:
73+
return nil
74+
case .abi:
75+
return abiDescriptorPath
76+
}
77+
}
78+
guard let currentABI = getDescriptorPath(for: mode) else {
79+
// we don't have existing descriptor to use so we have to load the module from interface/swiftmodule
80+
return try digesterCompareToBaselineJob(modulePath: modulePath, baselinePath: baselinePath, mode: digesterMode)
81+
}
82+
var commandLine = [Job.ArgTemplate]()
83+
commandLine.appendFlag("-diagnose-sdk")
84+
commandLine.appendFlag("-input-paths")
85+
commandLine.appendPath(VirtualPath.lookup(baselinePath))
86+
commandLine.appendFlag("-input-paths")
87+
commandLine.appendPath(currentABI.file)
88+
if mode == .abi {
89+
commandLine.appendFlag("-abi")
90+
}
91+
if let arg = parsedOptions.getLastArgument(.digesterBreakageAllowlistPath)?.asSingle {
92+
let path = try VirtualPath(path: arg)
93+
commandLine.appendFlag("-breakage-allowlist-path")
94+
commandLine.appendPath(path)
95+
}
96+
commandLine.appendFlag("-serialize-diagnostics-path")
97+
let diag = TypedVirtualPath(file: currentABI.file.parentDirectory.appending(component: currentABI.file.basename + ".dia").intern(), type: .diagnostics)
98+
commandLine.appendPath(diag.file)
99+
let inputs: [TypedVirtualPath] = [currentABI]
100+
return Job(
101+
moduleName: moduleOutputInfo.name,
102+
kind: .compareABIBaseline,
103+
tool: .absolute(try toolchain.getToolPath(.swiftAPIDigester)),
104+
commandLine: commandLine,
105+
inputs: inputs,
106+
primaryInputs: [],
107+
outputs: [diag],
108+
supportsResponseFiles: true
109+
)
110+
}
111+
68112
mutating func digesterCompareToBaselineJob(modulePath: VirtualPath.Handle, baselinePath: VirtualPath.Handle, mode: DigesterMode) throws -> Job {
69113
var commandLine = [Job.ArgTemplate]()
70114
commandLine.appendFlag("-diagnose-sdk")

Sources/SwiftDriver/Jobs/EmitModuleJob.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ extension Driver {
9292
let outputPath = VirtualPath.lookup(moduleOutputPath)
9393
commandLine.appendFlag(.o)
9494
commandLine.appendPath(outputPath)
95-
if isFeatureSupported(.emit_abi_descriptor) {
95+
if let abiPath = abiDescriptorPath {
9696
commandLine.appendFlag(.emitAbiDescriptorPath)
97-
commandLine.appendPath(outputPath.replacingExtension(with: .jsonABIBaseline))
97+
commandLine.appendPath(abiPath.file)
9898
}
9999
return Job(
100100
moduleName: moduleOutputInfo.name,

Sources/SwiftDriver/Jobs/Job.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public struct Job: Codable, Equatable, Hashable {
4040
case generateAPIBaseline = "generate-api-baseline"
4141
case generateABIBaseline = "generate-abi-baseline"
4242
case compareAPIBaseline = "compare-api-baseline"
43-
case compareABIBaseline = "compare-abi-baseline"
43+
case compareABIBaseline = "Check ABI stability"
4444
}
4545

4646
public enum ArgTemplate: Equatable, Hashable {

Sources/SwiftDriver/Jobs/MergeModuleJob.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ extension Driver {
7676
commandLine.appendFlag(.o)
7777
commandLine.appendPath(outputPath)
7878

79-
if isFeatureSupported(.emit_abi_descriptor) {
79+
if let abiPath = abiDescriptorPath {
8080
commandLine.appendFlag(.emitAbiDescriptorPath)
81-
commandLine.appendPath(outputPath.replacingExtension(with: .jsonABIBaseline))
81+
commandLine.appendPath(abiPath.file)
8282
}
8383
return Job(
8484
moduleName: moduleOutputInfo.name,

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ extension Driver {
495495
}
496496
if let baselineArg = parsedOptions.getLastArgument(.compareToBaselinePath)?.asSingle,
497497
let baselinePath = try? VirtualPath.intern(path: baselineArg) {
498-
addJob(try digesterCompareToBaselineJob(modulePath: moduleOutputPath, baselinePath: baselinePath, mode: digesterMode))
498+
addJob(try digesterDiagnosticsJob(modulePath: moduleOutputPath, baselinePath: baselinePath, mode: digesterMode))
499499
}
500500
}
501501

Tests/SwiftDriverTests/APIDigesterTests.swift

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,18 +252,11 @@ class APIDigesterTests: XCTestCase {
252252
"-digester-breakage-allowlist-path", "allowlist/path"])
253253
let digesterJob = try XCTUnwrap(driver.planBuild().first { $0.kind == .compareABIBaseline })
254254
XCTAssertTrue(digesterJob.commandLine.contains("-diagnose-sdk"))
255-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-module", "foo"]))
256-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-baseline-path", .path(.absolute(.init("/baseline/path")))]))
257-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-I", .path(.relative(.init(".")))]))
258-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-sdk", .path(.absolute(.init("/path/to/sdk")))]))
259-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-I", .path(.absolute(.init("/some/path")))]))
260-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-F", .path(.relative(.init("framework/path")))]))
261-
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-serialize-diagnostics-path",
262-
.path(.relative(.init("breaking-changes.dia")))]))
255+
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-input-paths", .path(.absolute(.init("/baseline/path")))]))
263256
XCTAssertTrue(digesterJob.commandLine.contains(subsequence: ["-breakage-allowlist-path",
264257
.path(.relative(.init("allowlist/path")))]))
265-
266258
XCTAssertTrue(digesterJob.commandLine.contains("-abi"))
259+
XCTAssertTrue(digesterJob.commandLine.contains("-serialize-diagnostics-path"))
267260
}
268261
}
269262

0 commit comments

Comments
 (0)