-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Skip MSBuild and call only CSC for simple file-based apps #49528
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
base: main
Are you sure you want to change the base?
Conversation
272c4ca
to
e9eae7a
Compare
@@ -32,6 +32,7 @@ | |||
<add key="richnav" value="https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-buildservices/nuget/v3/index.json" /> | |||
<!-- mstest dependencies --> | |||
<add key="test-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/test-tools/nuget/v3/index.json" /> | |||
<add key="temporary" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json" /> |
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 should go away before the PR is merged. I'm using this to get a test build of the BuildClient package before dotnet/roslyn#78986 is merged and we have an official build.
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.
nice!
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.
Concern: How is output handled? MSBuild has lots of handling of error situations and things. So, skipping that, what do we see when doing certain "normal" failure scenarios? I see some of the tests handle some of the CS#### errors. I'm not familiar with how/if MSBuild translates or supersedes those.
@RikkiGibson @chsienki @jaredpar for reviews, thanks |
Directory.CreateDirectory(binDir); | ||
|
||
string assemblyAttributes = Path.Join(objDir, $".NETCoreApp,Version=v{TargetFrameworkVersion}.AssemblyAttributes.cs"); | ||
if (ShouldEmit(assemblyAttributes)) |
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.
Could you please explain why we need the ability to create the auxiliary files here? I was hoping these would just be on disk from a previous msbuild run, and if they are not, then we just run msbuild and save the csc optimization for the next time.
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.
The motivation for this optimization is to make even the first run faster as per @jaredpar's comment: #48011 (comment).
The limitation is that only simple apps can be optimized like this (due to the need of hard-coding the csc arguments and the auxiliary files). The advantage is that even the first run is fast. Next, though, I'd like to add an optimization where msbuild results would be re-used like you say and that should work for any apps. We won't need to hard-code any auxiliary files nor csc arguments for those (we can just extract them from the prior msbuild run), but they don't work on the first run. Both optimizations can work side-by-side in different scenarios.
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 I buy this, thanks. I am using file-based apps with no directives a significant amount already.
I am interested to see how it works in practice, as we insert new compilers, new versions of standard references get introduced, etc. and the arguments evolve. Possibly there will be various PRs where we just need to jump in and rerun the generator. And since this is the type of codegen that we would really like to manually review, it seems good for the generated code to be version controlled, require an explicit step to change it, and so on.
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.
...should we just encode this generation into an MSBuild Target? It should be pretty easy to make a one-off task in the src/Layout/redist.csproj Targets that
- builds a 'simple' .NET app using the targets in the SDK's 'stage 2' SDK layout
- grabs the CSC command line from that (it's available as a project/etc)
- writes that data to whatever file you need
and does so in a highly-incremental way to not impact inner loop builds too badly.
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.
should we just encode this generation into an MSBuild Target?
I've considered that and I chose the current approach so that changes in the generated code need to be reviewed since they are included in Git (as Rikki also mentioned).1 Mainly because I'm not 100% confident that the code generator is perfect and hence I'd like to see how the generated code changes over time, at least in the beginning, we can move it to be a more automatic part of the build process (via a Target) later if that sounds good to you?
Note that we have a prior work: CLI completion snapshots are also generated by tests.
builds a 'simple' .NET app using the targets in the SDK's 'stage 2' SDK layout
Wouldn't this mean that the generated code couldn't be included in the SDK which is being built because the CLI DLL is already built at this point?
Footnotes
-
If the generated code came from a target, presumably that wouldn't be Git-tracked (otherwise I'm not sure what would be the advantage of a Target over a test). ↩
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.
LGTM with some questions and minor comments.
Part of #48011.
With this PR, simple file-based apps (with no
#:
directives, no implicit build files, no command-line-property
switches) use C# compiler (via the compiler server), skipping MSBuild altogether. That can improve time ofdotnet run file.cs
significantly as the following table shows.(UPDATE: Figured out that "no build" is slower than "csc" because the csc optimized path doesn't need to invoke MSBuild to do project evaluation to figure out the target command to run, whereas the no-build path still does that. I will look into improving that in a follow up.)
The next step will be to skip MSBuild for more complex file-based apps as well (by reusing csc arguments from the previous msbuild run).
Resolves #49478 (sdk and runtime version is now included in the cache and build isn't skipped if those are different between the previous and current run).