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

Respect DOTNET_ROOT #225

Merged
merged 4 commits into from
Aug 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 49 additions & 15 deletions src/MSBuildLocator/DotNetSdkLocationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ public static IEnumerable<VisualStudioInstance> GetInstances(string workingDirec
}
}

/// <summary>
/// This native method call determines the actual location of path, including
/// resolving symbolic links.
/// </summary>
private static string realpath(string path)
{
IntPtr ptr = NativeMethods.realpath(path, IntPtr.Zero);
Expand All @@ -86,33 +90,63 @@ private static string realpath(string path)
return result;
}

private static string FindDotnetFromEnvironmentVariable(string environmentVariable, string exeName)
{
string dotnet_root = Environment.GetEnvironmentVariable(environmentVariable);
if (!string.IsNullOrEmpty(dotnet_root))
{
string fullPathToDotnetFromRoot = Path.Combine(dotnet_root, exeName);
if (File.Exists(fullPathToDotnetFromRoot))
{
return realpath(fullPathToDotnetFromRoot) ?? fullPathToDotnetFromRoot;
}
}

return null;
}

private static IEnumerable<string> GetDotNetBasePaths(string workingDirectory)
{
string dotnetPath = null;
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
string exeName = isWindows ? "dotnet.exe" : "dotnet";

// We will generally find the dotnet exe on the path, but on linux, it is often just a 'dotnet' symlink (possibly even to more symlinks) that we have to resolve
// to the real dotnet executable.
// This will work as often as just invoking dotnet from the command line, but we can be more confident in finding a dotnet executable by following
// 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))
// First check for the DOTNET_ROOT environment variable, as it's often there as with, for example, dotnet format.
if (IntPtr.Size == 4)
{
string filePath = Path.Combine(dir, exeName);
if (File.Exists(filePath))
// 32-bit architecture
dotnetPath ??= FindDotnetFromEnvironmentVariable("DOTNET_ROOT(x86)", exeName);
}
else if (IntPtr.Size == 8)
{
// 64-bit architecture
dotnetPath ??= FindDotnetFromEnvironmentVariable("DOTNET_ROOT", exeName);
}

if (dotnetPath is null)
{
// We will generally find the dotnet exe on the path, but on linux, it is often just a 'dotnet' symlink (possibly even to more symlinks) that we have to resolve
// to the real dotnet executable.
// This will work as often as just invoking dotnet from the command line, but we can be more confident in finding a dotnet executable by following
// 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 (!isWindows)
string filePath = Path.Combine(dir, exeName);
if (File.Exists(filePath))
{
filePath = realpath(filePath) ?? filePath;
if (!File.Exists(filePath))
if (!isWindows)
{
continue;
filePath = realpath(filePath) ?? filePath;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment would be helpful here ('unwrapping symlinks' or so)

if (!File.Exists(filePath))
{
continue;
}
}
}

dotnetPath = Path.GetDirectoryName(filePath);
break;
dotnetPath = dir;
break;
}
}
}

Expand Down
Loading