【问题标题】:Unexpected AfterTargets="Build" execution order for dependent projectsUnexpected AfterTargets="Build" 依赖项目的执行顺序
【发布时间】:2018-04-28 20:02:06
【问题描述】:

我在 Visual Studio 2017 中有两个多目标项目。

项目依赖

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks>
  </PropertyGroup>

  <Target Name="DependencyAfterBuild" AfterTargets="Build">
    <Message Text="DependencyAfterBuild  IsCrossTargetingBuild=$(IsCrossTargetingBuild)" />
  </Target>

</Project>

项目主要

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks>
  </PropertyGroup>

    <PropertyGroup>
        <TestProperty>Exe</TestProperty>
    </PropertyGroup>

  <Target Name="MainAfterBuild" AfterTargets="Build">
    <Message Text="MainAfterBuild IsCrossTargetingBuild=$(IsCrossTargetingBuild)" />
  </Target> 

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\Dependency.csproj" />
  </ItemGroup>

</Project>

项目主要依赖于依赖。 我希望构建输出是

DependencyAfterBuild  IsCrossTargetingBuild=
DependencyAfterBuild  IsCrossTargetingBuild=
DependencyAfterBuild  IsCrossTargetingBuild=true
MainAfterBuild IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=true

当我使用 Visual Studio 2017 构建解决方案时,我得到了该输出

但是当我从 cmd 运行 msbuild 时,我得到下一个输出

DependencyAfterBuild  IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=
DependencyAfterBuild  IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=true
DependencyAfterBuild  IsCrossTargetingBuild=true

而且这个顺序有点出乎意料(并且破坏了我在实际项目中的自定义逻辑)。

为什么“DependencyAfterBuild IsCrossTargetingBuild=true”比“MainAfterBuild IsCrossTargetingBuild=true”运行晚?

我需要如何修改我的项目以使 msbuild 在“MainAfterBuild IsCrossTargetingBuild=true”之前运行“DependencyAfterBuild IsCrossTargetingBuild=true”。

【问题讨论】:

  • 您正在构建其中一个项目还是解决方案?如果只是构建它的项目,我希望少一行(我可以在答案中解释,但我需要检查一下)
  • 我建立了一个解决方案

标签: msbuild msbuild-target


【解决方案1】:

这里有几件事在起作用:

首先,Visual Studio 的构建方式略有不同——它会计算项目依赖关系,但单个项目的构建可能会发生也可能不会发生,其顺序由 VS 内部的组件解决。项目系统可能会确定一个项目是“最新的”并完全跳过为该项目调用 MSBuild。

因此,在解决方案上调用命令行 MSBuild 的行为可能会有所不同,因为所有项目都是根据需要按特定顺序构建的。如果您更改了在 .sln 文件中定义项目的顺序(Project… EndProject 部分),则顺序会有所不同。

要强制执行一个特殊的命令,您可以在解决方案中使用项目依赖项,这将回答您可以做些什么的问题(注意:使用此功能时存在 NuGet 错误)。

在您的情况下,主项目由 msbuild 选择首先构建。

由于它是一个多目标项目,它将为每个目标框架衍生“内部构建”。

这些内部构建引用了“DependencyAfterBuild”项目,该项目也是一个多目标项目。当一个多目标项目被引用时,只会构建一个目标框架作为参考——因此 msbuild 为依赖项选择“最近的目标框架”。这就是为什么您会首先看到 DependencyAfterBuild IsCrossTargetingBuild= 行(以及在主项目的类似行之前)。

内部构建完成后,您的主项目的构建目标运行。

由于您正在构建解决方案而不是单独构建主项目,因此也会调用依赖项目的“构建”目标,因为它也在您正在构建的解决方案中。由于内部构建已经执行,它们被跳过并且不会显示额外的构建后消息。

如果您手动添加项目依赖项或简单地编辑 .sln 文件以更改项目的定义顺序,您会看到所有“DependencyAfterBuild”目标在所有主项目的目标之前运行。

【讨论】:

  • 谢谢。使用项目依赖项和构建顺序窗口时,我可以看到构建顺序具有第一个依赖项和下一个主项。但是目标输出的顺序仍然不正确。只有当我在主项目的 sln 文件 (ProjectSection(ProjectDependencies) = postProject ...) 中手动添加构建依赖项时,我才会得到正确的输出。
  • 有趣。但请注意,除非您点击“全部保存”或关闭 VS 窗口,否则 VS 不会保存 sln 文件,因此在您再次调用命令行 msbuild 之前,您的更改可能尚未保存到磁盘。
【解决方案2】:

为了完整性。 我有sln文件

Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Main", "ConsoleApp16\Main.csproj", "{52892173-D25E-43B7-9E14-248C37CF422B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dependency", "ClassLibrary1\Dependency.csproj", "{14E1692E-FDB4-46F7-85DF-7B6EFF7B46A6}"
EndProject

并且在 msbuild 中以意外的顺序调用了 afterbuild 目标。

仅当我如下手动更改 sln 文件时

Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Main", "ConsoleApp16\Main.csproj", "{52892173-D25E-43B7-9E14-248C37CF422B}"
    ProjectSection(ProjectDependencies) = postProject
        {14E1692E-FDB4-46F7-85DF-7B6EFF7B46A6} = {14E1692E-FDB4-46F7-85DF-7B6EFF7B46A6}
    EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dependency", "ClassLibrary1\Dependency.csproj", "{14E1692E-FDB4-46F7-85DF-7B6EFF7B46A6}"
EndProject

我设法获得了“所需”的执行顺序,如下所示

DependencyAfterBuild  IsCrossTargetingBuild=
DependencyAfterBuild  IsCrossTargetingBuild=
DependencyAfterBuild  IsCrossTargetingBuild=true
MainAfterBuild IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=
MainAfterBuild IsCrossTargetingBuild=true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-22
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多