Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET Core 3.1, .NET 5 Lightning.NET multi-targeting breaks lmdb.dll copying for multi-targeted projects #143

Closed
Aaronontheweb opened this issue Aug 7, 2021 · 6 comments

Comments

@Aaronontheweb
Copy link

This is most likely an MSBuild problem with the latest sources in master, but it will definitely affect users during the next NuGet release. I've been able to reproduce the issue here: akkadotnet/akka.net#5180

We have a test project that multi-targets and consumes Lightning.NET:

  • .NET Framework 4.7.2
  • .NET Core 3.1
  • .NET 5.0

When targeting the most recent version of Lightning.NET (0.13.0) on NuGet we're able to run all of our tests that depend on LMDB in this project without any issues. In the output directory for each of those builds we can see the lmdb.dll successfully copied right next to the LightningDB.dll:

image

LightningDB 0.13.0 only targets .NET Standard 2.0 and doesn't multi-target - this appears to be one of the reasons why everything works with v0.13.0.

However, if I build and publish a package from the latest sources in master, which now targets:

  • .NET Standard 2.0
  • .NET Core 3.1
  • .NET 5.0

All three of my builds are missing lmdb.dll from the output directory:

image

And all three of them fail with the following runtime error during execution (on Windows primarily):

Node #2(second)][INFO][8/7/2021 3:48:53 AM][Thread 0028][akka.tcp://DDataClusterShardingRememberEntitiesSpec@localhost:50592/system/sharding/replicator/durableStore] Using durable data in LMDB directory [D:\a\1\s\src\contrib\cluster\Akka.Cluster.Sharding.Tests.MultiNode\bin\Release\net471\target\ClusterShardingMinMembersSpec\sharding-ddata-DDataClusterShardingRememberEntitiesSpec-replicator-50592]
[Node #2(second)]   at LightningDB.Native.Lmdb.mdb_env_create(IntPtr& env)
[Node #2(second)]   at LightningDB.LightningEnvironment..ctor(String path, EnvironmentConfiguration configuration)
[Node #2(second)]   at Akka.DistributedData.LightningDB.LmdbDurableStore.GetLightningEnvironment()
[Node #2(second)]   at Akka.DistributedData.LightningDB.LmdbDurableStore.<Active>b__17_0(Store store)
[Node #2(second)]   at lambda_method(Closure , Object , Action`1 , Action`1 )
[Node #2(second)]   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
[Node #2(second)]   at Akka.Actor.ActorCell.<>c__DisplayClass114_0.<Akka.Actor.IUntypedActorContext.Become>b__0(Object m)
[Node #2(second)]   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
[Node #2(second)]   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
[Node #2(second)]   at Akka.Actor.ActorCell.Invoke(Envelope envelope)
[Node #2(second)]Cause: System.DllNotFoundException: Unable to load DLL 'lmdb': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
[Node #2(second)]   at LightningDB.Native.Lmdb.mdb_env_create(IntPtr& env)
[Node #2(second)]   at LightningDB.LightningEnvironment..ctor(String path, EnvironmentConfiguration configuration)
[Node #2(second)]   at Akka.DistributedData.LightningDB.LmdbDurableStore.GetLightningEnvironment()
[Node #2(second)]   at Akka.DistributedData.LightningDB.LmdbDurableStore.<Active>b__17_0(Store store)
[Node #2(second)]   at lambda_method(Closure , Object , Action`1 , Action`1 )
[Node #2(second)]   at Akka.Actor.ReceiveActor.ExecutePartialMessageHandler(Object message, PartialAction`1 partialAction)
[Node #2(second)]   at Akka.Actor.ActorCell.<>c__DisplayClass114_0.<Akka.Actor.IUntypedActorContext.Become>b__0(Object m)
[Node #2(second)]   at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
[Node #2(second)]   at Akka.Actor.ActorCell.ReceiveMessage(Object message)
[Node #2(second)]   at Akka.Actor.ActorCell.Invoke(Envelope envelope)

I don't necessarily think the issue is the presence of lmdb.dll being in the exact same folder as LightningDB.dll - but this is one of the few things that definitively changed between versions of the package. I think this is an effect of the package moving to multi-targeting and how those dependencies now get resolved by downstream consumers who multi-target.

N.B. I have another project that only targets .NET Core 3.1 using this same package. It doesn't have lmdb.dll in its output directory either but it runs just fine, able to resolve the native .DLL from its runtimes/{platform} folder. This tells me that this issue is a combination of both the Lightning.NET and the downstream consumer both multi-targeting.

I suspect that in order to fix this issue we'll need to handle some additional edge cases here:

<PropertyGroup>
<LightningDBTargetRuntimeRelativePath Condition=" '$(LightningDBTargetRuntimeRelativePath)' == '' ">\..\</LightningDBTargetRuntimeRelativePath>
</PropertyGroup>
<ItemGroup Condition="'$([MSBuild]::IsOsPlatform(Windows))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X64'">
<None Include="$(MSBuildThisFileDirectory)$(LightningDBTargetRuntimeRelativePath)runtimes\win-x64\native\lmdb.dll">
<Visible>false</Visible>
<Link>lmdb.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)$(LightningDBTargetRuntimeRelativePath)runtimes\win-x64\native\lmdbautoresize.dll">
<Visible>false</Visible>
<Link>lmdbautoresize.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup Condition="'$([MSBuild]::IsOsPlatform(Windows))' And '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)'=='X86'">
<None Include="$(MSBuildThisFileDirectory)$(LightningDBTargetRuntimeRelativePath)runtimes\win-x86\native\lmdb.dll">
<Visible>false</Visible>
<Link>lmdbautoresize.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)$(LightningDBTargetRuntimeRelativePath)runtimes\win-x86\native\lmdbautoresize.dll">
<Visible>false</Visible>
<Link>lmdb.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

I'm going to take a look at how SQLite addresses this and see if I can submit a PR myself. But I wanted to fully document the issue for the sake of staying organized and in case anyone else has any ideas on how to address this.

@Aaronontheweb
Copy link
Author

Also, I'm taking a look at some of the suggestions on this thread to help debug in more detail what's actually going on here: dotnet/runtime#13472

@AlgorithmsAreCool
Copy link
Collaborator

Hey thanks for the report. I'll try to crave some time this week to close out some of these issues.

@Aaronontheweb
Copy link
Author

No problem! I worked around the issue here akkadotnet/akka.net#5180 - by just manually copying the binaries and the Lightning.targets file into our two testing projects which were affected.

As far as I can tell this issue doesn't affect normal usage of the plugin in applications - just multi-targeted tests.

@CoreyKaylor
Copy link
Owner

I'm speculating that in the setup it's possible that the LightningDBTargetRuntimeRelativePath might be off. If so, you should be able to set this to the correct relative path for your test projects. You can see I had to do the same in the test project here. I'm going to publish 0.14.0 shortly. The only change to the targets file was the additional file inclusion for the auto grow binary on Windows. Otherwise the changes are the same as before. Let me know if the issue continues to be "worse than before" now that it's multi-targeting in the new version.

@CoreyKaylor
Copy link
Owner

https://github.com/CoreyKaylor/Lightning.NET/releases/tag/v0.14.0 is published to nuget.org now.

@CoreyKaylor
Copy link
Owner

Feel free to re-open if there is still an issue that isn't fixed with my previous comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants