Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
YuliiaKovalova committed Aug 23, 2023
2 parents b53cd42 + 6b320c1 commit 06e4571
Showing 1 changed file with 71 additions and 22 deletions.
93 changes: 71 additions & 22 deletions src/MSBuildLocator/DotNetSdkLocationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ namespace Microsoft.Build.Locator
internal static class DotNetSdkLocationHelper
{
private static readonly Regex VersionRegex = new Regex(@"^(\d+)\.(\d+)\.(\d+)", RegexOptions.Multiline);
private static readonly Regex SdkRegex = new Regex(@"(\S+) \[(.*?)]$", RegexOptions.Multiline);
private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
private static readonly string ExeName = IsWindows ? "dotnet.exe" : "dotnet";
private static readonly string? DotnetPath = ResolveDotnetPath();

static DotNetSdkLocationHelper() => LoadHostFxr();

Expand Down Expand Up @@ -69,7 +68,11 @@ public static IEnumerable<VisualStudioInstance> GetInstances(string workingDirec
}
}

private static IEnumerable<string> GetDotNetBasePaths(string workingDirectory)
/// <summary>
/// This native method call determines the actual location of path, including
/// resolving symbolic links.
/// </summary>
private static string realpath(string path)
{
string? bestSDK = GetSdkFromGlobalSettings(workingDirectory);
if (!string.IsNullOrEmpty(bestSDK))
Expand Down Expand Up @@ -97,34 +100,80 @@ private static void LoadHostFxr()
}
}

private static IntPtr HostFxrResolver(Assembly assembly, string libraryName)
private static string FindDotnetFromEnvironmentVariable(string environmentVariable, string exeName)
{
var hostFxrLibName = "libhostfxr.dylib";
string dotnet_root = Environment.GetEnvironmentVariable(environmentVariable);
if (!string.IsNullOrEmpty(dotnet_root))
{
string fullPathToDotnetFromRoot = Path.Combine(dotnet_root, exeName);
if (File.Exists(fullPathToDotnetFromRoot))
{
if (!IsWindows)
{
fullPathToDotnetFromRoot = realpath(fullPathToDotnetFromRoot) ?? fullPathToDotnetFromRoot;
return File.Exists(fullPathToDotnetFromRoot) ? Path.GetDirectoryName(fullPathToDotnetFromRoot) : null;
}

return dotnet_root;
}
}

if (!hostFxrLibName.Equals(libraryName, StringComparison.Ordinal) || string.IsNullOrEmpty(DotnetPath))
return IntPtr.Zero;
return null;
}

var hostFxrRoot = Path.Combine(DotnetPath, "host", "fxr");
if (Directory.Exists(hostFxrRoot))
private static IEnumerable<string> GetDotNetBasePaths(string workingDirectory)
{
string dotnetPath = null;
string exeName = IsWindows ? "dotnet.exe" : "dotnet";

// First check for the DOTNET_ROOT environment variable, as it's often there as with, for example, dotnet format.
if (IntPtr.Size == 4)
{
// Agreed to load hostfxr from the highest version
var hostFxrAssemblyDirectory = Directory.GetDirectories(hostFxrRoot)
.OrderByDescending(d => d)
.FirstOrDefault();
// 32-bit architecture
dotnetPath ??= FindDotnetFromEnvironmentVariable("DOTNET_ROOT(x86)", exeName);
}
else if (IntPtr.Size == 8)
{
// 64-bit architecture
dotnetPath ??= FindDotnetFromEnvironmentVariable("DOTNET_ROOT", exeName);
}

if (hostFxrAssemblyDirectory != null)
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))
{
var hostfxrAssembly = Directory.GetFiles(hostFxrAssemblyDirectory)
.Where(filePath => hostFxrLibName.Equals(libraryName, StringComparison.Ordinal))
.FirstOrDefault();

if (hostfxrAssembly != null)
return NativeLibrary.TryLoad(hostfxrAssembly, out var handle) ? handle : IntPtr.Zero;
string filePath = Path.Combine(dir, exeName);
if (File.Exists(filePath))
{
if (!IsWindows)
{
filePath = realpath(filePath) ?? filePath;
if (File.Exists(filePath))
{
dotnetPath = Path.GetDirectoryName(filePath);
break;
}
else
{
continue;
}
}

dotnetPath = dir;
break;
}
}
}

return IntPtr.Zero;
}
if (dotnetPath is null)
{
throw new InvalidOperationException("Could not find the dotnet executable. Is it on the PATH?");
}

private static string SdkResolutionExceptionMessage(string methodName) => $"Failed to find all versions of .NET Core MSBuild. Call to {methodName}. There may be more details in stderr.";

Check failure on line 178 in src/MSBuildLocator/DotNetSdkLocationHelper.cs

View workflow job for this annotation

GitHub Actions / build

The modifier 'private' is not valid for this item

Expand Down

0 comments on commit 06e4571

Please sign in to comment.