From 747e9fd6adc189d12a418fd4bac978c4b1582369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 12 Jul 2017 16:33:29 +0200 Subject: [PATCH] MSBuildSdkResolver: resolve symlink for 'dotnet' binary On Linux the dotnet installed by the dotnet packages is a symlink (/usr/bin/dotnet -> ../share/dotnet/dotnet). We need to resolve the symlink so we're passing the path to the actual .NET Core installation to libhostfxr. Fixes https://github.com/dotnet/cli/issues/7125 --- .../Interop.NETStandard.cs | 16 ++++++++++++++++ .../MSBuildSdkResolver.cs | 12 +++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) 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); } } }