Skip to content

build/LightningDB.targets copies native lib based on build-machine architecture, not the target RuntimeIdentifier (breaks cross-arch dotnet publish) #205

Description

@JamestsaiTW

Summary

build/LightningDB.targets (target LightningDBIncludeNativeDll) selects which native liblmdb/lmdb.dll binary to copy into the output directory based on $([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture) — i.e. the architecture of the machine running the build — rather than the target RuntimeIdentifier (RID) being published for.

This breaks cross-architecture publishing, e.g.:

dotnet publish -r linux-arm64

run on an x64 build host. The target's conditions only check IsOsPlatform(Linux) + OSArchitecture == X64, so it copies the x64
native binary regardless of the -r linux-arm64 RID passed to publish. That wrong-architecture binary can then win NuGet's publish asset conflict resolution over the correct RID-specific binary (which the SDK's own runtimes/{rid}/native + .deps.json runtimeTargets mechanism already resolves correctly), resulting in an app that ships with the wrong-arch native library and fails at runtime on the target platform.

Repro

  1. On a linux-x64 (or any) host, add PackageReference Include="LightningDB" to a project (no RuntimeIdentifier set on the project itself — e.g. a library referenced via ProjectReference).
  2. Publish a consuming app with a different target RID:
    dotnet publish -r linux-arm64
    
  3. Inspect the publish output — the liblmdb.so present is built for the host architecture (x64), not linux-arm64.

Expected

The native binary copied (or excluded, deferring to normal SDK runtime asset resolution) should be based on the target RuntimeIdentifier of the publish/build, not the host machine's architecture.

Suggested fix

Two options that would both fix this:

  1. Change the Conditions in LightningDBIncludeNativeDll to key off $(RuntimeIdentifier) (when set) instead of RuntimeInformation.OSArchitecture, falling back to host-arch detection only when RuntimeIdentifier is empty (e.g. plain dotnet build with no RID).
  2. Alternatively, drop this custom copy target entirely and rely on the standard NuGet runtimes/{rid}/native convention, which the .NET SDK already resolves correctly per target RID during both build and publish (including RID-less ProjectReference builds, via .deps.json runtimeTargets entries). This target appears to predate reliable SDK support for that convention, but it's fully handled by the SDK today.

Workaround

We currently work around this downstream with:

<ItemGroup>
  <PackageReference Update="LightningDB" ExcludeAssets="build" />
</ItemGroup>

which disables this target and lets the SDK's built-in RID-based runtime asset resolution take over. This resolves cross-arch publishing for us, but ideally shouldn't be necessary.

Environment

  • LightningDB NuGet package version: 0.21.0
  • .NET SDK: (fill in your SDK version, e.g. 8.0.x / 6.0.x)
  • Host OS/Arch: linux-x64 (also reproducible cross-compiling from Windows)
  • Target RID: linux-arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions