System.Data.SQLite

Login
This project makes use of Eagle, provided by Mistachkin Systems.
Eagle: Secure Software Automation
Ticket Hash: d292f2e23d8a74e0e7619638a2ff1ccab973fffe
Title: DllNotFoundException on .NET Core 2 Linux
Status: Closed Type: Code_Defect
Severity: Important Priority: Medium
Subsystem: NuGetPackage Resolution: Fixed
Last Modified: 2018-11-07 02:13:51
Version Found In: 1.0.109
User Comments:
anonymous added on 2018-08-14 06:16:07:
Hi, I've tried to use newly released System.Data.SQLite.Core on .NET Core 2.0/2.1 on Linux/MacOS. I'm getting DllNotFoundException:

System.DllNotFoundException: Unable to load shared library 'SQLite.Interop.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libSQLite.Interop.dll: cannot open shared object file: No such file or directory
   at System.Data.SQLite.UnsafeNativeMethods.sqlite3_config_none(SQLiteConfigOpsEnum op)
   at System.Data.SQLite.SQLite3.StaticIsInitialized()
   at System.Data.SQLite.SQLiteLog.Initialize(String className)
   at System.Data.SQLite.SQLiteConnection..ctor(String connectionString, Boolean parseViaFramework)

Steps to reproduce: 

1. Create a new console app. 
2. Install System.Data.SQLite.Core 1.0.109
3. Replace Program.cs with follwoing code:

using System;
using System.Data.SQLite;

namespace ConsoleApp6
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var c = new SQLiteConnection
            {
                ConnectionString = ":memory:"
            })
            {
                c.Open();
            }

            Console.WriteLine("Hello World!");
        }
    }
}

4. Run => DllNotFoundException

This is the resulting directory strucure:

./ConsoleApp6.dll
./osx-x64
./osx-x64/SQLite.Interop.dll
./x64
./x64/SQLite.Interop.dll
./ConsoleApp6.pdb
./ConsoleApp6.runtimeconfig.dev.json
./ConsoleApp6.runtimeconfig.json
./x86
./x86/SQLite.Interop.dll
./ConsoleApp6.deps.json
./linux-x64
./linux-x64/SQLite.Interop.dll

As you can see all required SQLite.Interop.dll files have been copied where they should be.

mistachkin added on 2018-08-14 11:12:49:
First off, where are the files "System.Data.SQLite.dll" and "System.Data.SQLite.dll.config"?

Second, on non-Windows platform, the LD_LIBRARY_PATH for the target process
must be modified to include whatever directory the "SQLite.Interop.dll" file
is copied to.  Unfortunately, there is no easy way to accomplish this from a
NuGet package.

mistachkin added on 2018-08-14 11:24:02:
It might be possible to modify the LD_LIBRARY_PATH using the project settings in
your IDE (e.g. in the debugging settings for the project).

anonymous added on 2018-08-15 11:45:36:
>First off, where are the files "System.Data.SQLite.dll" and "System.Data.SQLite.dll.config"?


I have no ideas. I just did the following:

dotnet new console
dotnet add package System.Data.SQLite.Core

modified the Program.cs

dotnet run

I would expect it to work OOB

anonymous added on 2018-08-15 11:54:46:
>First off, where are the files "System.Data.SQLite.dll" and "System.Data.SQLite.dll.config"?

If I put these files near the "executable" and run:

dotnet ConsoleApp6.dll

It still failes with the same exception. 

Also, it tries to load SQLite.Interop.dll from ./x64/ folder instead of ./osx-x64/ (or ./linux-x64 on linux)

anonymous added on 2018-08-15 23:39:57:
Hi there,

I have been able to fix all my problems by repacking the package using the "architecture" specific folders in nuget. You can check repacked package here: https://www.nuget.org/packages/Hazzik.System.Data.SQLite.Core/1.0.109-a1

The structure of the package is like following:

./runtimes/osx-x64/native/SQLite.Interop.dll
./runtimes/win-x86/native/SQLite.Interop.dll
./runtimes/win-x64/native/SQLite.Interop.dll
./runtimes/linux-x64/native/SQLite.Interop.dll
./lib/netstandard2.0/System.Data.SQLite.dll.config
./lib/netstandard2.0/System.Data.SQLite.xml
./lib/netstandard2.0/System.Data.SQLite.dll
./build/netstandard2.0/ - removed completely

Full framework directories are not changed

mistachkin added on 2018-08-16 03:19:28:
Thanks for the update, I'll work on fixing the official NuGet packages.

mistachkin added on 2018-08-16 05:10:31:
Your original revision matched what the NuSpec documentation states about using
native runtimes.

It looks like you've made some changes to the package you originally created.

Given the NuGet documentation, I'm not quite sure what the correct file layout
should be for the native files.

anonymous added on 2018-08-16 05:39:23:
-a1 is a valid layout. I've created -a2 and -a3 to test, but they do not work.

mistachkin added on 2018-08-16 05:50:39:
I've just pushed a new package that uses a slightly different way.  According to
the NuGet documentation, it should work.

Could you please check if it works you for and let us know?

anonymous added on 2018-08-16 10:23:02:
No, it does not work: it does not copy System.Data.SQLite dll to the output folder, so I'm getting an exception:

$ dotnet run

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Data.SQLite, Version=1.0.109.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139'. The system cannot find the file specified.

As I understand, the content of `runtimes/../lib` is replacing the content of `lib/..`. But content of `runtimes/../native` is copied in _addition_ to the content of `lib/..`

anonymous added on 2018-08-16 11:17:09:
I've checked my package on windows and it does not work. It seems that `native` folders interferes with other framework folders.

anonymous added on 2018-08-16 11:52:32:
*On windows on full .net

mistachkin added on 2018-08-16 17:11:23:
I was afraid of that.  I'm not sure what the correct solution is, given how
NuGet has chosen to support native libraries.

anonymous added on 2018-08-27 05:54:31:
It seems I'm facing the same (similar?) problem on windows.

Up to now, I'm working with a 
- net462 console app that is referencing
- net462 library (anycpu) that is referencing
- <PackageReference Include="System.Data.SQLite.Core" PrivateAssets="none" Version="1.0.109.1"/>
This is working as intended, x86/x64 directories are created, native dlls copied, all works.

Moving from net462 to dotnet core 2.1 fails with a DllNotFoundException because no dlls from the nuget get copied at all, not even System.Data.Sqlite.dll itself! No directories are created, no native dlls copied. I tried the same (minimalistic) steps our anonymous linux user posted on win-x64, same result - no output at all except for my app dll itself.

mistachkin added on 2018-08-28 01:03:22:
I think the fix for this issue is going to involve breaking out the native
binaries for .NET Core into a completely different NuGet package that will
end up being a dependency.  I cannot think of any other way, given the
(apparently) limitations of the NuGet client included with the .NET Core
SDK.

anonymous added on 2018-09-24 18:29:48:
I got this working with a much earlier version of System.Data.SQLite that I forked in order to run it on Windows, Linux, and OSX under .NET Core and .NET Framework.  I was hoping to migrate to a newer version of SQLite and also break the dependency on my own version of the package so that I would no longer have to distribute or maintain it, which led me to this ticket :).

Anyway, the secret is using "native" as the folder name under runtimes/{runtime ID}.  For .NET Core, this causes the build and runtime to include *both* the assembly under lib and whatever is under runtimes for the currently executing or compiling runtime.  My forked version of the package includes a purely native SQLite library under runtimes instead of a mixed-mode assembly like you have, but I think it should still work regardless.  

So this works for .NET Core, and for .NET Framework, you use the build folder in the NuGet package with the .targets file to copy the x64 and x86 folders to the bin folder of the target library or application.  Something to note is that your current .targets file won't copy over those folders transitively.  That is, if I have Project1 referencing Project2 and Project2 referencing System.Data.SQLite, the x86 and x64 folders won't be copied over to Project1 when it compiles.  The .targets file in my version do this, so you might be able to adapt it to your .targets file to do this.

Anyway, I've put my forked version of the package up at https://www.dropbox.com/s/lqez0hyg52rzcuu/system.data.sqlite.medicomp.1.0.65.nupkg?dl=0 for you to take a look at if you want.

mistachkin added on 2018-11-07 02:13:51:
This appears to be fixed via NuGet package 1.0.109.2.