Skip to content
Snippets Groups Projects
Commit d4f04e8e authored by Jan Tattermusch's avatar Jan Tattermusch
Browse files

Merge pull request #6115 from jtattermusch/csharp_support_projectjson

Make gRPC C# nuget work with new project.json style projects
parents ab1c84f4 1afdf846
No related branches found
No related tags found
No related merge requests found
......@@ -16,7 +16,6 @@
<tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies>
<dependency id="Ix-Async" version="1.2.5" />
<dependency id="grpc.native.csharp" version="$version$" />
</dependencies>
</metadata>
<files>
......@@ -24,5 +23,12 @@
<file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" />
<file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" />
<file src="**\*.cs" target="src" />
<file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" />
<file src="windows_x86/grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" />
<file src="windows_x64/grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" />
<file src="linux_x86/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" />
<file src="linux_x64/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" />
<file src="macosx_x86/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" />
<file src="macosx_x64/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" />
</files>
</package>
......@@ -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()
{
......
......@@ -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")]
......
......@@ -12,12 +12,12 @@ set NUGET=C:\nuget\nuget.exe
@rem Collect the artifacts built by the previous build step if running on Jenkins
@rem TODO(jtattermusch): is there a better way to do this?
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x64\
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x64\
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64\
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x64\
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x64\
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x86\
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x64\
@rem Collect protoc artifacts built by the previous build step
xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\
......@@ -42,7 +42,6 @@ msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error
endlocal
%NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
......
gRPC Native Nuget package
=========================
Prerequisites
-------------
NuGet binary
Building the package
--------------------
To build the native package, you need precompiled versions
of grpc_csharp_ext library artifacts for Windows, Linux and Mac.
In the normal gRPC release process, these are built by a Jenkins
job and they are copied to the expected location before building
the native nuget package is attempted.
See tools/run_tests/build_artifacts.py for more details how
precompiled artifacts are built.
When building the native NuGet package, ignore the "Assembly outside lib folder"
warnings (the DLLs are not assemblies, they are native libraries).
......@@ -14,12 +14,12 @@
@rem Collect the artifacts built by the previous build step if running on Jenkins
@rem TODO(jtattermusch): is there a better way to do this?
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* grpc.native.csharp\windows_x64${"\\"}
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* grpc.native.csharp\linux_x64${"\\"}
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* grpc.native.csharp\macosx_x64${"\\"}
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* Grpc.Core\windows_x64${"\\"}
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* Grpc.Core\linux_x64${"\\"}
xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x86${"\\"}
xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* Grpc.Core\macosx_x64${"\\"}
@rem Collect protoc artifacts built by the previous build step
xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86${"\\"}
......@@ -44,7 +44,6 @@
endlocal
%%NUGET% pack grpc.native.csharp\grpc.native.csharp.nuspec -Version %VERSION% || goto :error
%%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
%%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
%%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment