1

I made a NuGet package, Askaiser.Marionette, that targets .NET Standard 2.0/2.1 and .NET 5.

Two of its dependencies are OpenCvSharp4 and OpenCvSharp4.runtime.win (native OpenCV bindings for Windows x64/x86).

Whenever I consume my package in a .NET Core app or .NET 5 app, any OpenCvSharp4 method works well because in the build output directory there is this runtimes directory that contains the native OpenCV library:

Debug/<netcoreapp3.1>/
├── <...>
└── runtimes/
    ├── unix/<...>
    ├── win/<...>
    ├── win-x64/native/OpenCvSharpExtern.dll
    └── win-x86/native/OpenCvSharpExtern.dll

However, if my app targets .NET Framework (net461 up to net48), this runtimes directory is missing from the build output directory, resulting in the failure of any OpenCV wrapped method. This is fixed when the consumer app also installs the two OpenCvSharp4 packages.

Why do the consumer app needs to install the OpenCvSharp4 packages to work on .NET Framework? Right now, any person that tries to consume my package on .NET Framework would have to do that. This is not convenient.

If it can help, this is how my generated .nuspec looks like:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>Askaiser.Marionette</id>
    [...]
    <dependencies>
      <group targetFramework="net5.0">
        <dependency id="OpenCvSharp4" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="OpenCvSharp4.runtime.win" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="Tesseract" version="4.1.1" include="All" />
        <dependency id="Tesseract.Drawing" version="4.1.1" exclude="Build,Analyzers" />
      </group>
      <group targetFramework=".NETStandard2.0">
        <dependency id="OpenCvSharp4" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="OpenCvSharp4.runtime.win" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="System.Text.Json" version="5.0.2" exclude="Build,Analyzers" />
        <dependency id="Tesseract" version="4.1.1" include="All" />
        <dependency id="Tesseract.Drawing" version="4.1.1" exclude="Build,Analyzers" />
      </group>
      <group targetFramework=".NETStandard2.1">
        <dependency id="OpenCvSharp4" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="OpenCvSharp4.runtime.win" version="4.5.2.20210404" exclude="Build,Analyzers" />
        <dependency id="System.Text.Json" version="5.0.2" exclude="Build,Analyzers" />
        <dependency id="Tesseract" version="4.1.1" include="All" />
        <dependency id="Tesseract.Drawing" version="4.1.1" exclude="Build,Analyzers" />
      </group>
    </dependencies>
    [...]
  </metadata>
</package>
Anthony Simmon
  • 1,579
  • 12
  • 26

1 Answers1

1

I'm not sure whether this is the neatest solution but I'm sure that you have been struggling for a while to figure this out.

One option might be to add a target file to your NuGet package that copies the relevant DLLs to the output directory on a build when your platform is net472.

The target file might contain something similar to the following:

<ItemGroup>
    <Content Include="$(PkgOpenCvSharp4_runtime_win)\runtimes\win-x86\native\OpenCvSharpExtern.dll" >
      <Link>runtimes\OpenCvSharpExtern.dll</Link>
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      <CopyToPublishDirectory>Always</CopyToPublishDirectory>
    </Content>
  </ItemGroup>
<ItemGroup>
    <PackageReference Include="OpenCvSharp4.runtime.win" Version="4.5.2.20210404" GeneratePathProperty="true"/>
</ItemGroup>

You will have to wrap it with a condition targeting .net 4.7.2

For how the targeting works please have a look at the GRPC NuGet package, https://www.nuget.org/packages/Grpc.Core/

GRPC

This might be a bit off-topic, but I see that you add the PDB files in the NuGet package as well, it might be a good idea to have a look at SourceLink to download the symbols on request.

The automation project is really awesome and will be using it in the future

ReneLombard
  • 46
  • 1
  • 4