Raylib-cs-Examples icon indicating copy to clipboard operation
Raylib-cs-Examples copied to clipboard

run-examples fails on Linux

Open ronnieholm opened this issue 4 years ago • 10 comments

On Linux shouldn't the following steps just work?

$ git clone https://github.com/ChrisDill/Raylib-cs-Examples.git
$ make build
$ make run-examples

Running the examples results in

Unhandled exception. System.DllNotFoundException: Unable to load shared library 'raylib' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libraylib: cannot open shared object file: No such file or directory
   at Raylib_cs.Raylib.InitWindow(Int32 width, Int32 height, String title)
   at Examples.core_2d_camera_platformer.Main() in /tmp/Raylib-cs-Examples/Examples/core/core_2d_camera_platformer.cs:line 60
   at Examples.Program.RunCoreExamples() in /tmp/Raylib-cs-Examples/Examples/Program.cs:line 19
   at Examples.Program.Main(String[] args) in /tmp/Raylib-cs-Examples/Examples/Program.cs:line 8
Makefile:12: recipe for target 'run-examples' failed
make: *** [run-examples] Error 134

Am I missing anything obvious?

ronnieholm avatar Oct 24 '21 12:10 ronnieholm

I assume the NuGet package isn't supposed to install the C libraries.

ronnieholm avatar Oct 24 '21 15:10 ronnieholm

@ronnieholm Please ensure you have run make restore as that should in turn run dotnet restore which should download the NuGet package, which should contain the native C libraries.

If you could include dotnet --info it may help us debug the issue.

9ParsonsB avatar Oct 25 '21 14:10 9ParsonsB

Indeed. A restore happens as part of

$ make build

after which

$ find . -name *.so
./Examples/bin/Debug/net5.0/runtimes/linux-x64/native/libraylib.so

but running the examples fails.

Here's some of the output from dotnet --info:

$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.401
 Commit:    4bef5f3dbf

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  18.04
 OS Platform: Linux
 RID:         ubuntu.18.04-x64
 Base Path:   /home/rh/.dotnet/sdk/5.0.401/

I also tried:

$ LD_DEBUG=libs make run-examples

which results in these entries for raylib.

       972:	find library=libraylib.so [0]; searching
       972:	 search cache=/etc/ld.so.cache
       972:	 search path=/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib:/usr/lib		(system search path)
       972:	  trying file=/lib/x86_64-linux-gnu/libraylib.so
       972:	  trying file=/usr/lib/x86_64-linux-gnu/libraylib.so
       972:	  trying file=/lib/libraylib.so
       972:	  trying file=/usr/lib/libraylib.so
       972:	
       972:	find library=raylib [0]; searching
       972:	 search cache=/etc/ld.so.cache
       972:	 search path=/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib:/usr/lib		(system search path)
       972:	  trying file=/lib/x86_64-linux-gnu/raylib
       972:	  trying file=/usr/lib/x86_64-linux-gnu/raylib
       972:	  trying file=/lib/raylib
       972:	  trying file=/usr/lib/raylib
       972:	
       972:	find library=libraylib [0]; searching
       972:	 search cache=/etc/ld.so.cache
       972:	 search path=/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/lib:/usr/lib		(system search path)
       972:	  trying file=/lib/x86_64-linux-gnu/libraylib
       972:	  trying file=/usr/lib/x86_64-linux-gnu/libraylib
       972:	  trying file=/lib/libraylib
       972:	  trying file=/usr/lib/libraylib

On non-Windows platforms, wouldn't you need to add ./Examples/bin/Debug/net5.0/runtimes/linux-x64/native/ to the system loader search path?

ronnieholm avatar Oct 25 '21 16:10 ronnieholm

On non-Windows platforms, wouldn't you need to add ./Examples/bin/Debug/net5.0/runtimes/linux-x64/native/ to the system loader search path?

Nope, taking a look at the documentation here, the runtime should look in those folders. The only reason I can think of that it wont look for them there is if there is a ref or lib folder under runimes/{rid} or similar.

If you could have a read of this documentation and get the value of the NATIVE_DLL_SEARCH_DIRECTORIES Property of AssemblyLoadContext.Default that would help greatly

9ParsonsB avatar Oct 26 '21 00:10 9ParsonsB

If I extend Raylib-cs-Examples/Examples/Program.cs:

        static void Main(string[] args)
        {
            // Added line
            var searchDirectories = AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES");

            RunCoreExamples();
            RunShapesExamples();
            RunTextureExamples();
            RunTextExamples();
            RunModelExamples();
            RunShaderExamples();
            RunAudioExamples();
        }

then searchDirectories has the value of

/tmp/Raylib-cs-Examples/Examples/bin/Debug/net5.0/runtimes/linux-x64/native:/home/rh/.dotnet/shared/Microsoft.NETCore.App/5.0.10:"

libraylib.so is in the first path in the list.

ronnieholm avatar Oct 26 '21 07:10 ronnieholm

To simplify the issue, I created a simple library.so:

#include <stdio.h>

// gcc -shared -o library.so -fPIC library.c

void Test() {
    printf("C");
}

and a C# file to call the Test() function:

using System;
using System.Runtime.InteropServices;

namespace PInvoke
{
    public static class Library
    {
        [DllImport("library", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Test();
    }
    
    class Program
    {
        static void Main()
        {
            Console.WriteLine("C#");
            Library.Test();
        }
    }
}

and placed library.so in Debug/net5.0/runtimes/linux-x64/native.

Running the C# app results in the same error as with raylib:

C#
Unhandled exception. System.DllNotFoundException: Unable to load shared library 'library' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibrary: cannot open shared object file: No such file or directory
   at PInvoke.Library.Test()
   at PInvoke.Program.Main() in /tmp/PInvoke/Program.cs:line 17

However, placing library.so in /usr/lib (one of the system include paths):

C#
C

Surely, someone must have managed to run the raylib examples on Linux? :-)

ronnieholm avatar Oct 28 '21 20:10 ronnieholm

Surely, someone must have managed to run the raylib examples on Linux? :-)

Absolutely! @ChrisDill and I both run Arch on our personal machines - which is why we are so confused.

The documentation says that it should look in the paths in NATIVE_DLL_SEARCH_DIRECTORIES and that has the path in it, but it does not actually seem to be looking there at all.

Need to have a go at reproducing this in a VM, I think.

Thank you for doing some tests, it really helps narrow things down

9ParsonsB avatar Oct 28 '21 21:10 9ParsonsB

Absolutely! @ChrisDill and I both run Arch on our personal machines - which is why we are so confused.

That's really odd when you don't have raylib installed in one of the system paths.

I did come across others with a similar issue on Linux: https://github.com/dotnet/runtime/issues/34711#issuecomment-614751722.

For now the way I resolve the issue is through the ImportResolver and NativeLibrary.TryLoad: https://stackoverflow.com/questions/58955723/net-core-project-with-native-library-depedency?noredirect=1&lq=1

ronnieholm avatar Oct 30 '21 01:10 ronnieholm

Good news. I was testing

dotnet run --project Examples/Examples.csproj

on Ubuntu 20.04 and the examples load with both .NET 5 and .NET 6.

I then tried the same command on Ubuntu 18.04 and they still fail.

LD_DEBUG=libs dotnet run --project Examples/Examples.csproj

As expected this results in Unable to load shared library 'raylib' or one of its dependencies and then later in the output:

/lib/x86_64-linux-gnu/libm.so.6: error: version lookup error: version `GLIBC_2.29' not found (required by /home/rh/Downloads/raylibtest/Raylib-cs-Examples/Examples/bin/Debug/net6.0/runtimes/linux-x64/native/libraylib.so) (fatal)

Ubuntu 18.04 does't support GLIBC 2.29. Here's the version installed on Ubuntu 18.04 (Ubuntu 20.04 has 2.31).

$ ldd --version ldd
ldd (Ubuntu GLIBC 2.27-3ubuntu1.4) 2.27

Raylib-cs was last published on October 2, 2021. That is before this issue was created on October 24, 2021.

So I downgraded to .NET 5 on Ubuntu 18.04 using a global.json file and re-ran the dotnet command. The glibc error message still shows up. The message originates from ldd and .NET is simply passing it along. Perhaps the loader was updated with better error reporting sometime after October 24 or perhaps I missed the error in original output.

For reference, here're the dependencies of libraylib.so (with the same error message):

$ ldd /home/rh/Downloads/raylibtest/Raylib-cs-Examples/Examples/bin/Debug/net6.0/runtimes/linux-x64/native/libraylib.so
/home/rh/Downloads/raylibtest/Raylib-cs-Examples/Examples/bin/Debug/net6.0/runtimes/linux-x64/native/libraylib.so: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /home/rh/Downloads/raylibtest/Raylib-cs-Examples/Examples/bin/Debug/net6.0/runtimes/linux-x64/native/libraylib.so)
	linux-vdso.so.1 (0x00007fff3f9eb000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3f2bcff000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3f2c0f0000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3f2b961000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3f2b742000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3f2b53e000)

In conclusion: because libraylib.so inside the NuGet package is compiled against GLIBC 2.29, it cannot easily be consumed on Ubuntu 18.04.

ronnieholm avatar Nov 24 '21 18:11 ronnieholm

Just a little info. Examples works fine on Ubuntu 22.04.

dsoronda avatar Oct 01 '22 14:10 dsoronda