Как правильно упаковать распространяемый пользовательский инструмент Nuget, который генерирует исходный код как часть сборки

Благодаря этой замечательной статье Нейта Макмастера, Я знаю, как упаковать основное консольное приложение .NET в виде пакета Nuget, который автоматически устанавливает себя как (предварительно, в данном случае) задачу сборки.

Чтобы проверить, все ли работает, я просто заставил свой собственный инструмент написать общедоступный класс C#.

Вот полный и работоспособный образец на Github.

Однако файл, который добавляет мой пользовательский инструмент, на самом деле не является частью сборки (первый, который фактически создает файл), и поэтому представленный класс не находится в сборке после первой сборки (см. Строка 38 здесь). Однако, поскольку основные проекты .NET теперь автоматически включают все файлы .cs вместе с проектом, новый класс встраивается в выходные данные последующих сборок (см. строку 57 здесь).

Однако сгенерированные файлы не удаляются при очистке и, как правило, не ведут себя так, как выводит задача MSBuild. Однако, поскольку exec происходит в целевом файле, мы должны иметь доступ ко всем механизмам, чтобы это произошло. Итак, мой вопрос:

Как мне правильно запустить пользовательский инструмент сборки (консольное приложение), который должен проверить проект, его файлы и сгенерировать исходный код (предпочтительно в obj/, например, <foo>.g.cs, который компилируется в результирующую сборку как часть одной сборки? В идеале, эти сгенерированные файлы также не должны отображаться в обозревателе решений.

Помощь!


person Ani    schedule 25.04.2019    source источник
comment
Добавьте цели сборки, которые вызываются перед фактической сборкой. Пример взят из библиотеки Refit: github.com/reactiveui/refit/ blob/master/Refit/targets/ .   -  person Styxxy    schedule 25.04.2019
comment
Я не понимаю. Это то, что я делаю здесь (github.com/aniongithub/CustomTool /blob/master/CustomTool/). Кроме того, в примере, на который вы ссылаетесь, используется UsingTask, задача MSBuild со своим собственным набором проблем, см. здесь: natemcmaster.com/blog/2017/11/11/msbuild-task-with-dependencies Я хотел бы сделать это с помощью консольного приложения + клей MSBuild, содержащий Исполнительный звонок.   -  person Ani    schedule 25.04.2019
comment
Вам нужно будет включить сгенерированный промежуточный файл в качестве элемента компиляции (см. строку 44 github.com/reactiveui/refit/blob/ ).   -  person Styxxy    schedule 26.04.2019
comment
Примечание для разрешения промежуточного пути (см. строку 11 github. com/reactiveui/refit/blob/ ).   -  person Styxxy    schedule 26.04.2019
comment
Круто, обновил мой образец и, вероятно, также превратит его в собственный шаблон dotnet! Не могли бы вы опубликовать это как ответ, чтобы я мог принять? Спасибо еще раз! :)   -  person Ani    schedule 26.04.2019
comment
Рад, что смог помочь. Я добавил это как ответ ;-).   -  person Styxxy    schedule 26.04.2019


Ответы (1)


При создании промежуточного файла (CustomTool.g.cs) в промежуточной папке (вам потребуется разрешить его, см. пример в библиотеке Refit: https://github.com/reactiveui/refit/blob/5b4e14aaf8a1fcc27396b7c08171d100aba1b97d/Refit);Ltargets#100aba1b97d/Refit вам нужно явно добавить его как элемент компиляции.

Взяв ваш пример файла target (https://github.com/aniongithub/CustomTool/blob/master/CustomTool/RunCustomTool.targets#L13):

<Project>
  <PropertyGroup>
    <IntermediateOutputPath Condition="$(IntermediateOutputPath) == '' Or $(IntermediateOutputPath) == '*Undefined*'">$(MSBuildProjectDirectory)obj\$(Configuration)\</IntermediateOutputPath>

    <!-- Command to invoke CustomTool -->
    <CustomTool>dotnet "$(MSBuildThisFileDirectory)/netcoreapp2.2/CustomTool.dll"</CustomTool>

    <!-- Other variables  -->
    <CustomVariable>"$(MSBuildProjectDir)"</CustomVariable>
  </PropertyGroup>

  <Target Name="CustomTool" BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild">
    <Exec Command="$(CustomTool) $(ProjectPath) $(IntermediateOutputPath)CustomTool.g.cs" />

    <!-- add generated file as a compile item, otherwise it won't get picked up -->
    <ItemGroup Condition="Exists('$(IntermediateOutputPath)\CustomTool.g.cs')">
      <Compile Include="$(IntermediateOutputPath)\CustomTool.g.cs" />
    </ItemGroup>
  </Target>
</Project>
person Styxxy    schedule 26.04.2019
comment
Пожалуйста, используйте ссылку Github в моем вопросе, чтобы увидеть полный источник окончательного решения. Спасибо @Styxxy! - person Ani; 26.04.2019