Wrt. the proposed dupe: Since this here queston suggests the opposite of the linked question, I'd rather like to think it is not a dupe.
First, I did read What is the best practice for “Copy Local” and with project references? (also this) and I'll have to try this out anyway, but getting general feedback on this seems necessary as the docs on this stuff are horrible and I'm only on VS2010 and maybe they changed something in newer versions that'll be nice to know.
Second, I'm only interested in project references for this question as I've read that assemblies from the GAC are handled differently and the GAC is irrelevant for my problem.
Third, after reading the suggested dupe, but more so the nice answer here by @Albireo, it would also appear that it is important to differentiate file dependencies, where the dependency references a dll assembly file and project dependencies (i.e. what I'm asking about), where the dependency references a project and implicitly the output file of that project.
/x1
for executable 1 project/x2
for executable 2 project/lib
for all the dll assembliesThe DLL assemblies all have Copy Local
set to false
for their project references, as they all build to the same output directory.
The 2 executable projects have set Copy Local
to true
for all the DLL assembly project references they reference directly, so that the DLLs will be copied into /x1
/x2
respectively.
The question now is wrt. to DLLs that are not directly referenced by an executable project, but only transitively through a referenced assembly: Will assemblies, that are only referenced transitively through another assembly, be copied into the output folder of the executable, when "Copy Local" is set to true on the first assembly?
Example:
x1.csproj
(e.g.Output = x1/one.exe
)
dlA.csproj
( e.g. Output = lib/a.dll
) with Copy Local = *true*
dlA.csproj
( e.g. Output = lib/a.dll
)
dlB.csproj
( e.g. Output = lib/b.dll
) with Copy Local = **false**
dlC.csproj
( e.g. Output = lib/c.dll
)
Thus, we have a logical dependency of one.exe -> a.dll -> b.dll -> c.dll
, where only a.dll
with obviously be copied to the output directory of one.exe
. Will the other two dlls also be copied to the output directory? Is this documented somewhere?
And, yes, I tried it. And, yes, it seems to work, but I haven't poked it hard enough yet and anyway there maybe something more to it that I may have missed. (And also there's the question wrt. any official docs.)
it would also appear that it is important to differentiate file dependencies, where the dependency references a dll assembly file and project dependencies (i.e. what I'm asking about), where the dependency references a project and implicitly the output file of that project.
Not really, no.
MSBuild doesn't really care if the reference points to another project in the solution or to a DLL.
If ProjectA
depends on ProjectB
to build ProjectA
ProjectB
must be already built (and up-to-date), MSBuild will then pull its DLL (not its C# code) and link it to ProjectA
.
Adding a project reference instead of a DLL is "syntactic sugar" for your convenience: this way MSBuild knows it must pick the output of the referenced project, whatever the output is.
Otherwise, you'll have to manually pre-build the dependency, find its DLL and link it to the project, repeating the process whenever you switch build configuration, move or rename things. Not really practical.
Will the other two dlls also be copied to the output directory?
If any kind of element from a dependency is used directly from the project where the assembly is referenced, that reference will be copied.
An example could be this solution layout:
With this dependency chain:
If you build this solution you'll notice that in MySolution.ConsoleApplication
output directory there will be the DLLs for MySolution.FirstDependency
, MySolution.SecondDependency
and MySolution.ThirdDependency
but no DLL for MySolution.FourthDependency
.
Why is it so? When MSBuild builds MySolution.SecondDependency
it notices that there's a dependency declared to MySolution.FourthDependency
, but since it can't find any usage of any kind of element from MySolution.FourthDependency
in MySolution.SecondDependency
code it decides to perform some "optimization" and omits MySolution.FourthDependency
assembly from the output.
This same issue bit me in the past when I added through NuGet AutoMapper to a "deep dependency": adding AutoMapper adds two assembly references, AutoMapper
and AutoMapper.Net4
, where the second assembly is loaded by the first through reflection when it needs to perform certain kind of action on the new collection objects introduced by the .NET Framework 4. Since the second assembly is loaded through reflection MSBuild thinks it's unused and doesn't bother to copy it around.
So, yes, they will be copied as long as you're using them directly and not through reflection.
Is this documented somewhere?
This behavior seems to be a "feature" of MSBuild, I managed to find a blog post by some folks from Microsoft back when I experienced this issue, but I can't find it again at the moment.