Как запустить сборку во время разработки при изменении файла в Rider? - PullRequest
0 голосов
/ 18 февраля 2019

Я создал пакет NuGet , который генерирует код C # из файлов DSL во время проектирования и сборки.Он отлично работает в Visual Studio, но имеет некоторые проблемы в Rider (о которых я расскажу ниже).

В Visual Studio

Пакет объявляет пользовательских элементов для DSLфайлы и присваивает им метаданные MSBuild:Compile Generator, которые запускают сборку во время разработки в Visual Studio при каждом изменении файла.

Затем настраиваемая цель подключается кпостроить с BeforeTargets="CoreCompile".Он генерирует код C # и добавляет Compile элементов в проект.Цель выполняется как в обычной, так и во время разработки, и поддерживает инкрементные сборки , чтобы избежать ненужной работы.

Вот соответствующий (упрощенный и прокомментированный) код MSBuild:

Файл props:

<Project>

  <!-- Define the item type with its default metadata -->
  <ItemDefinitionGroup>
    <ZebusMessages>
      <Generator>MSBuild:Compile</Generator>
    </ZebusMessages>
  </ItemDefinitionGroup>

  <!-- Make the item type user-visible in VS -->
  <ItemGroup>
    <AvailableItemName Include="ZebusMessages" />
    <PropertyPageSchema Include="$(MSBuildThisFileDirectory)ZebusMessages.xml" />
  </ItemGroup>

  <!-- Include all .msg files by default -->
  <ItemGroup>
    <ZebusMessages Include="**\*.msg" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
  </ItemGroup>

</Project>

Файл targets:

<Project>

  <ItemGroup>
    <!-- Add a GeneratorTargetPath metadata for the target file -->
    <ZebusMessages Update="@(ZebusMessages)" GeneratorTargetPath="$([MSBuild]::ValueOrDefault('$(IntermediateOutputPath)ZebusMessages/%(RecursiveDir)%(FileName)%(Extension).cs', '').Replace('\', '/'))" />

    <!-- Remove all None items for .msg files -->
    <None Remove="**\*.msg" />
  </ItemGroup>

  <Target Name="GenerateZebusMessages"
          BeforeTargets="CoreCompile"
          Condition="'@(ZebusMessages)' != ''"
          Inputs="@(ZebusMessages)"
          Outputs="@(ZebusMessages->'%(GeneratorTargetPath)')">

    <!-- Generate output files -->
    <GenerateZebusMessagesTask InputFiles="@(ZebusMessages)" />

    <ItemGroup>
      <!-- Add the output items -->
      <Compile Include="@(ZebusMessages->'%(GeneratorTargetPath)')" Visible="false" />
      <FileWrites Include="@(ZebusMessages->'%(GeneratorTargetPath)')" />
    </ItemGroup>
  </Target>

</Project>

Полные файлы доступны здесь .

InRider

Протестировано с Rider 2018.3.3:

Это не сработало из коробки в Rider, так как похоже, что оно не запускает сборки во время разработки, как VS.

Сначала Rider полностью не знал о сгенерированных файлах C #, из-за чего он отображал ошибки в коде, который ссылается на сгенерированные классы.

Я использовал внутренний режим Rider , который предоставляетдействие «Обновить проект и показать журналы» в проекте, которое показывает, что Rider вызывает MSBuild при загрузке проекта со следующими целями:

GenerateAssemblyInfo; _CheckForInvalidConfigurationAndPlatform; GetFrameworkPaths; ResolvePackageDependenciesDesignTime; CollectPackageReferences; BeforeResolveReferences; ResolveAssemblyReferences; ResolveComReferences; ResolveSDKReferences; ResolveCodeAnalysisRuleSet

Обратите внимание на отсутствие CompileDesignTime или Compile в этом списке.

* 1054 добавлено к этой цели. *1053* * 1054support Rider:
  <Target Name="GenerateZebusMessagesRiderDesignTime"
          Condition="'$(BuildingByReSharper)' == 'true'"
          AfterTargets="PrepareForBuild"
          DependsOnTargets="GenerateZebusMessages" />

Перехватывает PrepareForBuild, от которого зависит ResolveAssemblyReferences, и вызывает GenerateZebusMessages.

. Это позволяет Rider знать о сгенерированных файлах, но есть проблемыЯ хотел бы решить:

  • Если я отредактирую MSG-файл, сгенерированный код C # будет обновлен только при сборке проекта, а завершение кода Rider не обновится до тех пор.
  • Если я добавлю MSG-файл в проект, мне нужно перезагрузить проект, чтобы он был учтен.Построение проекта здесь не помогает.

Вопрос

Я бы хотел, чтобы Rider вызывал цель MSBuild и переоценивал проект всякий раз, когда MSG-файл редактируется или добавляется./removed.

При добавлении файла я нашел только следующее в журналах, но это мало помогает:

10:54:05.076 |I| ProjectModel                   | RequestBuilder thread:7        | Add item ZebusMessages = 'OtherFile.msg'...
10:54:05.076 |I| ProjectModel                   | RequestBuilder thread:7        | Item matches to a wildcard pattern, mark project as dirty
10:54:05.095 |I| ProjectModel                   | RequestBuilder thread:7        | Project file content requested: ZebusMessages.csproj
10:54:08.330 |I| ProjectModel                   | RequestBuilder thread:7        | Item with EvaluatedInclude 'OtherFile.msg' was already changed. Perform project reevaluation before processing.
10:54:08.361 |I| ProjectModel                   | RequestBuilder thread:7        | Project 'ZebusMessages.csproj' was reevaluated in 22 ms, EvaluationCounter: 9

Ничто другое не упоминает MSBuild в этот период времени в журналах.

Можно ли вызвать что-то похожее на сборку во время разработки в Rider при изменении данного типа файла?

Или в более общем случае, при каких обстоятельствах Rider вызывает MSBuild для переоценки проекта

1 Ответ

0 голосов
/ 18 февраля 2019

У меня есть две истории для вас - короткая и длинная =)

Короткая история

В предстоящем 2019,1 EAP 1

все должно получиться из коробки

Длинная история

Rider (в отличие от Visual Studio) не выполняет сборку во время разработки на этапе загрузки проекта.Мы считаем, что это слишком дорого (особенно для проектов на основе .net SDK).Поэтому Rider оценивает каждый проект и затем создает некоторый набор предопределенных целей для получения сгенерированных файлов и ссылок на сборки.

Иногда это вызывает проблемы (как этот), поэтому в 2019.1 мы реализовали дополнительный алгоритм, который сканирует все импортированные цели и ищет пользовательские item-factory цели.Насколько я вижу, ваша цель идеально подходит, поэтому Rider сможет найти ее и построить вместе с заранее определенными целями.

Если это не сработает, у вас останутся две опции:

  1. Мы переписали страницу опции Build Tools, так что вы сможете добавить любую произвольную цель в процесс загрузки.
  2. Покажите проблему здесь: https://youtrack.jetbrains.com/newIssue?project=Rider, и я постараюсь исправить ваше дело как можно скорее.Такие вопросы имеют для нас первостепенное значение.
...