-
Notifications
You must be signed in to change notification settings - Fork 204
Add an integration with swift-api-digester #721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f26cb05
eac3fd5
6206c02
4ec1161
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
//===- APIDigesterJobs.swift - Baseline Generation and API/ABI Comparison -===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2021 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import TSCBasic | ||
|
||
enum DigesterMode: String { | ||
case api, abi | ||
|
||
var baselineFileType: FileType { | ||
switch self { | ||
case .api: | ||
return .jsonAPIBaseline | ||
case .abi: | ||
return .jsonABIBaseline | ||
} | ||
} | ||
|
||
var baselineGenerationJobKind: Job.Kind { | ||
switch self { | ||
case .api: | ||
return .generateAPIBaseline | ||
case .abi: | ||
return .generateABIBaseline | ||
} | ||
} | ||
|
||
var baselineComparisonJobKind: Job.Kind { | ||
switch self { | ||
case .api: | ||
return .compareAPIBaseline | ||
case .abi: | ||
return .compareABIBaseline | ||
} | ||
} | ||
} | ||
|
||
extension Driver { | ||
mutating func digesterBaselineGenerationJob(modulePath: VirtualPath.Handle, outputPath: VirtualPath.Handle, mode: DigesterMode) throws -> Job { | ||
var commandLine = [Job.ArgTemplate]() | ||
commandLine.appendFlag("-dump-sdk") | ||
|
||
try addCommonDigesterOptions(&commandLine, modulePath: modulePath, mode: mode) | ||
|
||
commandLine.appendFlag(.o) | ||
commandLine.appendPath(VirtualPath.lookup(outputPath)) | ||
|
||
return Job( | ||
moduleName: moduleOutputInfo.name, | ||
kind: mode.baselineGenerationJobKind, | ||
tool: .absolute(try toolchain.getToolPath(.swiftAPIDigester)), | ||
commandLine: commandLine, | ||
inputs: [.init(file: modulePath, type: .swiftModule)], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 makes sense, done! |
||
primaryInputs: [], | ||
outputs: [.init(file: outputPath, type: mode.baselineFileType)], | ||
supportsResponseFiles: true | ||
) | ||
} | ||
|
||
mutating func digesterCompareToBaselineJob(modulePath: VirtualPath.Handle, baselinePath: VirtualPath.Handle, mode: DigesterMode) throws -> Job { | ||
var commandLine = [Job.ArgTemplate]() | ||
commandLine.appendFlag("-diagnose-sdk") | ||
commandLine.appendFlag("-disable-fail-on-error") | ||
commandLine.appendFlag("-baseline-path") | ||
commandLine.appendPath(VirtualPath.lookup(baselinePath)) | ||
|
||
try addCommonDigesterOptions(&commandLine, modulePath: modulePath, mode: mode) | ||
|
||
var serializedDiagnosticsPath: VirtualPath.Handle? | ||
if let arg = parsedOptions.getLastArgument(.serializeBreakingChangesPath)?.asSingle { | ||
let path = try VirtualPath.intern(path: arg) | ||
commandLine.appendFlag("-serialize-diagnostics-path") | ||
commandLine.appendPath(VirtualPath.lookup(path)) | ||
serializedDiagnosticsPath = path | ||
} | ||
if let arg = parsedOptions.getLastArgument(.digesterBreakageAllowlistPath)?.asSingle { | ||
let path = try VirtualPath(path: arg) | ||
commandLine.appendFlag("-breakage-allowlist-path") | ||
commandLine.appendPath(path) | ||
} | ||
|
||
var inputs: [TypedVirtualPath] = [.init(file: modulePath, type: .swiftModule), | ||
.init(file: baselinePath, type: mode.baselineFileType)] | ||
// If a module interface was emitted, treat it as an input in ABI mode. | ||
if let interfacePath = self.swiftInterfacePath, mode == .abi { | ||
inputs.append(.init(file: interfacePath, type: .swiftInterface)) | ||
} | ||
|
||
return Job( | ||
moduleName: moduleOutputInfo.name, | ||
kind: mode.baselineComparisonJobKind, | ||
tool: .absolute(try toolchain.getToolPath(.swiftAPIDigester)), | ||
commandLine: commandLine, | ||
inputs: inputs, | ||
primaryInputs: [], | ||
outputs: [.init(file: serializedDiagnosticsPath ?? VirtualPath.Handle.standardOutput, type: .diagnostics)], | ||
supportsResponseFiles: true | ||
) | ||
} | ||
|
||
private mutating func addCommonDigesterOptions(_ commandLine: inout [Job.ArgTemplate], | ||
modulePath: VirtualPath.Handle, | ||
mode: DigesterMode) throws { | ||
commandLine.appendFlag("-module") | ||
commandLine.appendFlag(moduleOutputInfo.name) | ||
if mode == .abi { | ||
commandLine.appendFlag("-abi") | ||
commandLine.appendFlag("-use-interface-for-module") | ||
commandLine.appendFlag(moduleOutputInfo.name) | ||
} | ||
|
||
// Add a search path for the emitted module, and its module interface if there is one. | ||
let searchPath = VirtualPath.lookup(modulePath).parentDirectory | ||
commandLine.appendFlag(.I) | ||
commandLine.appendPath(searchPath) | ||
if let interfacePath = self.swiftInterfacePath { | ||
let interfaceSearchPath = VirtualPath.lookup(interfacePath).parentDirectory | ||
if interfaceSearchPath != searchPath { | ||
commandLine.appendFlag(.I) | ||
commandLine.appendPath(interfaceSearchPath) | ||
} | ||
} | ||
|
||
commandLine.appendFlag(.target) | ||
commandLine.appendFlag(targetTriple.triple) | ||
|
||
if let sdkPath = frontendTargetInfo.sdkPath?.path { | ||
commandLine.appendFlag(.sdk) | ||
commandLine.append(.path(VirtualPath.lookup(sdkPath))) | ||
} | ||
|
||
commandLine.appendFlag(.resourceDir) | ||
commandLine.appendPath(VirtualPath.lookup(frontendTargetInfo.runtimeResourcePath.path)) | ||
|
||
try commandLine.appendAll(.I, from: &parsedOptions) | ||
try commandLine.appendAll(.F, from: &parsedOptions) | ||
for systemFramework in parsedOptions.arguments(for: .Fsystem) { | ||
commandLine.appendFlag(.iframework) | ||
commandLine.appendFlag(systemFramework.argument.asSingle) | ||
} | ||
|
||
try commandLine.appendLast(.swiftVersion, from: &parsedOptions) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing the previous round of comments! Here will give us a location next to
.swiftmodule
file. Can we change it so that we emit next to.swiftsourceinfo
file instead?.swiftsourceinfo
is in theProject
directory if you use XCBuild, which is a sub-directory reserved for local artifacts.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is already using the same logic as
.swiftsourceinfo
, they both callcomputeModuleAuxiliaryOutputPath
and should use theProject
folder if it's present. The only difference is that source info is opt-out and baseline generation is opt-in. I have a couple basic tests for this intestBaselineOutputPath
which roughly correspond to the ones intestSourceInfoFileEmitOption
. It's possible I made a mistake somewhere though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, you are right. I meant the build system has already been passing down the path of
.swiftsourceinfo
via output file map. We could just use that to decide where we should put the baseline files. I presume we could add a special case in here: https://github.com/apple/swift-driver/blob/main/Sources/SwiftDriver/Driver/OutputFileMap.swift#L49There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, that makes sense! I added the new rule and a couple tests involving output file maps