y-crdt / ydotnet

.NET bindings for yrs.
MIT License
29 stars 9 forks source link

Unable to load shared library 'yrs' or one of its dependencies. #76

Closed vdurante closed 6 months ago

vdurante commented 6 months ago

Hey, I am trying to run the server on a Mac Apple Silicon, but I am getting the following error:

Checking that folder, I can only see a libyrs.dylib file, but no yrs.dylib file.

Thanks!

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.DllNotFoundException: Unable to load shared library 'yrs' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: 
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs.dylib, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs.dylib' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs.dylib' (no such file)
      dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs.dylib, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs.dylib' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs.dylib' (no such file)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs.dylib, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs.dylib' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs.dylib' (no such file)
      dlopen(yrs.dylib, 0x0001): tried: 'yrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSyrs.dylib' (no such file), '/usr/lib/yrs.dylib' (no such file, not in dyld cache), 'yrs.dylib' (no such file), '/usr/local/lib/yrs.dylib' (no such file), '/usr/lib/yrs.dylib' (no such file, not in dyld cache)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs.dylib, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs.dylib' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'))
      dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs.dylib, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs.dylib' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs.dylib' (no such file)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs.dylib, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs.dylib' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs.dylib' (no such file)
      dlopen(libyrs.dylib, 0x0001): tried: 'libyrs.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibyrs.dylib' (no such file), '/usr/lib/libyrs.dylib' (no such file, not in dyld cache), 'libyrs.dylib' (no such file), '/usr/local/lib/libyrs.dylib' (no such file), '/usr/lib/libyrs.dylib' (no such file, not in dyld cache)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/yrs' (no such file)
      dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/yrs' (no such file)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/yrs' (no such file)
      dlopen(yrs, 0x0001): tried: 'yrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OSyrs' (no such file), '/usr/lib/yrs' (no such file, not in dyld cache), 'yrs' (no such file), '/usr/local/lib/yrs' (no such file), '/usr/lib/yrs' (no such file, not in dyld cache)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/runtimes/osx/native/libyrs' (no such file)
      dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.14/libyrs' (no such file)
      dlopen(/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs, 0x0001): tried: '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs' (no such file), '/Users/vitor/dev/temp/Yjs/Yjs/bin/Debug/net7.0/libyrs' (no such file)
      dlopen(libyrs, 0x0001): tried: 'libyrs' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibyrs' (no such file), '/usr/lib/libyrs' (no such file, not in dyld cache), 'libyrs' (no such file), '/usr/local/lib/libyrs' (no such file), '/usr/lib/libyrs' (no such file, not in dyld cache)

         at YDotNet.Native.Document.DocChannel.NewWithOptions(DocOptionsNative options)
         at YDotNet.Document.Doc.CreateDoc(DocOptions options)
         at YDotNet.Document.Doc..ctor(DocOptions options)
         at YDotNet.Document.Doc..ctor()
         at YDotNet.Server.Internal.DocumentContainer.LoadCoreAsync()
         at YDotNet.Server.Internal.DocumentContainer.LoadInternalAsync(IDocumentCallback documentCallback, IDocumentManager documentManager)
         at YDotNet.Server.Internal.DocumentContainer.ApplyUpdateReturnAsync[T](Func`2 action)
         at YDotNet.Server.DefaultDocumentManager.GetStateVectorAsync(DocumentContext context, CancellationToken ct)
         at YDotNet.Server.WebSockets.YDotNetSocketMiddleware.<HandleSyncAsync>b__11_0(WebSocketEncoder encoder, Boolean context, ClientState state, CancellationToken ct)
         at YDotNet.Server.WebSockets.ClientState.WriteLockedAsync[T](T state, Func`5 action, CancellationToken ct)
         at YDotNet.Server.WebSockets.YDotNetSocketMiddleware.HandleSyncAsync(ClientState state, CancellationToken ct)
         at YDotNet.Server.WebSockets.YDotNetSocketMiddleware.InvokeAsync(HttpContext httpContext, String documentName)
         at YDotNet.Server.WebSockets.YDotNetSocketMiddleware.InvokeAsync(HttpContext httpContext, String documentName)
         at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.InvokeCore(HttpContext context, PathString matchedPath, PathString remainingPath)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
SebastianStehle commented 6 months ago

It tries several file names, including libyrs.dylib as you can see in the logs.

So the problem seems to be the following: (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')). So we need dedicated arm images.

I don't have a mac and github does not provide arm runners yet, therefore I cannot help with that. If you are willing to contribute, you could build the yrs library on your machine and then provide a PR.

vdurante commented 6 months ago

@SebastianStehle I will definitely try to do that. Not sure how to since I am not experienced with rust, but I can definitely try to build for macos arm and contribute!

Thanks for the help

SebastianStehle commented 6 months ago

You don't have to understand rust.

Just...

  1. Install rust
  2. Checkout the yrs project
  3. Apply the patch: https://github.com/y-crdt/ydotnet/blob/main/native/build.patch
  4. Run RUSTFLAGS="-C target-feature=-crt-static" cargo build --release

Then create a copy of the OSX project and reference your built project: https://github.com/y-crdt/ydotnet/blob/main/native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj

The problem is that you would have 2 libraries with the same name if you want to build a project for x86 and arm. So we need a custom library resolver: (which needs to be documented):

https://learn.microsoft.com/en-us/dotnet/standard/native-interop/native-library-loading

vdurante commented 6 months ago

@SebastianStehle thanks for the help. I ended up using a Linux machine for this.

SebastianStehle commented 6 months ago

If you have a mac, your contribution would be awesome. As mentioned above, you don't have to understand rust. Just build the binary. Then add a new native package by and reference your binary: https://github.com/y-crdt/ydotnet/blob/main/native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj#L10

if you put your binary to the correct folder, dotnet should pick it up. The folder name contains the runtime identifier (rid) - here osx - so we have to use the correct rid: https://learn.microsoft.com/en-us/dotnet/core/rid-catalog#macos-rids

vdurante commented 6 months ago

@SebastianStehle I will open a PR with the binaries after I build it. I just don't know how we will differentiate from ARM to Intel, since both are apparently using the macos/native path.

Give me some time to build that.

SebastianStehle commented 6 months ago

I guess you mean osx/native?

This is what the rids are for. We can change the current osx/native path to osx-x64/native and then create a new project where we use osx-arm/native.

Even if we don't change the existing package, it should work, because dotnet has this RID graph (https://learn.microsoft.com/en-us/dotnet/core/rid-catalog#rid-graph), so it tries the very specific folder first and then moves the graph upwards to the root.

vdurante commented 6 months ago

@SebastianStehle Is this what you expect?

https://github.com/y-crdt/ydotnet/pull/81