dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.22k stars 1.35k forks source link

Consider logging BeforeTargets/AfterTargets/DependsOn for each target #4936

Open KirillOsenkov opened 4 years ago

KirillOsenkov commented 4 years ago

I wonder what's the best way to get the target graph information. Should this get logged during evaluation? We do log the ParentTarget here: https://github.com/microsoft/msbuild/blob/8eda0fac789ac3314a14bf002bd9b6e8ab382aca/src/Framework/TargetStartedEventArgs.cs#L165

But would be nice to get high fidelity information

rainersigwald commented 4 years ago

This gets complicated, because the reasonable mental model for how target dependencies work (a directed acyclic graph of targets with edges determined by DependsOnTargets, BeforeTargets, and AfterTargets) is not how the actual dependencies are implemented, in user-observable (and user-manipulable) ways.

The real implementation is that targets are pushed and popped off a stack as their dependencies are considered. This results in the documented ordering rules for MSBuild targets.

The consequence of the stack-based implementation is that the logged data is completely accurate: exactly one target caused the target in question to be built, for exactly one reason.

That's not the full picture; when trying to understand builds it's completely reasonable to want to know "ok, but if that hadn't been there, what would have happened?". For instance, "is there another target that this target would have run after/before", or "what targets depend on this target?"

Unfortunately, the stack manipulations are dynamic, so simply logging the value of DependsOn and friends at the end of evalution isn't sufficient; another target run a the right time can change a property and affect dependencies.

It might be possible to add a log event at the relevant target-stack transition points, like https://github.com/microsoft/msbuild/blob/9c33693c492a0cb99474dcb703bfd0947056d8a9/src/Build/BackEnd/Components/RequestBuilder/TargetBuilder.cs#L414-L416

and other calls to PushTargets.

I think it'd have to be an entirely new log event, though, and possibly one per dependency type.

rainersigwald commented 4 years ago

We might also be able to store the true expanded values of those attributes at the place I mentioned, then pass them along to the place that the current target-started event gets fired and add them to new fields there.

KirillOsenkov commented 4 years ago

It would be nice to just have the expanded actual values for these attributes, just to see what they evaluated to.

I could add hyperlinks from a target to any of its DependsOnTargets, BeforeTargets or AfterTargets targets:

image

tmat commented 4 years ago

Not sure if this feature would address it, but sometimes I see a grayed out target and I don't understand why it wasn't executed. This doc: https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/Viewer-UI lists multiple possible reasons for a target to not log any messages. It would be really useful to know which of the reasons is it.