Search code examples
xamarin.iosilmergeskiasharp

DllNotFoundException is thrown after ILMerge SkiaSharp into my Xamarin.iOS dll


I try to create a Xamarin.iOS class library, which uses SkiaSharp internally. I would like to distribute the final class library as a single dll without external dependencies. For this purpose I use ILMerge (or ILRepack). Final dll is successfully created but when I try to call some method from my class library I get DllNotFoundException. Here is the stack trace:

{System.DllNotFoundException: @rpath/libSkiaSharp.framework/libSkiaSharp at (wrapper managed-to-native) SkiaSharp.SkiaApi:sk_filestream_new (string) at SkiaSharp.SKFileStream..ctor (System.String path) [0x00000] in <9d222c42d8aa4f729033b25ddebc012a>:0 at SkiaSharp.SKBitmap.Decode (System.String filename) [0x00011] in <9d222c42d8aa4f729033b25ddebc012a>:0 at TestMerge.TestClass.TestMethod (System.String imageFile) [0x00001] in <9d222c42d8aa4f729033b25ddebc012a>:0 at Tests.Xamarin.Tests.Test001 () [0x00002] in /Users/mac1/Projects/awxamarin/Xamarin.Tests/Tests.Xamarin/Tests.cs:19 }

Steps to reproduce:

  1. Create a simple Xamarin.iOS class library.
  2. Add reference to SkiaSharp
  3. Create some simple public class with method that uses SkiaSharp. For example

    namespace TestMerge
    {
        public class TestClass
        {
            public static void TestMethod(string imageFile)
            {
                SkiaSharp.SKBitmap bmp = SkiaSharp.SKBitmap.Decode(imageFile);
            }
        }
    }
    
  4. Build the project and merge dlls using ILMerge (or ILRepack if you like it more). Here is the command used to merge dlls:

    ILMerge.exe /log:C:\Temp\ILMerge.log /internalize /ndebug /targetplatform:v4,"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\Xamarin.iOS\v1.0" /out:C:\Temp\TestMerge.dll C:\Temp\TestMerge\TestMerge\bin\Debug\TestMerge.dll C:\Temp\TestMerge\TestMerge\bin\Debug\SkiaSharp.dll

  5. Create Xamarin.iOS application (I used UnitTest application for testing) add reference to created dll, call method TestMethod. As the result the System.DllNotFoundException: @rpath/libSkiaSharp.framework/libSkiaSharp occurs.

I tried to decompile my dll and libSkiaSharp.framework is there, it is embedded as a resource, just like in SkiaSharp.dll. Any help is appreciated, I am stuck with this. By the way, exactly the same approach works fine for Xamarin.Android.


Solution

  • I finally get it worked. The solution was simple as always :). To make it work it is required to add the following attribute into the AssemblyInfo.cs of the main class library project:

    [assembly: ObjCRuntime.LinkWith("libSkiaSharp.framework", SmartLink = true)]
    

    Hope this will be useful for others