diff options
Diffstat (limited to 'src/csharp/Grpc.Core/Internal')
-rw-r--r-- | src/csharp/Grpc.Core/Internal/NativeExtension.cs | 27 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs | 24 |
2 files changed, 37 insertions, 14 deletions
diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index bff1e56582..b45ba19c24 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -32,7 +32,6 @@ #endregion using System; -using System.Globalization; using System.IO; using System.Reflection; @@ -46,6 +45,7 @@ namespace Grpc.Core.Internal internal sealed class NativeExtension { const string NativeLibrariesDir = "nativelibs"; + const string DnxStyleNativeLibrariesDir = "../../build/native/bin/"; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>(); static readonly object staticLock = new object(); @@ -100,31 +100,48 @@ namespace Grpc.Core.Internal // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property). var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString()); - var fullPath = Path.Combine(Path.GetDirectoryName(GetAssemblyPath()), - NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); - return new UnmanagedLibrary(fullPath); + + var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); + + // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder + // alongside the compiled assembly. + var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + + // DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored + // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. + var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + + return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath}); } private static string GetAssemblyPath() { var assembly = typeof(NativeExtension).GetTypeInfo().Assembly; - +#if DOTNET5_4 + // Assembly.EscapedCodeBase does not exit under CoreCLR, but assemblies imported from a nuget package + // don't seem to be shadowed by DNX-based projects at all. + return assembly.Location; +#else // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing // to the original location of the assembly, and Location is pointing // to the shadow copy. We care about the original location because // the native dlls don't get shadowed. + var escapedCodeBase = assembly.EscapedCodeBase; if (IsFileUri(escapedCodeBase)) { return new Uri(escapedCodeBase).LocalPath; } return assembly.Location; +#endif } +#if !DOTNET5_4 private static bool IsFileUri(string uri) { return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile); } +#endif private static string GetPlatformString() { diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs index 47308f8c9e..5a80746101 100644 --- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -32,8 +32,6 @@ #endregion using System; -using System.Collections.Concurrent; -using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; @@ -63,14 +61,9 @@ namespace Grpc.Core.Internal readonly string libraryPath; readonly IntPtr handle; - public UnmanagedLibrary(string libraryPath) + public UnmanagedLibrary(string[] libraryPathAlternatives) { - this.libraryPath = GrpcPreconditions.CheckNotNull(libraryPath); - - if (!File.Exists(this.libraryPath)) - { - throw new FileNotFoundException("Error loading native library. File does not exist.", this.libraryPath); - } + this.libraryPath = FirstValidLibraryPath(libraryPathAlternatives); Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath); @@ -139,6 +132,19 @@ namespace Grpc.Core.Internal throw new InvalidOperationException("Unsupported platform."); } + private static string FirstValidLibraryPath(string[] libraryPathAlternatives) + { + GrpcPreconditions.CheckArgument(libraryPathAlternatives.Length > 0, "libraryPathAlternatives cannot be empty."); + foreach (var path in libraryPathAlternatives) + { + if (File.Exists(path)) + { + return path; + } + } + throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives)); + } + private static class Windows { [DllImport("kernel32.dll")] |