.NET core and SkiaSharp runtime error

Hi

We have a big problem with the .net core and our oxygen project using SkiaSharp nugets.
I attach a simple test case in oxygene and c#:
ConsoleApplicationC#.zip (1.4 KB)
SkiaSharp_oxygene.zip (30.4 KB)
Using c# I can run the app in Windows, macOS and WSL without problems.
With the oxygene project I get error:

Exception of type System.DllNotFoundException on thread 8980
Message: Unable to load DLL '@rpath/libSkiaSharp.framework/libSkiaSharp' or one of its dependencies: The specified module could not be found. (0x8007007E)

The problem here seems to be an invalid ConsoleApplication.deps.json file that for runtimes and assets for different platforms generates an invalid json (compared with c#).

In addition, the output structure of files in bin/debug is different. libSkiaSharp.dll should not be copied to .exe directory as it’s a runtime asset library.
Even if I set publish in the project settings and the runtime directory is created, invalid .deps.json file stops the app from executing and loading runtime deps correctly.

One trick for Windows is to copy libSkiaSharp.dll manually but this won’t work for linux or macos.
The only workaround for us right now is to create c# project, compile it, copy generated .deps.json file to our project, and then we can run the app on all platforms.

Please verify your build logic and fix it to make it work like c# does for Nuget packages having runtime dependencies for different platforms.
We need to run .net core app on any platform without any tricks.

Regards
Artur

What platform is this on, macOS?

Dll resolving on macOS is tricky/difficult and using a very strange system, where the libraries (.dylibs, equivalent of a Windows .dll) specify the (relative or absolute) path where the exe should look for the dll. the @rpath is that. This mikeash.com: Friday Q&A 2009-11-06: Linking and Install Names is a fun read on the topic.

It sound like somehow the native libSkiaSharp.framework is not being deployed as it should or the exe is not setting the right rpaths.

I will have a look at the projects. Could you send me (if it’s not included in the zips already, I haven’t downloaded yet) the output of the VC# project, so I can compare (as I’m traveling thisweek, and not set up right now to build that one locally).

thanx,
marc

Update this is odd. the skiasharp.nativeassets.macos package has libSkiaSharp.dylib, which is being deployed correctly for me (im testing on Mac only, right now). But I do repro that its its not being loaded; apparently it is checkin these 6 paths, all of which expect the dylib to be inside a “libSkiaSharp.framework” — which does not exist.

dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file)
dlopen(/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib, 0x0001): tried: '/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file), '/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp.dylib' (no such file)
dlopen(@rpath/libSkiaSharp.framework/libSkiaSharp.dylib, 0x0001): 
dlopen(/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp, 0x0001): tried: '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.2.23128.3/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file), '/System/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file, not in dyld cache)
dlopen(/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp, 0x0001): tried: '/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/Users/mh/Downloads/SkiaSharp_oxygene/Bin/Debug/@rpath/libSkiaSharp.framework/libSkiaSharp' (no such file), '/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file), '/System/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file, not in dyld cache)
dlopen(@rpath/libSkiaSharp.framework/libSkiaSharp, 0x0001): tried: '/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file), '/System/Library/Frameworks/libSkiaSharp.framework/libSkiaSharp' (no such file, not in dyld cache)

without seeing what C# generates, right now just from looking at the Oxygene project and the input packages, I would say this is “expected”, this dll depends on a .framework it doesn’t ship. :(.

I’m using Windows. I’m interested in Windows and Linux (wsl) platforms for now.
http://download.tatukgis.com/upload/TTK-9FE8BF6F-C550-4AAE-AF4C-895FB0F99424/ConsoleApp1.zip
I’ve skipped some folders from runtimes.

Hm ok. that probably is a slight different issue, as Windows should just find the .dll, ion copied next to the exe. I’ll see info can find a chance to test this Windows myself, tomorrow.

Hmm, on Windows, nothing happens when i run the app, but also no error. libSkiaSharp.dll is deployed correctly next to the exe… what could I be missing?

Hi
If everything is correctly configured in .deps.json, the .exe should create a native skia bitmap and nothing more for Windows and Linux wsl platforms. In other cases runtime exceptions like System.DllNotFoundException or an unknown type will be thrown.

libSkiaSharp.dll should not be copied next to the exe or dll. Do you know which file was copied? arm, win-32, x64, etc. There are many many subplatforms for skia. This dependence should be resolved in “nuget” way and .deps.json via runtime subdirectories. The project output files when copied to different platforms (win, linux wsl) should work the same way without copying libSkiaSharp locally. Exactly like c# compiler does it for exe or library projects.

For Windows, it’s easier. For linux, the .deps.json file doesn’t contain runtime information for linux at all. Please try to execute the project in WSL env. using dotnet command and dll library as output. It will fail because cannot resolve dependencies (as no files copied). If we locally replace .deps.json file with the one generated by c#, everything works. But we don’t want to do this fake workaround.

It’s hard to explain these technicals but I hope you now understand the problem better.
So:

  1. Are you able to produce the same .deps.json as c# does?
  2. In the future will it be possible (or maybe it is) to run .net core app with a debugger directly on wsl under Windows as VS2022 can?
  3. If I set publish = true for a project, it generates different output as c# does with runtime dir. This is what we want but with fixed .deps.json. and working on WSL and Windows.

We really count on resolving points 1 and 3.
Thanks.

I see, yes. I’ll log an issue to have a look at this and address this, but probably not until next week, as I’m traveling this week.

thanx,
marc

Logged as bugs://E26637.

Can you see ion setting Publish to YES/True solves this for you, at least for the local architecture? When I enable this, I do get the runtimes folder, albeit not for all selected RuntimeIdentifiers, only current (I’ll fix that; and I will also review of this logic needs to maybe move from Publish to general processing for both scenarios…).

publish=true solves the dirs-files structure problem.

This was a corner-case bug when not selecting “all” windows platforms (for loop had a break instead of a continue. oops ;). Fixed, if you wish, I can upload a new build to your Personal Downloads, in about an hour…

No, thanks. We can wait for all the fixes and the next stable release.

1 Like

FWIW, it still fails for me with this fixes, on macOS. which makes sense, as its looking for those the dylib inside libSkiaSharp.framework/libSkiaSharp.dylib, which doesn’t exist; I don’t believe thats our bug. I’ll retry in my Windows VM once I have a full build to install there, but remember i couldn’t reproduce the error there — so it might be prudent to test on your side early rather than wait for the official build, in case this did not do the trick…

No problem, I can test your builds when you want.

1 Like

that is fixed (with Publish=YES), but it doesn’t solve the problem :(. It still fails, on Windows with Unable to load DLL '@rpath/libSkiaSharp.framework/libSkiaSharp', which is a message that makes no sense, as both @rpath and libSkiaSharp.framework are macOS specific things…

I see no relevant differences in the .deps.json, but i’ll dig some more. But to me this seams like the what Skia tries to loads its native .dll is just broken, as it not only uses a mac-specific path, but also uses the framwork path — and that’s not only a Mac-speciifc ting, but said framework also does not even exist in the NuGet packages — where would it get it from?

C# nad Oxygene deps are very different (Oxygene is not completer). Try to search both for .so - C# has references to all .so locations (Mac by default, Linxu when proper nuget added.)

Also,

  • copying libSkiaSharp into the same folder as EXE is wrong - which one has been copied: intel or arm?
  • even SkiaSharp.dll is not a proper one. For NET6 Lib, it should be SkiSharp for .NET6 folders while it is… skiasharp.2.88.3.nupkg\lib\net6.0-tvos13.4
  • for .NET 6.0 Winforms application SkiaSharp is copied from: skiasharp.2.88.3.nupkg\lib\net462

The same bad NuGet copying is true also for .NET Framework apps:

.so is Linux. For simplicity, I’m focusing on getting Windows working for now.

This, I believe is the root cause for this error, and explains why it is looking for the .framework version of the .dll — because the tvOS version of SkiaSharp uses that.

~/Library/Application Support/RemObjects Software/EBuild/Packages/NuGet/skiasharp.nativeassets.tvos/2.88.3/runtimes/tvos/native/libSkiaSharp.framework/libSkiaSharp

Somehow the :“find the right framework version folder” doesn’t take into account the -tvos suffix, it should not be using that folder. I’ll fix that one first and then we can retest and see if there’s more issues.

Probably wrong, yes, but unlikely to be the/a problem. I’ll still check & fix, though.

With this fixed, your test app runs ok on macOS. Will retest Windows once I have a build

1 Like

and test WSL, please.

Fixed the missing .so and .dylib entries, but I don’t believe this had any real-life effect either way.

I’m not set up to test that, as I;'m only running Windows/arm64 and only in a VM, and I don’t believe that supports WSL. That said, in Mac and Windows work, Linux shokld too.

Note that the main SkiaSharp ref seems to only pull in the native assets for macOS and Windows; for linux you have to explicitly add a reference to SkiaSharp.NativeAssets.Linux (which your C# project seems to have done, but your Oxhygene test case did/does not). Very odd design choice on their end, but that’s what it is…