From cba17e017ddc118626d7d9e7f99899d3a3782255 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Thu, 22 Oct 2015 22:54:01 -0700 Subject: [PATCH] Enabling loading native libs from project references CoreClr --- .../PackageDependencyProvider.cs | 23 ++------ .../Loader/ProjectAssemblyLoader.cs | 41 ++++++++++++++ .../NativeLibPathUtils.cs | 56 +++++++++++++++++++ .../NativeLibPathUitlsFacts.cs | 17 ++++++ 4 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 src/Microsoft.Dnx.Runtime/NativeLibPathUtils.cs create mode 100644 test/Microsoft.Dnx.Runtime.Tests/NativeLibPathUitlsFacts.cs diff --git a/src/Microsoft.Dnx.Runtime/DependencyManagement/PackageDependencyProvider.cs b/src/Microsoft.Dnx.Runtime/DependencyManagement/PackageDependencyProvider.cs index a93ac5051..556902452 100644 --- a/src/Microsoft.Dnx.Runtime/DependencyManagement/PackageDependencyProvider.cs +++ b/src/Microsoft.Dnx.Runtime/DependencyManagement/PackageDependencyProvider.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Collections.Generic; using System.Diagnostics; @@ -6,7 +9,6 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; -using System.Runtime.Versioning; using System.Text; using Microsoft.Dnx.Runtime.Servicing; using Microsoft.Extensions.PlatformAbstractions; @@ -279,7 +281,7 @@ public static void EnableLoadingNativeLibraries(IEnumerable public static void EnableLoadingNativeLibraries(IEnumerable projects) { - var folderCandidates = GetFolderCandidates(); + var folderCandidates = NativeLibPathUtils.GetNativeSubfolderCandidates(); var nativeLibPaths = new StringBuilder(); foreach (var projectDescription in projects) @@ -323,23 +325,6 @@ private static void PreLoadNativeLib(string nativeLibFullPath) Logger.TraceInformation("[{0}]: Preloading : {1} {2}", nameof(PackageDependencyProvider), nativeLibFullPath, handle != IntPtr.Zero ? "succeeded" : "failed"); } - - private static IEnumerable GetFolderCandidates() - { - if (RuntimeEnvironmentHelper.IsWindows) - { - return PlatformServices.Default.Runtime.GetAllRuntimeIdentifiers(); - } - - var runtimeId = PlatformServices.Default.Runtime.GetRuntimeOsName(); - - return new[] - { - runtimeId, - runtimeId.Split('-')[0], - runtimeId.Split('.')[0] - }; - } #endif #if DNX451 diff --git a/src/Microsoft.Dnx.Runtime/Loader/ProjectAssemblyLoader.cs b/src/Microsoft.Dnx.Runtime/Loader/ProjectAssemblyLoader.cs index a91bbf7a8..4fa31f89a 100644 --- a/src/Microsoft.Dnx.Runtime/Loader/ProjectAssemblyLoader.cs +++ b/src/Microsoft.Dnx.Runtime/Loader/ProjectAssemblyLoader.cs @@ -17,6 +17,7 @@ public class ProjectAssemblyLoader : IAssemblyLoader private readonly IAssemblyLoadContextAccessor _loadContextAccessor; private readonly ICompilationEngine _compilationEngine; private readonly IDictionary _projects; + private readonly HashSet _unloadableNativeLibs = new HashSet(); public ProjectAssemblyLoader(IAssemblyLoadContextAccessor loadContextAccessor, ICompilationEngine compilationEngine, @@ -25,6 +26,8 @@ public ProjectAssemblyLoader(IAssemblyLoadContextAccessor loadContextAccessor, _loadContextAccessor = loadContextAccessor; _compilationEngine = compilationEngine; _projects = projects.ToDictionary(p => p.Identity.Name, p => new RuntimeProject(p.Project, p.Framework)); + + var environment = RuntimeEnvironmentHelper.RuntimeEnvironment; } public Assembly Load(AssemblyName assemblyName) @@ -83,7 +86,45 @@ public RuntimeProject(Project project, FrameworkName targetFramework) public IntPtr LoadUnmanagedLibrary(string name) { + if (_unloadableNativeLibs.Contains(name)) + { + return IntPtr.Zero; + } + + foreach(var projectPath in _projects.Values.Select(p => p.Project.ProjectDirectory)) + { + foreach (var folder in NativeLibPathUtils.GetNativeSubfolderCandidates(RuntimeEnvironmentHelper.RuntimeEnvironment)) + { + var path = NativeLibPathUtils.GetProjectNativeLibPath(projectPath, folder); + if (Directory.Exists(path)) + { + var handle = LoadUnamangedLibrary(path, name); + if (handle != IntPtr.Zero) + { + return handle; + } + } + } + } + + _unloadableNativeLibs.Add(name); + + return IntPtr.Zero; + } + + private IntPtr LoadUnamangedLibrary(string path, string name) + { + foreach (var nativeLibFullPath in Directory.EnumerateFiles(path)) + { + if (NativeLibPathUtils.IsMatchingNativeLibrary(RuntimeEnvironmentHelper.RuntimeEnvironment, name, Path.GetFileName(nativeLibFullPath))) + { + return _loadContextAccessor.Default.LoadUnmanagedLibraryFromPath(nativeLibFullPath); + } + } + return IntPtr.Zero; } + + private string ExpectedExtension { get; } } } \ No newline at end of file diff --git a/src/Microsoft.Dnx.Runtime/NativeLibPathUtils.cs b/src/Microsoft.Dnx.Runtime/NativeLibPathUtils.cs new file mode 100644 index 000000000..0b8ab201c --- /dev/null +++ b/src/Microsoft.Dnx.Runtime/NativeLibPathUtils.cs @@ -0,0 +1,56 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Microsoft.Dnx.Runtime +{ + internal class NativeLibPathUtils + { + public static IEnumerable GetNativeSubfolderCandidates(IRuntimeEnvironment runtimeEnvironment) + { + if (runtimeEnvironment.OperatingSystem == RuntimeOperatingSystems.Windows) + { + return PlatformServices.Default.Runtime.GetAllRuntimeIdentifiers(); + } + + var runtimeId = PlatformServices.Default.Runtime.GetRuntimeOsName(); + + return new[] + { + runtimeId, + runtimeId.Split('-')[0], + runtimeId.Split('.')[0] + }; + } + + public static string GetProjectNativeLibPath(string projectPath, string nativeSubfolder) + { + return Path.Combine(projectPath, "runtimes", nativeSubfolder, "native"); + } + + public static bool IsMatchingNativeLibrary(IRuntimeEnvironment runtimeEnvironment, string requestedFile, string actualFile) + { + if (string.Equals(requestedFile, actualFile, StringComparison.Ordinal)) + { + return true; + } + + if (runtimeEnvironment.OperatingSystem == RuntimeOperatingSystems.Windows) + { + return string.Equals(requestedFile, actualFile, StringComparison.OrdinalIgnoreCase) || + string.Equals(requestedFile + ".dll", actualFile, StringComparison.OrdinalIgnoreCase); + } + + if (runtimeEnvironment.OperatingSystem == RuntimeOperatingSystems.Linux) + { + return string.Equals(requestedFile + ".so", actualFile, StringComparison.Ordinal); + } + + return string.Equals(requestedFile + ".dylib", actualFile, StringComparison.Ordinal); + } + + } +} diff --git a/test/Microsoft.Dnx.Runtime.Tests/NativeLibPathUitlsFacts.cs b/test/Microsoft.Dnx.Runtime.Tests/NativeLibPathUitlsFacts.cs new file mode 100644 index 000000000..d56bd8c45 --- /dev/null +++ b/test/Microsoft.Dnx.Runtime.Tests/NativeLibPathUitlsFacts.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + + +using Xunit; + +namespace Microsoft.Dnx.Runtime.Tests +{ + public class NativeLibPathUitlsFacts + { + [Fact] + public void test() + { + + } + } +}