System.Data.SQLite

View Ticket
Login
Ticket Hash: 83e8001008fdfb8307aa0264c7c4a23f8ab00f71
Title: Nuget package assembly name conflict.
Status: Closed Type: Incident
Severity: Important Priority: Medium
Subsystem: NuGetPackage Resolution: Need_More_Info
Last Modified: 2020-11-10 02:44:47
4.45 years ago
Created: 2020-10-21 20:30:24
4.51 years ago
Version Found In: 1.0.113.1
User Comments:
anonymous added on 2020-10-21 20:30:24:

When compiling an application that targets multiple platforms, the platform dependent SQLite.Interop.dll is copied to the application output directory. E.g. When targeting the x86 platform application.x86.exe is created. When targeting the x64 platform application.x64.exe is created. Both applications have the same dependencies, however they cannot be deployed in the same directory due to the platform specific SQLite.Interop libraries having the same filename. This issue can be fixed by deploying the platform specific version of the SQLite.Interop.dll into subfolders in the build output directory and adding <dependentAssembly> sections to the app.config files that indicate where to find the platform specific assembly. E.g. The following would allow an application that targets the AnyCPU platform to correctly load the platform specific version of the SQLite.Interop.dll.

<dependentAssembly>
   <assemblyIdentity name="SQLite.Interop.dll" processorArchitecture="x86" culture="neutral"/>
   <codeBase version="1.0.113.0" href="x86/SQLite.Interop.dll"/>
</dependentAssembly>
<dependentAssembly>
   <assemblyIdentity name="SQLite.Interop.dll" processorArchitecture="amd64" culture="neutral"/>
   <codeBase version="1.0.113.0" href="x64/SQLite.Interop.dll"/>
</dependentAssembly>

For x86 or x64 applications only one of the above sections is needed. The same may also be accomplished by using platform dependent file names and similar <dependentAssembly> sections.


mistachkin added on 2020-10-24 18:59:28:
I do not understand how the SQLite interop assemblies are being deployed
by NuGet (or Visual Studio?) without ending up in their processor specific
sub-directories, e.g. "x86" and "x64".  The existing NuGet packages should
be authored in such a way to force this to be the case.

anonymous added on 2020-10-28 20:18:19:

This issue is caused by a lack of support for transitive builds. Our application depends on a package which depends on System.Data.SQLite.Core. That package had exclude="Build,Analyzers" for System.Data.Sqlite.Core specified due to how dotnet pack built the package. There are two ways to fix this issue:

  1. Support transitive builds by adding a /buildTransitive folder to the System.Data.SQLite.Core.NetFramework package that is a duplicate of the /build folder.
  2. We modify our .csproj for the dependent package to specify <ExcludeAssets>none</ExcludeAssets> inside the <PackageReference> for System.Data.SQLite.

Given that I will not be the last person to encounter this issue, I suggest implementing #1 in the System.Data.SQLite.Core.NetFramework package.


mistachkin added on 2020-10-28 22:09:47:
I'm not sure what is meant by "transitive" build support here.  I suppose
duplicating the content of the build folder is easy enough; however, I do
not yet understand why that is required.

mistachkin added on 2020-10-28 22:13:09:
From the documentation, it looks like I would only need to duplicate the
MSBuild related file(s).  I hope that is true because duplicating all the
native interop assemblies would be quite cost (i.e. size) prohibitive.

mistachkin added on 2020-10-28 22:16:12:
It looks like NuGet purposely introduced a breaking change:

[https://github.com/NuGet/Home/wiki/Allow-package--authors-to-define-build-assets-transitive-behavior]

Changing to external bug.  I'll still look into addressing this.

mistachkin added on 2020-10-28 23:59:58:
I've published some new packages; however, I do not think they are going to
work right for the 'transitive' build support.  Seemingly, there is no easy
way to obtain the right directory where the interop assembly DLLs reside,
relative to the new MSBuild targets file.

mistachkin added on 2020-10-29 00:56:33:
Ok, I *think* the very latest version of the core NuGet packages should work
for this scenario.

Either way, please let us know if they work for you.

anonymous added on 2020-10-29 14:24:03:

Thank you for the quick fix for this. I believe the changes you have made will correct the issue. Given that there probably won't ever be any differences to the .targets in /build and in /buildTransitive you can probably simplify the .targets in /buildTransitive to just import the .targets from /build. From the documentation it looks like it will only use one set of targets during build either from /build or /buildTransitive not both.


anonymous added on 2020-10-31 13:05:03:

FYI, this change broke multi-platform build. Previously we built single netcore target on windows and used it on win/linux/osx without changes. Now for linux/osx builds it cannot locate native dlls/libs and we need to copy them to expected location.


anonymous added on 2020-11-02 20:52:33:

I don't think supporting transitive builds is what is causing your problem. I think your problems stem from spitting the .Net Standard support from the .Net framework support into two separate packages. Transitive build support only ensures that the .Net Framework .targets files get run when an application depends on a package that depends on the SQLite package. If you are not targeting the .Net Framework then the .targets files should not have been used.

The 1.0.113.1 version of the packages had an invalid /runtimes structure that caused multiple copies of the SQLite.Interop.dll files to be found during build. The directory structure of that version resembled the following:

/build
   /net46
      /x86
         SQLite.Interop.dll
      /x64
         SQLite.Interop.dll
      System.Data.SQLite.Core.targets
/runtimes
   /win-x86
      /native
         /netstandard2.0
            SQLite.Interop.dll
         /netstandard2.1
            SQLite.Interop.dll
   /win-x64
      /native
         /netstandard2.0
            SQLite.Interop.dll
         /netstandard2.1
            SQLite.Interop.dll

When System.Data.SQLite.Core was a direct dependency of an application that targets .Net Framework 4.6, the SQLite.Data.SQLite.Core.targets file would copy the /x86 and /x64 directories from the /net46 directory to the build output directory. However, if you were creating an x86 or x64 application, msbuild would also find both copies of SQLite.Interop.dll under the platform dependent /netstandard2.0 and /netstandard2.1 directories and attempt to copy them to the output directory as well. This was due to the fact that the path to these files should have been /runtimes/win-x86/lib/{framework}/SQLite.Interop.dll if framework dependent versions were needed OR /runtimes/win-x86/native/SQLite.Interop.dll otherwise. The Linux and Mac OS X directories had the same structure and would have had the same issues. The latest version of the packages uses the latter approach of using a common library in the native directory, but also moves all .Net Standard files to a separate package.


anonymous added on 2020-11-03 13:53:32:

I'm not saying that transitive builds support broke it, just trying to say that changes in this fix caused new issues(regressions). Anyway I've already filled new issue here https://system.data.sqlite.org/index.html/tktview/83e8001008fdfb8307aa0264c7c4a23f8ab00f71


mistachkin added on 2020-11-04 23:17:03:
When I tested the "dotnet build" command, all native runtime files were copied
into sub-directories of the build output directory.

I'm not sure what would cause something else to happen.

mistachkin added on 2020-11-05 01:08:07:
The full list of output files produced by using the "dotnet build" command
on a "console" project that refers to the "System.Data.SQLite" package was:

netcoreapp3.0\EntityFramework.dll
netcoreapp3.0\EntityFramework.SqlServer.dll
netcoreapp3.0\Microsoft.Win32.SystemEvents.dll
netcoreapp3.0\projects.deps.json
netcoreapp3.0\projects.dll
netcoreapp3.0\projects.exe
netcoreapp3.0\projects.pdb
netcoreapp3.0\projects.runtimeconfig.dev.json
netcoreapp3.0\projects.runtimeconfig.json
netcoreapp3.0\System.CodeDom.dll
netcoreapp3.0\System.Configuration.ConfigurationManager.dll
netcoreapp3.0\System.Data.SqlClient.dll
netcoreapp3.0\System.Data.SQLite.dll
netcoreapp3.0\System.Data.SQLite.EF6.dll
netcoreapp3.0\System.Drawing.Common.dll
netcoreapp3.0\System.Security.Cryptography.ProtectedData.dll
netcoreapp3.0\System.Security.Permissions.dll
netcoreapp3.0\System.Windows.Extensions.dll
netcoreapp3.0\runtimes\linux-x64\native\SQLite.Interop.dll
netcoreapp3.0\runtimes\osx-x64\native\SQLite.Interop.dll
netcoreapp3.0\runtimes\unix\lib\netcoreapp2.1\System.Data.SqlClient.dll
netcoreapp3.0\runtimes\unix\lib\netcoreapp3.0\System.Drawing.Common.dll
netcoreapp3.0\runtimes\win\lib\netcoreapp2.1\System.Data.SqlClient.dll
netcoreapp3.0\runtimes\win\lib\netcoreapp3.0\Microsoft.Win32.SystemEvents.dll
netcoreapp3.0\runtimes\win\lib\netcoreapp3.0\System.Drawing.Common.dll
netcoreapp3.0\runtimes\win\lib\netcoreapp3.0\System.Windows.Extensions.dll
netcoreapp3.0\runtimes\win\lib\netstandard2.0\System.Security.Cryptography.ProtectedData.dll
netcoreapp3.0\runtimes\win-arm64\native\sni.dll
netcoreapp3.0\runtimes\win-x64\native\sni.dll
netcoreapp3.0\runtimes\win-x64\native\SQLite.Interop.dll
netcoreapp3.0\runtimes\win-x86\native\sni.dll
netcoreapp3.0\runtimes\win-x86\native\SQLite.Interop.dll

mistachkin added on 2020-11-06 17:45:04:
Need more information to proceed on this; otherwise, I'll assume the latest
NuGet packages address this issue as well.

anonymous added on 2020-11-07 14:26:23:

Ah, sorry. It is already fixed in https://system.data.sqlite.org/index.html/tktview/eb04d8c55f685ea3a302a77a42bd902f19a50b25