-
Notifications
You must be signed in to change notification settings - Fork 83
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
Use dotnet from current process if possible #203
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.
This change may break someone. If MSBuildLocator is running under a private runtime, it would now be enumerating only private SDKs in the corresponding directory. Is this really what we want?
// https://github.com/dotnet/designs/blob/main/accepted/2021/install-location-per-architecture.md | ||
// This can be done using the nethost library. We didn't do this previously, so I did not implement this extension. | ||
foreach (string dir in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) | ||
if (Process.GetCurrentProcess().ProcessName.Equals(exeName)) |
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.
On Windows the ProcessName
property does not include the trailing .exe
so I'm afraid this won't work.
What do you mean by a private runtime? I'd assume the only relevant runtime here is the .NET runtime. Since this is intended to be process-specific, I was thinking it would only affect things hosted in the dotnet process, which would mean first-party only. I think it's reasonable in that case to prioritize the dotnet they are actively using. @rainersigwald, do you have an opinion? |
.NET runtime is xcopy-able and may exist in many copies on the machine, including copies used only by a specific app. Consider the case where I use MSBuildLocator in an app which runs on its copy of the runtime, like for example on what's under What is the motivation for this change? |
I guess I was mostly thinking of/motivated by the opposite case, where you unzip an SDK to some random spot on disk without adding it to PATH, then build. Ideally, we'd be able to detect that SDK and use it if there are no other SDKs available and offer it if possible. I changed this to search both where it had been searching and next to the process it's running in if it's running in dotnet. It should only throw if it fails to find dotnet in either location. Does that sound like a more appropriate way to find both safely? |
|
||
if (!returnedSDKs) | ||
{ | ||
throw new InvalidOperationException("Failed to find an appropriate version of .NET Core MSBuild. Call to hostfxr_resolve_sdk2 failed. There may be more details in stderr."); |
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: It doesn't look like getting here necessarily implies that hostfxr_resolve_sdk2
failed. We may have simply found no SDKs.
Makes perfect sense!
I think so. It's hard for me to guess what all the use cases are. As long as the caller can then choose the SDK to use, I'd say returning both locations is a good approach. It just shouldn't return duplicates, which I believe would happen with the code as it is written now if we're running on a regularly installed runtime. |
It does, and I've been wrestling with this a bit. I'm not a huge fan of on-the-fly deduplication code in general, first because it sometimes erases subtle ordering decisions (like that the first SDK is potentially the one from the global.json, whereas the rest are "normal") and second because it tends to be less efficient. The first version of this only did the second check (current process) if the first version found no SDKs, but I decided that wasn't necessarily desirable. I'll see if I can implement some deduplication logic today. |
@@ -112,34 +115,110 @@ private static IEnumerable<string> GetDotNetBasePaths(string workingDirectory) | |||
dotnetPath = Path.GetDirectoryName(isWindows ? dotnetPath : realpath(dotnetPath) ?? dotnetPath); | |||
} | |||
|
|||
string pathOfPinnedSdk = string.Empty; | |||
|
|||
foreach (string path in GetDotNetBasePaths(workingDirectory, dotnetPath)) |
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.
What's your thinking on preferring the PATH search to the current executable? I could see that going either 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 agree it could go either way...in this case, since I'm adding them all to a HashSet rather than a List (for deduplication), I'm not actually preferring one above the other. I'm just going by version number and mixing them up. (I also see an argument for keeping them separate...but I'm not sure how valuable that is, and I honestly don't think the "from current process" code path will be important all that often.)
{ | ||
pinnedSdk = 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.
What is a "pinned" sdk?
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 would be like if you have a global.json. Is there a better name that would've made that clear?
@baronfel please take a look |
Implemented in scope of #230 |
If we are running in a dotnet executable, we should use that instead of trying to find it on the PATH.