run-examples fails on Linux
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?
I assume the NuGet package isn't supposed to install the C libraries.
@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.
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?
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
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.
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? :-)
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
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
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.
Just a little info. Examples works fine on Ubuntu 22.04.