-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Implements targets that calculate PathMap from SourceRoots #25325
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
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.
@jaredpar Can these 3 issues with PathMap be addressed in 15.7 so we can clean this up?
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.
@jaredpar Ping.
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.
Is this asking to add a new warning / error to the compiler in the default config?
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.
Yes, that's one of the issues. Right now if you pass /deterministic and /pathmap that doesn't cover all paths you don't know that the compiler outputs are still non-deterministic.
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 particular issue is not blocking the SourceLink change. It's the other issues with quoting and escaping that are (to some extent).
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.
Then add a new switch? Or you don't see value in reporting that error?
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.
/deterministic:strict
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.
It's not that I don't see value in the switch, I just understand the constraints we live under. There are scenarios which are far more valuable and easy to detect for which I can't issue new diagnostics.
In reply to: 176509304 [](ancestors = 176509304)
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 scenario is somewhat unique though since one can't write an analyzer that reports these errors currently. We would need to expose a new API that the analyzer could hook into. This would be a callback that's invoked on every path that's embedded into the DLL/PDB. Then an analyzer could hook that and report errors if the paths do not match the PathMap. Would that be a preferred way?
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 guess the analyzer can be written today that finds all the paths that end up embedded into the DLL/PDB, but it'd be hard to keep it up to date with the compiler.
5772897 to
efdc916
Compare
build/scripts/build.ps1
Outdated
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.
Split-Path $dotnet [](start = 30, length = 18)
Should use Split-Path -Parent to make the use explicit here.
build/scripts/build.ps1
Outdated
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.
$env:DOTNET_INSTALL_DIR [](start = 4, length = 24)
This approach overall seems fragile. Our tests run in many contexts, most of which are not driven by this script. Hence there is no way to depend on this value being set.
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.
A better idea? The test runner tries to use the DOTNET_INSTALL_DIR and falls back to looking for the right version of the SDK on PATH.
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.
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.
DotNetSdkTests [](start = 17, length = 14)
If the intent is to test MSBuild you need to be deploying a Directory.Build.props, Directory.Build.targets, and editorconfig that disables parent lookup. That's necessary to make these type of tests stable.
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.
Why editor config?
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.
Good point. I'll add those.
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.
xml doc would be good here too #Closed
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.
Will add. #Resolved
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.
Nit: local functions should be camelCased. If it's ok, please also move to the end of the method. #Closed
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 have actually refactored it a bit here. #Resolved
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.
Will change the casing.
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 looking at iteration 3. Should I wait until you push something more?
In reply to: 176874575 [](ancestors = 176874575)
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.
Please add a link for follow-up issue, rather than just a TODO comment. #Closed
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.
Perhaps sourceControlled? #Closed
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.
Perhaps add comment // root isn't nested #Closed
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.
root.ItemSpec [](start = 56, length = 13)
Perhaps extract local for string path = root.ItemSpec; #Closed
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.
Is there harm to leave the zero in /_0/ in the i==0 case? #Closed
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.
Can or should we assert that there was no metadata called MappedPath on the root before setting our own? #Closed
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.
Maybe "...source-controlled non-nested roots first:" #Closed
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.
Maybe "...other non-nested roots:" #Closed
|
@jcouv I rebased the PR and your comments are not visible here anymore:
No harm, just the common case will be a single root, so I didn't want to include
Good question. we can't assert, but we can report a warning if there is one. Rewriting metadata in msbuild does not usually produce warnings though, so I'm not sure we should here. #Resolved |
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 looked around for a similar UsingTask to import the Csc task. I found it in WriteMSBuildFiles which makes a .props file for the package.
Should we use the same mechanism for the MapSourceRoots task?
#Closed
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.
No, this needs to be in the Microsoft.Managed.Core.targets. These are targets are only used via a package reference if you explicitly drop Microsoft.Net.Compilers to your project. By default these are picked up from msbuild, where we insert them to.
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.
ContinuousIntegrationBuild [](start = 117, length = 26)
Btw, it would be helpful to indicate in your documentation for ContinuousIntegrationBuild that it's a boolean.
https://github.com/tmat/repository-info/tree/master/docs #Closed
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.
Done.
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.
Typo: This target ... #Closed
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.
Fixed.
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 the tests/framework simulating end-to-end msbuild are great, and will be useful for future work with custom targets. I wonder if the msbuild repo has something similar by now (seems it would be useful there too). #Resolved
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 dotnet SDK repo has this kind of test API. The problem is none of these are in a form that's reusable elsewhere. It would indeed be good to create some model that can be reused via a NuGet package.
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.
Consider EnsureEndsWithSlash.
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.
Fixed
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.
var rootByItemSpec = new Dictionary<string, ITaskItem>(); [](start = 1, length = 68)
Why are we using ordinal path comparison here? The compiler is pretty inconsistent here but generally favors insensiitive.
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.
Are you saying we do not support source directories that differ by casing on Linux?
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.
Different parts of the compiler differ here. It's not consistent.
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.
var topLevelMappedPaths = new Dictionary<string, string>(); [](start = 16, length = 59)
Why are we using ordinal path comparison here? The compiler is pretty inconsistent here but generally favors insensiitive.
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.
These paths are generally produced by a source control package (e.g. one based on GitLib library). It is expected that the tool produces paths that have consistent casing. This particular dictionary is used to map submodule paths to their containing source roots. When the submodule paths are produced by the GitLib library they should match the casing exactly.
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.
DotNetSdkTestBase [](start = 34, length = 17)
I have concerns with how this is intended to work. There are really two options to doing MSBuild integration tests
- Use an official layout mechanism to place the compiler binaries on dusk. For example unzipping the compiler NuGet package.
- Adhoc copy the binaries on disk to a single directory.
This test seems to be doing the latter. We've been moving away from that because we've found it's both flaky and it doesn't actually catch all of the issues it's intended to catch. I'm worried we're creating a new case where we're tricking ourselves into believing scenarios are covered that simply aren't.
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 I understand. I'm not copying binaries anywhere. The compiler build task is not even executed in these tests scenarios - I replace the csc target. The only binary that matters for these tests is the one that defines the build tasks. The goal of these tests is to test the .targets files, not the compiler.
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.
That's a bit more stable. Overall though I'm highly skeptical of tests like this. There are reasons we yanked out similar ones for MSBuild. Their sustainability doesn't seem to hold up over 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.
I'd be more than happy to use any other mechanism to test these targets once it's available. I think msbuild or dotnet SDK should come up with a test framework that can be imported as a package. Until that happens though we need to test the targets somehow.
|
test this please #Resolved |
|
test this please |
|
test windows_debug_unit64_prtest please |
|
test windows_release_vs-integration_prtest please |
|
@dotnet/roslyn-compiler Ping. |
jcouv
left a comment
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 Thanks
|
LGTM |
…e extension point for Source Link generator
|
@jaredpar Is any ask mode approval needed for merge? |
|
@tmat yes. Mine 😄. Approved |
|
@jaredpar 👍 Thanks |
Customer scenario
This change is a piece in larger effort to make SourceLink easy to use, robust and compatible with deterministic builds.
See https://github.com/tmat/repository-info/tree/master/docs for an overview of the end-to-end scenario and dotnet/msbuild#2960 for a list of all components that support the scenario.
Bugs this fixes
#25635
Workarounds, if any
Risk
Small.
Performance impact
Small.
Is this a regression from a previous update?
New feature.
Root cause analysis
How was the bug found?
Test documentation updated?
Implementation details
The data flow among msbuild targets involved here is a bit tricky. The high-level design assumes a set of producers and a set of consumers of source control information. Producing targets (e.g. target wrapping a
GitLib) need to execute before consuming targets (e.g. AssemblyInformationalVersion generator, Roslyn compiler, NuSpec generator, etc.), thus they need to synchronize on an in-between target, which isInitializeSourceControlInformationtarget defined in Microsoft.Common.targets.Source control info producer populates
SourceRootitems. They can also be populated from source packages or added manually to the project.MapSourceRootPathstakesSourceRootitems and addsMappedPathto metadata of each item. This is the path that the compiler will generate into the DLL/PDB. It's a path with a deterministic prefix ifDeterministicis true, and the original path otherwise.SourceRootthen flows to the other target defined here that calculatesPathMapbased on theMappedPathmetadata of each root.PathMapis then used bycsctask.SoruceRootalso flows to Source Link generator target (which will be supplied by a SourceLink nuget package), which usesMappedPathand other info on theSourceRootto generatesourcelink.jsonfile that is passed tocsctask.TODO: