Is Copy Local Transitive for project references?

Wrt. suggested fraud:. Since this criterion suggests the opposite of a related question , I would rather think that this is not a hoax.

First , I read. What is the best practice for "Copy local" and with links to projects? (also this ), and I still have to try this, but getting general feedback on this seems necessary, since the docs on this material are terrible, and I'm only on VS2010 and maybe they changed something in newer versions, who will be pleased to know.

Second , I’m only interested in the project’s links on this issue, since I read that assemblies from the GAC are handled differently and the GAC is not related to my problem.

A third , after reading the suggested trick, but all the more pleasant answer here by @Albireo, it would also seem that it is important to distinguish between file dependencies, where the dependency refers to the dll assembly file and the project-dependent dependencies (that is, what I'm asking), where the dependency refers to the project and the implicit output file of this project.

In any case, here the situation is somewhat peculiar, I think, but still:

  • 2 executable C # projects
  • n cll dll build projects
  • The 2 executable files have different output directories, because they will be deployed separately and thus they will also be separate on the developer's machine.
  • 2 executable files have dependencies on some DLL assemblies (which may depend on each other)
  • There are three output directories:
    • /x1 for executable project 1
    • /x2 for executable project 2
    • /lib for all dll builds

All DLL assemblies have Copy Local for their project references, since they are all built in the same directory.

2 executable projects set Copy Local to true for all references to the DLL assembly project, the links to which they link directly, so the DLLs will be copied to /x1 /x2 respectively.

There is a question now. to DLLs that do not directly link to an executable project, but only in transit through a reference assembly: Are assemblies that only link in transit from another assembly are copied to the output folder of the executable when "Copy local" is set to true on the first assembly?

Example:

  • x1.csproj (for example, Output = x1/one.exe )
    • Link: dlA.csproj (e.g. Output = lib/a.dll ) with Copy Local = *true*
    • (without link to b.dll)
  • dlA.csproj (e.g. Output = lib/a.dll )
    • Link: dlB.csproj (e.g. Output = lib/b.dll ) with Copy Local = **false**
    • (no direct link to c.dll)
  • dlC.csproj (e.g. Output = lib/c.dll )
    • (no additional links)

Thus, we have a logical dependence on one.exe -> a.dll -> b.dll -> c.dll , where only a.dll is obviously copied to the one.exe output directory. Will the other two DLLs be copied to the output directory? Is it documented anywhere?




And, yes, I tried. And, yes, it seems to work, but I haven't done it too much yet, and in any case, there might be something else that I might have missed. (And there is also a question on any official documents.)

+25
c # visual-studio msbuild
Oct 02 '14 at 2:43 on
source share
2 answers

it would also seem that it is important to distinguish between file dependencies, where the dependency refers to the dll assembly file and project-dependent dependencies (i.e. what I ask for), where the dependency refers to the project and implicitly displays the file of this project.

Not really, no.

MSBuild does not care if the link refers to another project in the solution or to the DLL.

If ProjectA depends on ProjectB to build ProjectA ProjectB should already be built (and updated), MSBuild will then pull out its DLL (and not its C # code) and link it to ProjectA .

Adding a project link instead of a DLL is “syntactic sugar” for your convenience: in this way, MSBuild knows that it must choose the output of the project it refers to, no matter what the result.

Otherwise, you will have to manually create the dependency first, find its DLL and associate it with the project, repeating the process when you switch assembly configuration, move or rename things. Not very practical.

Will the other two DLLs be copied to the output directory?

If any element from the dependency is used directly from the project referenced by the assembly, this link will be copied.

An example is this solution layout:

  • Mysolution
    • MySolution.ConsoleApplication
    • MySolution.FirstDependency
    • MySolution.SecondDependency
    • MySolution.ThirdDependency
    • MySolution.FourthDependency

With this dependency chain:

  • MySolution.ConsoleApplication
    • MySolution.FirstDependency
      • MySolution.SecondDependency
        • MySolution.ThirdDependency
        • MySolution.FourthDependency

If you create this solution, you will notice that in the output directory MySolution.ConsoleApplication will be DLLs for MySolution.FirstDependency , MySolution.SecondDependency and MySolution.ThirdDependency , but there is no DLL for MySolution.FourthDependency .

Why is that? When MSBuild creates MySolution.SecondDependency , he notices that there is a dependency declared in MySolution.FourthDependency , but since it cannot find any use of any element from MySolution.FourthDependency in the MySolution.SecondDependency code, he decides to do some “optimization” and omits MySolution.FourthDependency MySolution.FourthDependency assembly.

The same problem bit me in the past when I added “deep dependency” through NuGet AutoMapper: adding AutoMapper adds two assembly links, AutoMapper and AutoMapper.Net4 , where the second assembly is loaded first by reflecting when it needs to perform a certain action on new collection objects provided by the .NET Framework 4. Since the second assembly is loaded via reflection, MSBuild considers it unused and does not attempt to copy it.

So yes, they will be copied as long as you use them directly and not through reflection.

Is it documented anywhere?

This behavior seems to be a “feature” of MSBuild, I was able to find a blog post from some people from Microsoft when I ran into this problem, but I cannot find it again at the moment.

+22
Oct 02 '14 at 15:11
source share

This is very straightforward, has nothing to do with Copy Local. MSBuild looks at the assembly metadata to find out what dependencies to build. So you can, run ildasm.exe on the assembly and double-click the manifest. Be sure to try this to get an idea. You will see .assembly directives. Inserted by the compiler during its assembly, only reference assemblies that you actually used in your code will be listed.

If MSBuild can find such an assembly in the same directory, it will automatically copy it. If not, he will silently skip the copy.

From this you can infer failure modes. It cannot copy unmanaged DLLs; they do not appear in metadata. It cannot copy assemblies that have an indirect dependency through Assembly.Load / From (), they also do not appear in the metadata. It cannot copy assemblies that have not yet been created, a problem with the assembly order. And it cannot copy assemblies for which the Copy Local property is set to False. This is usually a valid choice, if the assembly is present in the GAC, no copying is required.

For such cases, you need to help, XCOPY in the event after the assembly receives the task.

+16
Oct 03 '14 at 9:58
source share



All Articles