ResolveProjectReferences如何工作?

时间:2011-09-01 08:58:14

标签: msbuild build resolveassemblyreference

我想描述和调整我们的构建希望在这里和那里节省几秒钟。我能够创建一个派生自ResolveAssemblyReferences的任务并使用它,但我在理解以下内容时遇到了问题(来自Microsoft.Common.targets):

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

    Build referenced projects:

        [IN]
        @(NonVCProjectReference) - The list of non-VC project references.

        [OUT]
        @(_ResolvedProjectReferencePaths) - Paths to referenced projects.
    ============================================================
    -->
    <Target
        Name="ResolveProjectReferences"
        DependsOnTargets="SplitProjectReferencesByType;_SplitProjectReferencesByFileExistence">

        <!--
        When building this project from the IDE or when building a .SLN from the command-line,
        just gather the referenced build outputs.  The code that builds the .SLN will already have
        built the project, so there's no need to do it again here.

        The ContinueOnError setting is here so that, during project load, as
        much information as possible will be passed to the compilers.
        -->
        <MSBuild
            Projects="@(_MSBuildProjectReferenceExistent)"
            Targets="GetTargetPath"
            BuildInParallel="$(BuildInParallel)"
            UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)"
            Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)"
            Condition="'@(NonVCProjectReference)'!='' and ('$(BuildingSolutionFile)' == 'true' or '$(BuildingInsideVisualStudio)' == 'true' or '$(BuildProjectReferences)' != 'true') and '@(_MSBuildProjectReferenceExistent)' != ''"
            ContinueOnError="!$(BuildingProject)">

            <Output TaskParameter="TargetOutputs" ItemName="_ResolvedProjectReferencePaths"/>
        </MSBuild>

        <!--
        Build referenced projects when building from the command line.

        The $(ProjectReferenceBuildTargets) will normally be blank so that the project's default
        target is used during a P2P reference. However if a custom build process requires that
        the referenced project has a different target to build it can be specified.
        -->
        <MSBuild
            Projects="@(_MSBuildProjectReferenceExistent)"
            Targets="$(ProjectReferenceBuildTargets)"
            BuildInParallel="$(BuildInParallel)"
            UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)"
            Condition="'@(NonVCProjectReference)'!='' and '$(BuildingInsideVisualStudio)' != 'true' and '$(BuildingSolutionFile)' != 'true' and '$(BuildProjectReferences)' == 'true' and '@(_MSBuildProjectReferenceExistent)' != ''">
            <Output TaskParameter="TargetOutputs" ItemName="_ResolvedProjectReferencePaths"/>

        </MSBuild>

        <!--
        Get manifest items from the (non-exe) built project references (to feed them into ResolveNativeReference).
        -->
        <MSBuild
            Projects="@(_MSBuildProjectReferenceExistent)"
            Targets="GetNativeManifest"
            BuildInParallel="$(BuildInParallel)"
            UnloadProjectsOnCompletion="$(UnloadProjectsOnCompletion)"
            Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform)"
            Condition="'@(NonVCProjectReference)'!='' and '$(BuildingProject)'=='true' and '@(_MSBuildProjectReferenceExistent)'!=''">

            <Output TaskParameter="TargetOutputs" ItemName="NativeReference"/>

        </MSBuild>


        <!-- Issue a warning for each non-existent project. -->
        <Warning
            Text="The referenced project '%(_MSBuildProjectReferenceNonexistent.Identity)' does not exist."
            Condition="'@(NonVCProjectReference)'!='' and '@(_MSBuildProjectReferenceNonexistent)'!=''"/>
    </Target>

传递了一些参数并返回了一些参数,但实际工作在哪里发生?在msdn上没有太多 - 我找到了Microsoft.Build.Tasks.ResolveProjectBase,但它的用处不大。

1 个答案:

答案 0 :(得分:13)

ResolveProjectReferences(至少是您指向的那个)是一个目标,用于通过使用<MSBuild>任务构建项目间引用来解决它们。此任务需要构建一个项目文件,以及项目中应该作为构建的一部分调用的一个或多个目标的名称(它还需要其他参数,但您现在可以忽略它们。)

考虑以下目标:

<Target
  Name="Build"
  Returns="@(BuildOutput)">

  <ItemGroup>
    <BuildOutput Include="bin\Debug\Foo.exe" />
  </ItemGroup>
</Target>

如果您引用了包含此目标的项目,并希望解析“Foo”目标的输出,那么您将拥有&lt; ProjectReference&gt;项目中的元素如下:

<ItemGroup>
  <ProjectReference Include="..\SomeProject\SomeProject.proj">
    <Targets>Build</Targets>
  </ProjectReference>
</ItemGroup>

请注意,如果“Build”是引用项目的默认目标,则可以完全关闭“Targets”元数据。您还可以在“目标”元数据中指定多个目标(以分号分隔的列表)。

所以你的ResolveProjectReferences目标会出现并调用&lt; MSBuild&gt;任务,传递它“.. \ SomeProject \ SomeProject.proj”并要求它构建“Build”目标。现在,由于“Build”目标通过其Returns属性指定输出(但如果未指定Returns属性,则将使用Outputs属性),这些输出将在构建期间收获,并在&lt; MSBuild&gt;处返回。 tasks的TargetOutputs参数。他们添加了几个额外的元数据,使您可以通过发起目标来隔离它们。其中包括:

  • MSBuildSourceProjectFile - 其构建生成输出的引用项目
  • MSBuildSourceTargetName - 构建生成输出的目标的名称

如果您在C#项目中工作,则还有许多其他阶段的参考分辨率(包括装配分辨率)。如果你想了解这些,请给我留言。