diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs index 272471bd3..74abc2a61 100644 --- a/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs +++ b/src/Microsoft.DotNet.MSBuildSdkResolver/Interop.NETStandard.cs @@ -7,6 +7,7 @@ // on non-Windows machines. #if NETSTANDARD1_5 +using System; using System.Runtime.InteropServices; using System.Text; @@ -16,6 +17,14 @@ namespace Microsoft.DotNet.MSBuildSdkResolver { internal static readonly bool RunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + internal static string realpath(string path) + { + var ptr = unix_realpath(path, IntPtr.Zero); + var result = Marshal.PtrToStringAnsi(ptr); // uses UTF8 on Unix + unix_free(ptr); + return result; + } + private static int hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size) { // hostfxr string encoding is platform -specific so dispatch to the @@ -31,6 +40,13 @@ namespace Microsoft.DotNet.MSBuildSdkResolver // CharSet.Ansi is UTF8 on Unix [DllImport("hostfxr", EntryPoint = nameof(hostfxr_resolve_sdk), CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] private static extern int unix_hostfxr_resolve_sdk(string exe_dir, string working_dir, [Out] StringBuilder buffer, int buffer_size); + + // CharSet.Ansi is UTF8 on Unix + [DllImport("libc", EntryPoint = nameof(realpath), CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr unix_realpath(string path, IntPtr buffer); + + [DllImport("libc", EntryPoint = "free", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + private static extern void unix_free(IntPtr ptr); } } diff --git a/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs b/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs index f5195f839..08a552479 100644 --- a/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs +++ b/src/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs @@ -174,8 +174,18 @@ namespace Microsoft.DotNet.MSBuildSdkResolver } var environmentProvider = new EnvironmentProvider(_getEnvironmentVariable); + var dotnetExe = environmentProvider.GetCommandPath("dotnet"); - return Path.GetDirectoryName(environmentProvider.GetCommandPath("dotnet")); +#if NETSTANDARD1_5 + if (dotnetExe != null && !Interop.RunningOnWindows) + { + // e.g. on Linux the 'dotnet' command from PATH is a symlink so we need to + // resolve it to get the actual path to the binary + dotnetExe = Interop.realpath(dotnetExe) ?? dotnetExe; + } +#endif + + return Path.GetDirectoryName(dotnetExe); } } }