Неожиданный AfterTargets = "Построить" порядок выполнения для зависимых проектов - PullRequest
0 голосов
/ 28 апреля 2018

У меня два многоцелевых проекта в 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>

Проект Main

<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>

Project Main зависит от зависимости. Я ожидаю, что результат сборки будет

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

и когда я создаю решение для Visual Studio 2017, я получаю этот вывод

но когда я запускаю msbuild из cmd, я получаю следующий вывод

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

И этот порядок несколько неожиданный (и нарушает мою пользовательскую логику в реальном проекте).

Почему «DependencyAfterBuild IsCrossTargetingBuild = true» запускается позже, чем «MainAfterBuild IsCrossTargetingBuild = true»?

Как мне нужно изменить мои проекты для msbuild для запуска «DependencyAfterBuild IsCrossTargetingBuild = true» до «MainAfterBuild IsCrossTargetingBuild = true».

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Для полноты. У меня есть файл 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.

только когда я вручную изменил файл 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
0 голосов
/ 29 апреля 2018

Здесь есть несколько вещей:

Во-первых, Visual Studio строит немного по-другому - он определяет зависимости проекта, но сборки отдельных проектов могут происходить или не происходить в порядке, определяемом компонентами внутри VS. Система проекта может решить, что проект «обновлен», и полностью пропустить вызов MSBuild для этого проекта.

Вызов командной строки MSBuild для решения может поэтому вести себя немного по-другому, так как все проекты создаются по мере необходимости в не обязательно определенном порядке. Если вы изменили порядок, проекты определены в файле .sln (часть Project… EndProject), порядок будет другим.

Чтобы применить специальный oder, вы можете использовать зависимости проекта внутри решения, которые ответят на ваш вопрос о том, что вы можете с этим сделать (осторожно: при использовании этой функции были ошибки NuGet).

В вашем случае, основной проект выбирается msbuild для сборки первым.

Поскольку это проект с множественным таргетингом, он будет выделять «внутренние сборки» для каждой целевой инфраструктуры.

Эти внутренние сборки ссылаются на проект "DependencyAfterBuild", который также является проектом с множественным таргетингом. При ссылке на проект с множественным таргетингом в качестве ссылки создается только одна целевая платформа, поэтому msbuild выбирает «ближайшую целевую среду» для зависимости. Вот почему вы видите строку DependencyAfterBuild IsCrossTargetingBuild= первой (и перед аналогичными строками основного проекта).

После завершения внутренних сборок запускается ваша цель после сборки основного проекта.

Поскольку вы создаете решение, а не только основной проект, также вызывается цель Build для проекта зависимостей, просто потому, что она также находится в решении, которое вы создаете. Поскольку внутренние сборки уже выполнены, они пропускаются, и дополнительные сообщения после сборки не отображаются.

Если вы вручную добавили зависимость проекта или просто отредактировали файл .sln, чтобы изменить порядок определения проектов, вы увидите, что все цели «DependencyAfterBuild» должны быть запущены раньше всех целей основного проекта.

...