Asmichi.InjectNativeFileDepsHack
0.2.0
dotnet add package Asmichi.InjectNativeFileDepsHack --version 0.2.0
NuGet\Install-Package Asmichi.InjectNativeFileDepsHack -Version 0.2.0
<PackageReference Include="Asmichi.InjectNativeFileDepsHack" Version="0.2.0" />
paket add Asmichi.InjectNativeFileDepsHack --version 0.2.0
#r "nuget: Asmichi.InjectNativeFileDepsHack, 0.2.0"
// Install Asmichi.InjectNativeFileDepsHack as a Cake Addin #addin nuget:?package=Asmichi.InjectNativeFileDepsHack&version=0.2.0 // Install Asmichi.InjectNativeFileDepsHack as a Cake Tool #tool nuget:?package=Asmichi.InjectNativeFileDepsHack&version=0.2.0
Asmichi.InjectNativeFileDepsHack
An insane hack to inject runtime assets into deps.json by injecting RuntimeTargetsCopyLocalItems
items into the GenerateDepsFile
task.
This library can be obtained via NuGet.
Background
By default (without DllImportSearchPath.AssemblyDirectory
), the .NET runtime only loads native DLLs listed in the deps.json of an application. There is a long-standing issue: deps.json does not list native DLLs from reference projects (only native DLLs from NuGet packages), which means that such native DLLs cannot be loaded:
- https://github.com/dotnet/sdk/issues/765 Copy runtime libraries from references project
- https://github.com/dotnet/sdk/issues/1088 Allow runtime-specific assets in the project
- https://github.com/dotnet/sdk/issues/24708 Architecture-specific folders like runtimes/<rid>/native/ outside of NuGet packages [nativeinterop]
So, if you develop a library containing native DLLs, you get stuck. The test projects and sample projects will project-reference the library project, which does not work!
WARNING
Again, this is an insane hack that plays with the implementation details deep inside the .NET SDK. It is likely that this will break even by a minor version update of the .NET SDK.
Tested on the following versions of the .NET SDK:
- 6.0.301
Usage
List the native files as InjectNativeFileDepsHack
items in your application project (not your library project).
Notes:
- Normally you list the native DLLs as
Content
items in the library project, so the native DLLs should be copied into$(OutputPath)
. - You cannot use wildcards in
Include
to list files within output directories because these wildcards are evaluated before the build starts and thus output files are not yet built (such a wildcard will break clean builds).
<ItemGroup>
<PackageReference Include="Asmichi.InjectNativeFileDepsHack" Version="0.2.0" PrivateAssets="all" IncludeAssets="runtime;build;native;contentfiles;analyzers" />
</ItemGroup>
<ItemGroup>
<InjectNativeFileDepsHack Include="$(OutputPath)runtimes\linux-x64\native\libMyAwesomeLibrary.so">
<DestinationSubDirectory>runtimes\linux-x64\native</DestinationSubDirectory>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
</InjectNativeFileDepsHack>
</ItemGroup>
Appendices
Example
See sample for a minimal example. To run the sample, on an x64 Linux system, run:
(cd sample; ./build_and_run.sh)
Real-world example
See https://github.com/asmichi/ChildProcess/blob/master/build/msbuild/InjectChildProcessNativeFileDeps.targets and its usage.
How Asmichi.InjectNativeFileDepsHack works
Basically, it tricks the deps.json generation process into treating the specified native DLLs as the runtime assets of the Asmichi.InjectNativeFileDepsHack
NuGet library.
The runtimeTargets
items (assetType
== native
) of a library comes from RuntimeLibray.NativeLibraryGroups
. Looking into the target, GenerateDepsFile
and DependencyContextBuilder
for clues of how NativeLibraryGroups
are collected, you will notice that a project
type library always have empty NativeLibraryGroups
. So, there is no way to add runtimeTargets
items into a project
type library. Absolutely no way! Only NuGet libraries!
NuGet runtime files are collected by ResolvePackageAssets
as RuntimeTargetsCopyLocalItems
. Asmichi.InjectNativeFileDepsHack
adds the specified native DLLs as RuntimeTargetsCopyLocalItems
items just before GenerateDepsFile
runs, hence they appear as runtimeTargets
items of the Asmichi.InjectNativeFileDepsHack
NuGet library.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.