在MSBuild项目文件中,ProjectReference的“Private”设置是什么作用?

168

我前几天在一个项目文件中看到了这个:

<ProjectReference Include="Foo\Bar\Baz.csproj">
    <Project>{A GUID HERE}</Project>
    <Name>Baz</Name>
    <Private>False</Private> <!-- ??? -->
    <ReferenceOutputAssembly>False</ReferenceOutputAssembly>
</ProjectReference>

每个中的节点都很容易理解(引用的项目文件、GUID、在解决方案资源管理器中显示的名称以及当前项目是否应链接到引用的项目),除了Private之外,Common MSBuild Project Items页面没有记录这个值。(在而不是中记录了一个Private设置,但它有Never、Always和PreserveNewest设置,而不是true和false)
这个设置是做什么用的?

2
就 MSBuild 而言,ProjectReference 是一个项目组 (即列表),而 Private 是所包含项目的项元数据。你的问题的答案取决于任何包含它的内容。更一般地说,它是哪种特定类型的项目?或许你可以给你的问题打上 csharp 的标签。 - Tom Blodget
我是指“导入”而不是“包含”。 - Tom Blodget
@malexander:如果您能恢复删除的答案,我认为您的回答很好。 - Billy ONeal
2
@Tom:当然,严格来说是这样的。另一方面,“ProjectReference”项被(至少)C#和C++ MSBuild支持基础设施所识别;看起来它主要在“Microsoft.Common.CurrentVersion.targets”文件中处理。 - Billy ONeal
2个回答

170

ProjectReference 项目项上的私有元数据对应于 Visual Studio 解决方案资源管理器中引用节点上的“复制本地”属性。

它控制着引用是否应该被复制到输出文件夹中:

  • true 表示引用应该被复制
  • false 表示引用不应该被复制

这在 Common MSBuild project items 中有文档记录,以及在 MSBuild 源代码中本身也有文档记录 Microsoft.Common.CurrentVersion.targets

<!--
============================================================

                  ResolveAssemblyReferences

Given the list of assemblies, find the closure of all assemblies that they depend on. These are
what we need to copy to the output directory.

    [IN]
    @(Reference) - List of assembly references as fusion names.
    @(_ResolvedProjectReferencePaths) - List of project references produced by projects that this project depends on.

        The 'Private' attribute on the reference corresponds to the Copy Local flag in IDE.
        The 'Private' flag can have three possible values:
            - 'True' means the reference should be Copied Local
            - 'False' means the reference should not be Copied Local
            - [Missing] means this task will decide whether to treat this reference as CopyLocal or not.

    [OUT]
    @(ReferencePath) - Paths to resolved primary files.
    @(ReferenceDependencyPaths) - Paths to resolved dependency files.
    @(_ReferenceRelatedPaths) - Paths to .xmls and .pdbs.
    @(ReferenceSatellitePaths) - Paths to satellites.
    @(_ReferenceSerializationAssemblyPaths) - Paths to XML serialization assemblies created by sgen.
    @(_ReferenceScatterPaths) - Paths to scatter files.
    @(ReferenceCopyLocalPaths) - Paths to files that should be copied to the local directory.

============================================================
-->

4
如果缺少<Private>,则不等同于True。搜索“MSBuild CopyLocal bug”。例如,参见https://dev59.com/PXNA5IYBdhLWcg3wAIxP。 - xmedeko
8
@xmedeko,没错。我不确定 @GPR 是从哪里得到的“如果缺失,则假定默认值为True”的信息,因为答案明确表示“[缺失]意味着此任务将决定是否将此引用视为 CopyLocal”。大部分逻辑都在msbuild\Reference.cs:949中。 - Mitch
1
如果应用程序没有使用引用,即使将 <Private> 设置为 True,MSBuild 仍然不会将其包含在输出中,这种情况是否可能发生?这是我本地得到的当前行为... - Ninja
@Ninja,这种情况最常见的原因是MSBuild无法找到所引用的程序集。如果该程序集未直接被代码使用,它仍然可以成功编译。您可以使用procmonMSBuild详细日志记录进行故障排除。 - Mitch
1
这些是我的私人文件...随便复制吧 - undefined
显示剩余3条评论

2
我想强调一下,<Private>false</Private>(可以应用于ProjectReference)可能在使用<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Publish" Properties="$(_MSBuildProperties)" />并且项目$(MSBuildProjectFullPath)具有ProjectReference,这些ProjectReference具有<None><CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory></None>时可能无法正常工作。我已经阅读了https://github.com/dotnet/sdk/blob/master/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets周围的源代码,并找到了解决方案。您需要定义_GetChildProjectCopyToPublishDirectoryItems=false,因此示例如下:<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="Publish" Properties="TargetFramework=$(TargetFramework);_GetChildProjectCopyToPublishDirectoryItems=false" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接