I have created two NuGet packages that contain Native Libraries. The first one has two subfolders (amd64 and x86) the second one includes the DLL flat under the build directory. The NativeLibraries of the the first package are supposed to be copied into subfolders of the OutputPath. The only DLL in the second package should be copied flat under the OutputPath. I used the following stackoverflow entry as a guide for creating the package: https://stackoverflow.com/a/30316946/4496150
The first NuGet package folder structure looks like this (amd64 and x86 subfolder under build):
- build
- amd64
- DLL1.dll
- DLL2.dll
- x86
- DLL1.dll
- DLL2.dll
- packagename.targets
- amd64
First targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
<None Include="@(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory)** as NativeLibs Include and %(RecursiveDir) as part of Link attribute.
The second NuGet package structure looks like this (no subfolders under build):
- build
- DLL1.dll
- packagename.targets
Second targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll" />
<None Include="@(NativeLibs)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory) (without **) as NativeLibs Include and missing %(RecursiveDir) in Link attribute.
If you reference both packages, the DLLs from the first package are additionally copied flat into the output folder, which is not desired. I suspect this is because the second include step also reads the DLLs from the first package, but then does not use %(RecursiveDir).
A workaround is to also include in the second package both. and NativeLibs Include="$(MSBuildThisFileDirectory)***.dll" /> exactly as in the first package.
However, I would prefer to understand why the second package ensures that the DLLs from the first are copied flat.
If I read https://learn.microsoft.com/de-de/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2019 correctly, $(MSBuildThisFileDirectory) points to the folder in my NuGet cache where the targets file of the NuGet package is located. So actually everything would be correct. But still (probably) wrong DLLs are copied.
Edit
I added the following snippet in both targets files to get some output:
<Target Name="OutputPackage1NativeLibs" BeforeTargets="Build">
<Message Text="Package1 %(NativeLibs.Identity)" Importance="high"/>
</Target>
For the seconds targets file I changed the target name to OutputPackage2NativeLibs and started the text Output with Packag2.
When I clean my NuGet Package Cache and rebuild the solution everything is fine. But after the third or forth rebuild operation the DLLs of the first package are copied flat under the Output path and I get the following output:
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
So NativeLibs are added from the other NuGet package apparently after the third or fourth rebuild.