Skip to content

Commit d282cb2

Browse files
committed
ABIChecking: use the always-generated-abi-descriptor to diagnose ABI breakages
rdar://84595482
1 parent 2aeeb0c commit d282cb2

File tree

7 files changed

+59
-20
lines changed

7 files changed

+59
-20
lines changed

Sources/SwiftDriver/Driver/Driver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ public struct Driver {
694694
compilerMode: compilerMode,
695695
outputFileMap: self.outputFileMap,
696696
moduleName: moduleOutputInfo.name)
697+
697698
let projectDirectory = Self.computeProjectDirectoryPath(
698699
moduleOutputPath: self.moduleOutputInfo.output?.outputPath,
699700
fileSystem: self.fileSystem)
@@ -721,7 +722,6 @@ public struct Driver {
721722
compilerMode: compilerMode,
722723
outputFileMap: self.outputFileMap,
723724
moduleName: moduleOutputInfo.name)
724-
725725
self.swiftPrivateInterfacePath = try Self.computeSupplementaryOutputPath(
726726
&parsedOptions, type: .privateSwiftInterface, isOutputOptions: [],
727727
outputPath: .emitPrivateModuleInterfacePath,

Sources/SwiftDriver/Jobs/APIDigesterJobs.swift

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

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

Sources/SwiftDriver/Jobs/EmitModuleJob.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,10 @@ 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 = getDescriptorPath(for: .abi) {
9696
commandLine.appendFlag(.emitAbiDescriptorPath)
97-
let abiOutput = outputPath.replacingExtension(with: .jsonABIBaseline)
98-
commandLine.appendPath(abiOutput)
99-
outputs.append(TypedVirtualPath(file: abiOutput.intern(), type: .jsonABIBaseline))
97+
commandLine.appendPath(abiPath.file)
98+
outputs.append(abiPath)
10099
}
101100
return Job(
102101
moduleName: moduleOutputInfo.name,

Sources/SwiftDriver/Jobs/Job.swift

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

4747
public enum ArgTemplate: Equatable, Hashable {

Sources/SwiftDriver/Jobs/MergeModuleJob.swift

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

79-
if isFeatureSupported(.emit_abi_descriptor) {
79+
if let abiPath = getDescriptorPath(for: .abi) {
8080
commandLine.appendFlag(.emitAbiDescriptorPath)
81-
let abiOutput = outputPath.replacingExtension(with: .jsonABIBaseline)
82-
commandLine.appendPath(abiOutput)
83-
outputs.append(TypedVirtualPath(file: abiOutput.intern(), type: .jsonABIBaseline))
81+
commandLine.appendPath(abiPath.file)
82+
outputs.append(abiPath)
8483
}
8584
return Job(
8685
moduleName: moduleOutputInfo.name,

Sources/SwiftDriver/Jobs/Planning.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ extension Driver {
510510
}
511511
if let baselineArg = parsedOptions.getLastArgument(.compareToBaselinePath)?.asSingle,
512512
let baselinePath = try? VirtualPath.intern(path: baselineArg) {
513-
addJob(try digesterCompareToBaselineJob(modulePath: moduleOutputPath, baselinePath: baselinePath, mode: digesterMode))
513+
addJob(try digesterDiagnosticsJob(modulePath: moduleOutputPath, baselinePath: baselinePath, mode: digesterMode))
514514
}
515515
}
516516

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)