c# – Copying native libraries to the output folder

Question:

There is a solution with two projects: the first is the library, the second is the application being launched.

Added a link to the first one in the second project.

A nuget package has been added to the first project, in which there are some native libraries.

Problem: when building a project, these native libraries are not copied to the SECOND project's output folder.

There are these libraries in the output folder of the first project, if you copy them to the output folder of the second project manually, the application works fine.

How do I get all libraries to be copied automatically?

Answer:

There are two problems here, and the first of them is the crooked hands of the author of the package. Often in such packages, copying files to the output folder is done with some kind of bicycle, which, of course, is not recognized by the standard toolchain.

You need to find the targets file inside the nuget package, examine its structure and write your patch. You will have to disable the standard target and write your own.

The idea is that any file copied to the output folder should be copied by the standard toolchain. To do this, you need to "hang" on AssignTargetPaths and create a ContentWithTargetPath element for each copied file:

<Target Name="КакойтоГлупыйТаргетИзПакета" />
<Target Name="AssignLibPaths" AfterTargets="AssignTargetPaths">
    <ItemGroup>
        <ContentWithTargetPath Include="$(КакоетоСвойствоИзПакета)\lib\foo.dll">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            <TargetPath>foo.dll</TargetPath>
        </ContentWithTargetPath>
    </ItemGroup>
</Target>

All items added in this way will be copied to dependent projects (just like files marked with CopyToOutputDirectory=PreserveNewest are copied).

Just in case, it makes no sense to edit the files downloaded via nuget, all changes must be made directly to your project file ( .csproj ). A detailed description of the syntax is beyond the scope of the answer, look for information on the keyword "msbuild".


Packages deserve a special mention; instead of extending the assembly during installation, they simply add xcopy commands to PostBuildEvent.

These xcopy commands should be scrubbed from there, and replaced with a specific Target.

Alternatively, you can simply add all the files you need to the project as links – it won't get any worse.


The second problem is in transitive dependencies. If project A depends on B, and B depends on C, then the files from project A will not get into project C. MS did not even try to solve this problem (moreover, I have a suspicion that this was done on purpose – because the C # compiler also does not supports transitive dependencies!).

The problem arises because the _SplitProjectReferencesByFileExistence target, responsible for retrieving the list of dependent projects, expects the items defined by the AssignProjectConfiguration – but never explicitly requires it.

So let's fix it!

<Target Name="FixCopyItemsFromSubsubprojects"
        DependsOnTargets="AssignProjectConfiguration" 
        BeforeTargets="_SplitProjectReferencesByFileExistence"
/>

I myself have never done this, so I will not say all the consequences of such a decision.

Scroll to Top