-
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
Conversation
This adds support for generating an API and/or ABI baseline as part of a driver build plan if a module is being emitted. As a result, build systems and higher-level tools no longer need to interact with swift-api-digester directly.
Thank you for working on this @owenv ! I was on vacation in the previous several days and I'll start review this exciting PR shortly! |
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.
This is amazing! @owenv Some comments are inlined.
@@ -18,6 +18,18 @@ extension Option { | |||
public static let noEmitModuleSeparately: Option = Option("-no-emit-module-separately", .flag, attributes: [.helpHidden], helpText: "Force using merge-module as the incremental build mode") | |||
public static let useFrontendParseableOutput: Option = Option("-use-frontend-parseable-output", .flag, attributes: [.helpHidden], helpText: "Emit parseable-output from swift-frontend jobs instead of from the driver") | |||
|
|||
// API digester operations | |||
public static let emitAPIBaseline: Option = Option("-emit-api-baseline", .flag, attributes: [.noInteractive, .supplementaryOutput], helpText: "Emit an API baseline file for the module") |
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.
Instead of introducing abi
versions of every flags, we probably just keep the api
versions of all these flags and introduce a -abi
flag to indicate ABI checking is actually intended. This is less error-prone and aligns with the tool's flags.
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.
Ok, that sounds good to me! Instead of -abi
, right now I'm using -digester-mode abi
or -digester-mode api
(with the default being api
if it's unspecified), which I think makes it a little clearer what the impact of the setting is.
@@ -462,6 +463,24 @@ extension Driver { | |||
} | |||
} | |||
|
|||
private mutating func addAPIDigesterJobs(addJob: (Job) -> Void) throws { |
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.
ABI checking is only relevant when -enable-library-evolution
and -emit-module-interface
are specified. Could you check these conditions before proceeding and diagnose as well?
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.
👍 makes sense, done!
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 comment
The reason will be displayed to describe this comment to others. Learn more.
For -abi
, we should also require the interface file as the input. Please also add digester flag -use-interface-for-module CurrentMainModule
when generating ABI baselines.
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.
👍 makes sense, done!
Remove duplicated API/ABI digester flags Fixes for ABI baselines and comparisons
c52bfba
to
eac3fd5
Compare
@nkcsgexi thanks for the feedback! I hadn't spent as much time thinking about the ABI-checking use case, so this is really helpful. |
) throws -> VirtualPath.Handle? { | ||
// Only emit a baseline if at least of the arguments was provided. | ||
guard parsedOptions.hasArgument(.emitDigesterBaseline, .emitDigesterBaselinePath) else { return nil } | ||
return try computeModuleAuxiliaryOutputPath(&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 the Project
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 call computeModuleAuxiliaryOutputPath
and should use the Project
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 in testBaselineOutputPath
which roughly correspond to the ones in testSourceInfoFileEmitOption
. 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#L49
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.
Oh I see, that makes sense! I added the new rule and a couple tests involving output file maps
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.
This looks great! @owenv
@swift-ci please test |
Thanks! Once I merge swiftlang/swift#37991 and it makes it into a nightly toolchain the tests here should pass |
Sounds good! |
@swift-ci please test |
The tests which run jobs are now checking for flag availability so they won't fail when run with an older toolchain. I verified in swiftlang/swift#38251 that they run & pass with new toolchains, so this is good to go. |
The goal here is to add support to the driver for generating an API/ABI baseline or comparing to one immediately after emitting a module. This means higher-level build systems like SwiftPM can share the implementation and each won't need to have their own support for generating swift-api-digester command lines to add breaking-change detection.
A few notes on the implementation:
-emit-module
is used to emit a top-level module. I implemented it this way because if the module is considered 'auxilary', the swiftmodule has a temporary filename and swift-api-digester won't be able to load it. This limitation could probably be lifted in the future.https://github.com/apple/swift/pull/37991
, and uses the new -disable-fail-on-error option so that when a breaking change is detected we don't mark the build as failed. I think this is the usually the right behavior, but we could make it configurable.The new flags are:
-emit-(api|abi)-baseline
,-emit-(api|abi)-baseline-path
: emit a baseline JSON file for the module being emitted-compare-to-(api|abi)-baseline-path
: compare the API/ABI of the module being emitted to the baseline at-serialize-(api|abi)-breaking-changes-path
: serialize the errors emitted by swift-api-digester instead of printing them to stdout-(api|abi)-breakage-allowlist-path
: specify a list of breaking changes which should be ignoredThis is just my first pass at the feature, so any and all feedback is welcome. Thanks to @nkcsgexi for the idea!