MSBuild ProjectReference:private ("Copy Local") - what are the allowed values and behaviour?
Asked Answered
R

1

62

TL;DR Is there any official documentation that describes in detail how the <private> / "Copy Local" option works with MSBuild? And what values are supposed to go into it?


When you add a project reference from one project in Visual Studio to another, it will add a <ProjectReference Include=".....csproj"> to the .csproj MSBuild file.

When you add a file reference from one project in Visual Studio to an assembly file in the file system, it will add a <Reference Include="Foo"> <HintPath>....Foo.dll</HintPath> ... to the .csproj MSBuild file.

In both cases, for the Visual Studio Setting Copy Local = True|False, a sub-element <Private>True</Private> or <Private>False</Private> will be added.

Referenceand ProjectReference seem to be documented under Common MSBuild Project Items:

<ProjectReference>
  Represents a reference to another project.

  Item Name    Description
  -------------------------
   Name         ...
   Project      ...
   Package      ...

<Reference>
  Represents an assembly (managed) reference in the project.

  Item Name     Description
  --------------------------
   HintPath      Optional string. Relative or absolute path of the assembly.
   Name          ...
   ...
   Private       Optional string. Determines whether to copy the file to the output directory. 
                 Values are:
                     1. Never
                     2. Always
                     3. PreserveNewest

You will notice that,

  1. ProjectReference doesn't document the <private> Item at all
  2. Reference does not list Trueor False as possible values.

So. Huh? Is there any official documentation (I'll be more than happy with a good blog entry) that describes in detail how the <private> option works? Are the doc's just dead wrong or is there something more to it?


Example snippet from my VS 2013 Express here:

...
  <ItemGroup>
    <Reference Include="ClassLibrary2">
      <HintPath>C:\Somewhere\ClassLibrary2.dll</HintPath>
      <Private>True</Private>
    </Reference>
    <Reference Include="System" />
...
  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
      <Project>{861dd746-de2e-4961-94db-4bb5b05effe9}</Project>
      <Name>ClassLibrary1</Name>
      <Private>False</Private>
    </ProjectReference>
...
Rubicon answered 2/10, 2014 at 19:43 Comment(8)
interesting point (still can't find what's exact question). The only one place I've found, where that Private value is used is line 3612 in Microsoft.Common.targets: Condition="'@(_MSBuildProjectReferenceExistent)' != '' and '$(_GetChildProjectCopyToOutputDirectoryItems)' == 'true' and '%(_MSBuildProjectReferenceExistent.Private)' != 'false' and '$(UseCommonOutputDirectory)' != 'true'"Innervate
Or maybe this metadata is also being transformed to more common "CopyLocal" somewhere in MSBuild tasks - not sure I want to decompile and scan them one by one. Anyway I agree - it's undocumented and not so much info about it is given in .targets files either...Innervate
@AlexeyShcherbak - thanks for your infos. I tried to edit a bit so that there is an actual question here :-)Rubicon
Answering your question - I think docs aren't 100% correct. But I'm ok with it - this happens with msdn docs from time to time. We can spend X time and trace "Private" metadata to certain tasks - where it's being copied\used, but as I said - my gut feelings that we will end up discovering that it's close to CopyLocal or something very similar. And it's just an inconsistency in MSBuild. Do you have any real task for which you need to know exact behaviour of this metadata ?Innervate
@AlexeyShcherbak - nah, it's just that I've been wondering how it works exactly and the docs were zero help. See also: #26163868Rubicon
MSBuild is open source now, so one should be able to dig it out. (Haven't gotten round to it yet though.)Rubicon
My guess is that the VS devs initially called it "Private Copy" and some early Alpha testers said that "Private" might make people think that it is like the private modifier in source code. So, being efficient developers they changed the label in the VS UI and left the internal references as is. How many of us work on a system where a database column or code variable was "re-purposed" to contain some slightly different data but refactoring the name was never done? If you are not raising your hand you have never worked in an enterprise-level development shop! :-)Istanbul
Docs learn.microsoft.com/en-us/visualstudio/msbuild/… now align with reality ("Private Optional boolean. Specifies whether the reference should be copied to the output folder. This attribute matches the Copy Local property of the reference that's in the Visual Studio IDE."), so voting to close as "no longer reproducible", but I think this information is useful and the question should not be deleted even if it is eventually closed.Titoism
S
21

For Reference and ProjectReference items, the accepted values for Private are: True or False

This property in msbuild corresponds with the project reference property in VS as Copy Local.

I got the above answer by manually setting the reference properties in VS and viewing the xml. I couldn't find official documentation of the Private item metadata.

Checking the docs at https://msdn.microsoft.com/en-us/library/bb629388.aspx shows the accepted values as Never, Always, and PreserveNewest. These seem to be wrong and only available for the CopyLocal metadata, which is used on Content, None, and other file items.

Silverware answered 17/4, 2015 at 19:3 Comment(2)
It seams that docs at msdn.microsoft.com/en-us/library/bb629388.aspx has been updated to now say: Private: Optional boolean. Specifies whether the reference should be copied to the output folder. This attribute matches the Copy Local property of the reference that's in the Visual Studio IDE.Accentual
Updated link to docs: learn.microsoft.com/en-us/visualstudio/msbuild/…Titoism

© 2022 - 2024 — McMap. All rights reserved.