Skip to content

Conversation

@jjonescz
Copy link
Member

@jjonescz jjonescz commented Oct 23, 2025

Fixes dotnet/msbuild#12669. Before the change to use csc apphost, we were searching for dotnet.exe either from DOTNET_HOST_PATH or PATH. With csc apphost (#80026) we regressed this by considering the dotnet host only from DOTNET_HOST_PATH (and passing that as DOTNET_ROOT to the apphost) - but that variable is not passed in MSBuilds older than 18.x (where the previous non-apphost implementation would work fine since it would fallback to finding dotnet.exe in PATH).

@jjonescz jjonescz marked this pull request as ready for review October 23, 2025 14:05
@jjonescz jjonescz requested a review from a team as a code owner October 23, 2025 14:05
@jjonescz
Copy link
Member Author

jjonescz commented Oct 27, 2025

@333fred @RikkiGibson @dotnet/roslyn-compiler for a second review, thanks. This fixes a regression.

internal static string? GetToolDotNetRoot()
{
if (GetDotNetHostPath() is { } dotNetHostPath)
var directoryName = Path.GetDirectoryName(GetDotNetPathOrDefault());
Copy link
Member

Choose a reason for hiding this comment

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

It looks like before we were looking specifically for the directory containing a suitable .NET runtime installation?

But now we are searching the path, and the dotnet we find on the PATH might be linked into a location like /usr/bin/dotnet. Is it fine to just return /usr/bin from this call?

Copy link
Member Author

Choose a reason for hiding this comment

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

But now we are searching the path, and the dotnet we find on the PATH might be linked into a location like /usr/bin/dotnet. Is it fine to just return /usr/bin from this call?

Good catch, that wouldn't work. I guess we can resolve symlinks first.

return s;
}

private const uint FILE_READ_ATTRIBUTES = 0x0080;
Copy link
Member

Choose a reason for hiding this comment

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

Where do these values come from? What documentation can I look at to verify them?

Copy link
Member Author

Choose a reason for hiding this comment

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

var symlinkPath = Path.Combine(binDir.Path, $"dotnet{PlatformInformation.ExeExtension}");

// Create symlink from binDir to the actual dotnet executable
File.CreateSymbolicLink(path: symlinkPath, pathToTarget: globalDotNetExe.Path);
Copy link
Member

Choose a reason for hiding this comment

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

Does this test need to be Windows-only?

Copy link
Member Author

Choose a reason for hiding this comment

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

Why? Symlinks are a thing especially on Linux.

//------------------------------------------------------------------------------
extension(File)
{
public static FileSystemInfo? ResolveLinkTarget(string path, bool returnFinalTarget)
Copy link
Member

Choose a reason for hiding this comment

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

Does this work on Linux/Mac?

Copy link
Member Author

@jjonescz jjonescz Oct 30, 2025

Choose a reason for hiding this comment

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

No, but on Linux, we run on .NET Core where the File.ResolveLinkTarget API exists from the BCL. This custom Win32 polyfill is defined only for .NET Framework (which I think we only support on Windows? I'm not sure about Mono, but given the other NativeMethods are also win32 APIs, this seems fine).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Known Issue: .NET 10.0.100-rc.2 can fail to launch the C# compiler when used in Visual Studio 2022

4 participants