runtime: [Preview 4] dotnet sdk check fails when runtimes installed via script
Running dotnet sdk check
throws this exception using dotnet preview4.
➜ dotnet sdk check
System.DllNotFoundException: Unable to load shared library 'hostfxr' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen(libhostfxr, 1): image not found
at Microsoft.DotNet.NativeWrapper.Interop.hostfxr_get_dotnet_environment_info(String dotnet_root, IntPtr reserved, hostfxr_get_dotnet_environment_info_result_fn result, IntPtr result_context)
at Microsoft.DotNet.NativeWrapper.NETBundlesNativeWrapper.GetDotnetEnvironmentInfo(String dotnetExeDirectory) in Microsoft.DotNet.NativeWrapper.dll:token 0x600000f+0x20
at Microsoft.DotNet.Tools.Sdk.Check.SdkCheckCommand.Execute() in dotnet.dll:token 0x60004e0+0x13
at Microsoft.DotNet.Cli.DotNetTopLevelCommandBase.RunCommand(String[] args) in dotnet.dll:token 0x60008af+0x5e
at Microsoft.DotNet.Tools.Sdk.SdkCommand.Run(String[] args) in dotnet.dll:token 0x60004ce+0x6
at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient) in dotnet.dll:token 0x6000918+0x2e8
at Microsoft.DotNet.Cli.Program.Main(String[] args) in dotnet.dll:token 0x6000916+0x6f
Here are the results of my call to dotnet --list-sdks
➜ dotnet --list-sdks
2.1.202 [/Users/khalidabuhakmeh/.dotnet/sdk]
2.1.816 [/Users/khalidabuhakmeh/.dotnet/sdk]
3.0.103 [/Users/khalidabuhakmeh/.dotnet/sdk]
3.1.409 [/Users/khalidabuhakmeh/.dotnet/sdk]
5.0.203 [/Users/khalidabuhakmeh/.dotnet/sdk]
6.0.100-preview.3.21202.5 [/Users/khalidabuhakmeh/.dotnet/sdk]
6.0.100-preview.4.21255.9 [/Users/khalidabuhakmeh/.dotnet/sdk]
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 2
- Comments: 33 (31 by maintainers)
Just to summarize - the plan is to:
dotnet.exe
) to set a new runtime property calledHOSTFXR_PATH
(simplified the name) when launching SDK/CLI (dotnet.dll
).AppContext.GetData("HOSTFXR_PATH")
DllImport
problems - I’ll let interop people advice what is the best way to do this (pre-load viaNativeLibrary
or useDllImportResolver
, or something else)After discussing this with a couple of people I like the idea of muxer helping SDK here. Let me first describe the possible solutions:
hostfxr
in the process. Unfortunately runtime doesn’t have this capability anddlopen
doesn’t do it either. But we do have a solution for this innethost
(well, hopefully - we should try if that solution actually works on M1)nethost
from SDK is tricky (ideally we would use it as a NuGet dependency, but that bring along quite a few other files which we would rather not ship in the SDK)hostfxr
on disk - this is not so bad - there are many things relying on the relative location ofdotnet
andhostfxr
so adding another would not be the end of it.dotnet
) to pass the path to thehostfxr
to the SDK somehow.I like the last solution the best (although technically the cleanest one is using
nethost
) since it’s relatively cheap and relatively clean. (Kudos for this goes to @agocke). I also agree with @elinor-fung that the muxer should not do this unconditionally. But the muxer knows that it’s running SDK - it has special code path to actually execute any SDK command, so it can easily do this only when running SDK. With that there are 2 options:HOSTFXR_FULL_PATH
. SDK would read this viaAppContext
and use it whichever way it wants to (in this case probably using it in theDllImportResolver
).NATIVE_DLL_SEARCH_DIRECTORIES
I find the first one (special new property) cleaner, but it’s more work. If others think that just setting the
NATIVE_DLL_SEARCH_DIRECTORIES
is not too bad, I’d be OK with it as well.[DllImport("hostfxr")]
is doing what we expect it (or any DllImport with just the library name) should, in my opinion - basically going through any extension points and runtime-configured search paths and then it is just ‘let the OS do its default load’ (so whateverdlopen
/LoadLibrary
does on that OS).Making the SDK implement a
DllImportResolver
(as @mateoatr had) makes sense to me. This is the same as would be needed for any other native library that is not part of the app’s deps.json and not next to the app. Unfortunately, that would mean the SDK would have knowledge of the install layout baked into it - I thinkProcess.Modules
only has the main module on macOS, so the implementation couldn’t use that to find the hostfxr that is already loaded.The other possibility I see is having the host add the hostfxr path to
NATIVE_DLL_SEARCH_DIRECTORIES
. I don’t think it would make sense to always add it, since it would affect other p/invokes (add an extra lookup), so I think it would need to be conditional. That would avoid the SDK (or any other app that wants to invoke into hostfxr) needing to figure out install layout, but I don’t see it as a common use case, so I wouldn’t want some new behaviour/configuration for the host to keep maintaining and supporting just for this one internal case.Code is here: https://github.com/dotnet/sdk/blob/a30e465a2e2ea4e2550f319a2dc088daaafe5649/src/Resolvers/Microsoft.DotNet.NativeWrapper/Interop.cs#L92
Looks like the assumption in the SDK is that hostfxr is automatically located, but I’m not sure how that’s supposed to work.
Not sure where should this issue be (that being said, I don’t mind moving this to runtime). I’m investigating, but it looks like dynamic linker environment variables (DYLD_LIBRARY_PATH) are being purged, thus failing to locate libhostfxr.dylib (specified in the DllImport).