supranational / blst

Multilingual BLS12-381 signature library
Apache License 2.0
454 stars 171 forks source link

C# - look for native library in nuget conventional locations #210

Closed dkackman closed 1 month ago

dkackman commented 3 months ago

.NET's package manage, NuGet, will install native libraries in a standard location, denoted by it's Runtime Identifier. This is the most common way for a .net package to be deployed.

This change modifies the C# POC code to look in those locations when loading the native library in the blst static constructor, making it easier to author NuGet packages that include the blst native libraries.

dot-asm commented 2 months ago

Doc says that its behaviour changed in .NET 8. Would it be appropriate to compile it conditionally? As in #if NET8_0_OR_GREATER that is. And mimic the new behaviour in #else? Or maybe one can simply mimic it without referring the RuntimeIdentifier? Also, does it make sense to preserve the original lookup? I mean it could check if the library exists in several locations...

dkackman commented 2 months ago

Doc says that its behaviour changed in .NET 8. Would it be appropriate to compile it conditionally? As in #if NET8_0_OR_GREATER that is. And mimic the new behaviour in #else? Or maybe one can simply mimic it without referring the RuntimeIdentifier? Also, does it make sense to preserve the original lookup? I mean it could check if the library exists in several locations...

How about like this:

var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".";
var arch = RuntimeInformation.ProcessArchitecture switch
{
    Architecture.X64 => "x64",
    Architecture.Arm64 => "arm64",
    _ => "unsupported"
};
var os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win"
            : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx"
            : "linux";
var name = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "blst.dll"
            : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "libblst.dll.dylib"
            : "libblst.dll.so";

// first look for the file in the standard locations for a nuget installed native lib
// which will be something like "win-x64", "linux-x64", "linux-arm64", "osx-x64"
dll = Path.Combine(dir, "runtimes", $"{os}-{arch}", "native", name);

// if that's not found look using a simple default
if (!File.Exists(dll))
    dll = Path.Combine(dir, arch, name);

// if not there we'll try the current directory
if (!File.Exists(dll))
    dll = Path.Combine(Environment.CurrentDirectory, name);

if (File.Exists(dll))
{
    AssemblyLoadContext.Default.ResolvingUnmanagedDll += (asm, needs) =>
        (needs == "blst.dll" ? NativeLibrary.Load(dll) : IntPtr.Zero);
}
dot-asm commented 2 months ago

How about like this:

Cool, that's basically what I meant :-) But please add a remark that $"{os}-{arch}" mimics RuntimeIdentifier from NET 8.

Couple of questions. Is there feature availability conflict between the $"{x}" interpolation and #if NET5_0_OR_GREATER? It doesn't seem to be, because interpolation was added in C# 6, which predates NET 5. Does it sound right to you? Second question is if it makes sense to expand the os selection with OSPlatform.FreeBSD. I mean it's documented at least in NET 5, so why not...

dot-asm commented 2 months ago

Oh! And execute run.me and update even supranational.blst.cs.

dkackman commented 2 months ago

How about like this:

Cool, that's basically what I meant :-) But please add a remark that $"{os}-{arch}" mimics RuntimeIdentifier from NET 8.

Couple of questions. Is there feature availability conflict between the $"{x}" interpolation and #if NET5_0_OR_GREATER? It doesn't seem to be, because interpolation was added in C# 6, which predates NET 5. Does it sound right to you? Second question is if it makes sense to expand the os selection with OSPlatform.FreeBSD. I mean it's documented at least in NET 5, so why not...

makes sense to me. I'll put the conditional compilation back in so for net 8 forward at least this can pick up new permutations without change.

libblst.dll.so the expected file name on FreeBSD?

dot-asm commented 2 months ago

I'll put the conditional compilation back in so for net 8 forward at least this can pick up new permutations without change.

I meant a commentary would be sufficient, but feel free to add #if NET8_0_OR_GREATER.

libblst.dll.so the expected file name on FreeBSD?

Yes.

[Out for today.]

dkackman commented 2 months ago

Feedback merged.

FYI using it over here which is a library modeled on how chia implemented it: https://github.com/dkackman/chia-dotnet-bls/tree/blst

dot-asm commented 1 month ago

Thanks!