-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Add support for parseable-output straight from the frontend #34417
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
@swift-ci Please Test Source Compatibility |
@swift-ci Please Smoke Test |
@swift-ci Please Smoke Test Windows platform |
2 similar comments
@swift-ci Please Smoke Test Windows platform |
@swift-ci Please Smoke Test Windows platform |
b6a53c7
to
63c51dd
Compare
@swift-ci Please Smoke Test |
63c51dd
to
24ca496
Compare
@swift-ci Please Smoke Test |
@swift-ci Please Smoke Test Linux Platform |
24ca496
to
e9a5203
Compare
@swift-ci Please Smoke Test |
@swift-ci Please smoke Test |
e9a5203
to
477c0a8
Compare
@swift-ci Please Test |
@swift-ci Please Test Source Compatibility |
#include "swift/Basic/LLVM.h" | ||
#include "swift/Basic/TaskQueue.h" | ||
#include "swift/Driver/Job.h" | ||
#include "swift/Frontend/Frontend.h" |
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.
Including Driver and Frontend headers from Basic is a layering violation. When we have to violate layering, we usually try to use forward declarations in the header and only import in the implementation, but it'd be better to avoid it entirely.
It looks like what's happening here is that you're trying to create equivalent entry points that take a driver::Job
and a CompilerInvocation
and share their implementation behind the scenes. Instead, I would create a common-currency type that captures the information about a job that parseable_output cares about, and then write conversion functions in Driver and Frontend respectively to construct this type from driver::Job
and CompilerInvocation
. (Alternatively, have a superclass in Basic that both of these classes subclass.) That will separate the components in Basic
more cleanly from the details of the driver and frontend.
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.
Thank you for pointing this out.
The implementation's Message
types already lended themselves pretty nicely to being separated in this fashion with some core basics being kept in a Basic
library. The specific portions have now been split into their new homes in Driver
and Frontend
.
lib/Basic/ParseableOutput.cpp
Outdated
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension( | ||
llvm::sys::path::extension(output)), | ||
output)); |
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'm not sure it's a good idea to use lookupTypeForExtension()
like this. A build system could pass filenames with no extension or the wrong extension; if they do, we should still treat these correctly, using a file type based on which field in the supplementary output path field we found the path in. (This probably means forEachSetOutput
would pass the file type to the lambda.)
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 a great observation, thank you. We do indeed have all the information we need to determines this based on action and known file type instead of inferring it. I modified forAllOutputPaths
to pass along the filetype.
// If we got this far, we need to suppress the output of the | ||
// PrintingDiagnosticConsumer to ensure that only the parseable-output | ||
// is emitted | ||
PDC.setSuppressOutput(true); |
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.
Just checking: We're disabling the PrintingDiagnosticConsumer instead of never adding it in the first place because we need the PDC while we're parsing arguments, including the argument that sets this option?
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.
Exactly. In fact, it seems that this is why setSuppressOutput
exists in the first place.
5d34735
to
c9d21e0
Compare
@brentdax Thank you for such thorough and insightful feedback. |
@swift-ci please test |
Build failed |
Build failed |
ba2f677
to
789504e
Compare
@swift-ci please test |
@swift-ci please test Windows platform |
@swift-ci please test |
Build failed |
@swift-ci please test |
Build failed |
ed24243
to
709b55c
Compare
@swift-ci please test |
@brentdax ping. The feedback above has been addressed, I believe. |
…primary messages for batched jobs Inside swift-frontend
Starting at a crude -1000, each invocation primary input will get its own unique quasi-Pid. Invocations with only one primary (non-batch) will get a real OS Pid. The selection of the constant starting point matches what the driver does when outputting its parseable output.
…d Parseable-Output mode
709b55c
to
234c49c
Compare
@swift-ci please test |
Build failed |
@swift-ci please test macOS platform |
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.
Much better! I have a couple nits to pick, but this has the right shape now.
struct DetailedMessagePayload { | ||
std::string Executable; | ||
SmallVector<std::string, 16> Arguments; | ||
std::string CommandLine; | ||
SmallVector<CommandInput, 4> Inputs; | ||
SmallVector<OutputPair, 8> Outputs; | ||
}; |
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 type ought to have a doc comment.
I'd also like you to think carefully about its name. Yes, from the perspective of the emit*Message()
functions, this is the payload of the DetailedMessage
you're emitting. But that's an implementation detail of this subsystem.
A better type name would come from asking, "what is this type to the clients of this header"? I might call it something like a "job description" or "process info" or maybe a "quasi-invocation" or something. I'll leave the exact decision to you.
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.
Thank you for the insight, I fully agree.
I have renamed the type and it now has a doc to describe its purpose.
…tend Introducing new entry-points that can be used from both Driver and Frontend clients, using an intermediary new type: `DetailedMessagePayload`, when needed.
234c49c
to
915186a
Compare
@swift-ci please test |
1 similar comment
@swift-ci please test |
This PR adds initial support for emitting parseable-output JSON directly from
swift-frontend
."began" and "finished" messages are currently supported.
Basic
and extended with entry-points that accept aCompilerInvocation
of aswift-frontend
, in addition to existing entry-points used by the Driver that accept aJob
.Note: The code in ParseableOutput.h and ParseableOutput.cpp with a
Job
-based interface is not new. I tried moving these files carefully to preserve history, but enough stuff seems to have changed to not get nice diffs here.