Skip to content
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

Setting ProvideCommandLineArgs to the Csc/Vbc task includes non-Csc args #67102

Closed
jasonmalinowski opened this issue Feb 28, 2023 · 9 comments · Fixed by #68918
Closed

Setting ProvideCommandLineArgs to the Csc/Vbc task includes non-Csc args #67102

jasonmalinowski opened this issue Feb 28, 2023 · 9 comments · Fixed by #68918
Assignees
Milestone

Comments

@jasonmalinowski
Copy link
Member

jasonmalinowski commented Feb 28, 2023

ProvideCommandLineArgs is a switch on the Csc/Vbc build tasks which lets the task produce as an output the arguments that will be passed to Csc. It doesn't quite work right however in .NET Core: since the tool task in that case doesn't invoke csc.exe but instead tries to invoke "dotnet.exe exec csc.dll"..., the "exec" and "csc.dll" also appear in the ProvideCommandLineArgs. This throws off project systems since we then take the command line args and pass them to the command like parser, so logically you have a source file named "exec"... 😄

Steps to Reproduce:

  1. Create a new dotnet console app project.
  2. Add <ProvideCommandLineArgs>true</ProvideCommandLineArgs>
  3. dotnet build -bl
  4. Look at the output items of the Csc task:

image

In this case, we'd expect the CscCommandLineArgs are just the parts going to csc, excluding the parts going to dotnet.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Feb 28, 2023
@tmeschter
Copy link
Contributor

Tangent: I thought those items would only be created during a design-time build. They seem like overhead in a real build. Or does something other than the project system use them?

@jasonmalinowski
Copy link
Member Author

@tmeschter: you have to set the property; although I see right now that GitHub thought my instructions were XML and didn't show them.

@jcouv
Copy link
Member

jcouv commented Apr 20, 2023

Tagging @jaredpar to advise/triage.

@jaredpar
Copy link
Member

They seem like overhead in a real build. Or does something other than the project system use them?

Lots of tools use them in real builds. It is immensely valuable to know what the actual invocation of csc was. Really helpful for recreating Compilation instances. Concrete example is here: https://github.com/jaredpar/basic-compiler-logger

@jaredpar
Copy link
Member

In this case, we'd expect the CscCommandLineArgs are just the parts going to csc, excluding the parts going to dotnet.

Sorry but I think this is a case where your expectations are just off. It is important to know the exact command line used by the compiler, particularly when root causing build failures. Other tools depend on this being there.

It's unfortunate that invocation can take so many forms but that is the reality. If the IDE needs to dig past dotnet then you can implement logic similar to here to do so

https://github.com/jaredpar/basic-compiler-logger/blob/main/src/Basic.CompilerLog.Util/BinaryLogUtil.cs#L227

@jasonmalinowski
Copy link
Member Author

jasonmalinowski commented May 10, 2023

case where your expectations are just off

@jaredpar: The support to the build tasks to produce a command line argument was originally added in this pull request to be used for design time builds, I'd absolutely expect that it's still usable for that purpose! Separately, if the item group was "DotnetArguments" I wouldn't be so worried, but it's named Csc arguments specifically.

Other tools depend on this being there.

Which tools? I don't have a sense of what we break if we change this but sounds like you do know of some tools out there. If there's other tools also breaking and having to work around this, then I wonder what the greater good is here.

If the IDE needs to dig past dotnet then you can implement logic similar to here to do so

That looks terribly fragile, especially if any other arguments ever had to get passed to dotnet.exe directly. I can think of other approaches, for example, having the build task mark the created MSBuild items with metadata for the ones that are "not really CSC" and then the tools can filter that more generally that'd be a good approach. If nothing else, if we did want to go with that approach we really need to formalize that approach and have tests in place to ensure it's never broken further, and figure out all the places that fix needs to go into.

I'm going to reactivate this bug just since right now we're not tracking this issue anywhere else, and I don't want this to fall of the radar. And as said, from the project system's perspective the thing that was created for its use isn't working right. If we do have tools that now depend on that behavior and fixing them is worse than the tools that all have to work around this, and we need to figure out a new approach, great, but let's use this bug to track and drive that discussion. (And if we need to spin a up a meeting between impacted parties happy to do that too!)

@jaredpar
Copy link
Member

jaredpar commented May 10, 2023

I'd absolutely expect that it's still usable for that purpose!

How is it not usable? Yes there is extra information here but it can easily be bypassed to get the information the design time build needs. I provided sample code to demonstrate where this can be done.

Which tools?

I listed a specific example in my previous comment. You can look to others like binary log viewer for tools that depend on the task args. I've also listed the importantance of this for debugging purposes.

That looks terribly fragile, especially if any other arguments ever had to get passed to dotnet.exe directly.

I disagree. The code is straight forward and there are no plans to change how the dotnet tool is invoked. If it ever does change then we can adjust the logic to work around it.

I'm going to reactivate this bug just since right now we're not tracking this issue anywhere else, and I don't want this to fall of the radar

Okay but at the moment I'm not convinced this code needs to be changed. The existing information is sufficient to solve the problem. The code has been this way for a considerable amount of time so I'm skeptical about the need, urgency around changing this.

@tmat
Copy link
Member

tmat commented Jul 6, 2023

@jaredpar

Sorry but I think this is a case where your expectations are just off. It is important to know the exact command line used by the compiler, particularly when root causing build failures. Other tools depend on this being there.

I understand the value of having full command line in the log for investigations.

The binlog actually contains the full command line for the task and using CscCommandLineArgs is not necessary for that:
image

Isn't that what basic-compilerlog tool is reading (using TaskCommandLineEventArgs binlog type)?

The values passed to CscCommandLineArgs are clearly incorrect.

The comment in
https://github.com/jaredpar/basic-compilerlog/blob/main/src/Basic.CompilerLog.Util/BinaryLogUtil.cs#L287
says: "The argument list is going to include either dotnet exec csc.dll or csc.exe."

It seems to be reading the command line from TaskCommandLineEventArgs, not from CscCommandLineArgs.

When building using dotnet the argument list actually does not include the path to "dotnet.exe". It only includes "exec" and path to "csc.dll".
image

On desktop it does not include the path to csc.exe.
image

CscCommandLineArgs thus doesn't inform me what tool is actually running the compiler. It's not the "exact" command line.

Besides, the name CscCommandLineArgs is misleading since "exec" is not an argument of csc.

@jaredpar
Copy link
Member

jaredpar commented Jul 6, 2023

Thanks for the break down there. I was confusing the two items for being one entry.

Dug into this a bit to see where the two values are coming from:

  • CommandLineArguments value is coming from ToolTask.Execute. Feel that essentially remain the same because it should be a faithful representation of the command that is executed.
  • CscCommandLineArgs is actually command from ManagedCompiler.CommandLineArgs. The targets file is what does the name mapping. Agree that can be modified safely.

Having these values be CommandLineArguments and CommandLineArgs is not confusing at all when reading the code 🤦. I'm tempted to clean that up and give it a better differentiated name.

@jaredpar jaredpar modified the milestones: Backlog, 17.8 Jul 6, 2023
@jaredpar jaredpar self-assigned this Jul 6, 2023
jaredpar added a commit that referenced this issue Jul 11, 2023
This changes our build tasks to remove the host specific args, namely the `exec ...\csc.dll`, from the `CommandLineArgs` property. That `ITaskItem[]` is meant for the IDE consumption and doesn't need host specific information. 

As a part of fixing this bug I cleaned up a lot of unnecessary member inheritance in the build tasks. There were several `virtual` members where every implementation had the same code. Moved all that up to the base and cleaned up the comments to make the intent clearer. 

closes #67102

Co-authored-by: Jared Parsons <jared@popcornbear.org>
Co-authored-by: Chris Sienkiewicz <chsienki@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants