MSBuild Post-Build
У меня есть сценарий MSBuild, который почти выполняет все, что мне нужно, кроме шага после сборки (см. Предыдущий вопрос, который я задал: условный Exec MSBuild?).
Я собираюсь собрать множество файлов csproj и при необходимости выполнить шаги после сборки, если и только если проект был собран. Я не хочу выполнять мой шаг после сборки все время, иначе временная метка на моем конечном выводе будет изменена без необходимости (и это делает процесс сборки очень трудоемким без какой-либо причины).
В моем скрипте MSBuild у меня есть что-то вроде следующего для каждого из моих файлов csproj:
<Target Name="ProjectName">
<MSBuild Projects="PathToProject" Properties="Configuration=$(buildtype)" />
</Target>
Изменить: я думаю, что я действительно хочу сделать, это определить, когда задача CoreCompile выполняется для каждого проекта. Если бы был какой-то способ проверить это в состоянии?
Есть идеи?
Я новичок в MSBuild, так что, возможно, я на неправильном пути!
Спасибо алан
3 ответа
После долгих поисков простого решения этой проблемы я не нашел его и в итоге нашел собственное решение, которое работает, но, возможно, не является лучшим решением. Тем не менее, я хотел бы поделиться этим с кем-то, у кого есть такая же проблема, чтобы вы могли по крайней мере иметь рабочее решение и, надеюсь, избавить вас от большого количества ударов головой.
Напомним, что я хотел сделать, это запустить инструмент командной строки после того, как мой проект был построен, но только если сборка была обновлена (т.е. изменилась временная метка). Я не хотел помещать это в раздел пост-сборки каждого проекта, потому что я хотел, чтобы пост-сборка происходила только на нашем сервере сборки (не на машинах разработки).
Я не нашел никакого способа сделать это внешне в моем основном файле.proj и в конечном итоге изменил раздел после сборки каждого файла.csproj. Однако я поставил перед ним условие if примерно так:
if '$(ExecuteCommand)' == 'true' command.exe
Это означает, что команда никогда не будет выполнена на компьютере разработчика, но когда я вызываю сборку из моего файла.proj, я могу установить для этого флага значение true следующим образом:
<!-- Define common properties -->
<PropertyGroup>
<ExecuteCommand>true</ExecuteCommand>
</PropertyGroup>
<Target Name="YourTarget">
<!-- Build project -->
<MSBuild Projects="Path to project" Properties="ExecuteCommand=$(ExecuteCommand)" />
</Target>
Как я уже сказал, я не думаю, что это самое изящное решение, но оно, безусловно, работает и будет достаточно для меня на данный момент. Однако мне все равно было бы интересно услышать, как правильно добиться этого, чтобы я мог улучшить свой сценарий.
Спасибо алан
Вы также можете сделать это на основе конфигурации, выбранной в процессе сборки. Для CI вы всегда должны использовать "Release" или "Production" (вы можете определить свой собственный)
<Exec Condition="'$(ConfigurationName)'=='Release'" Command="your command goes here ..."/>
Если вы можете добавить следующее к каждому из ваших проектов:
<Target Name="DoStuffWithNewlyCompiledAssembly">
<Exec Command="command.exe" />
</Target>
... тогда вам нужно только добавить свойство:
<Target Name="Name">
<MSBuild Projects="" Properties="TargetsTriggeredByCompilation=DoStuffWithNewlyCompiledAssembly" />
</Target>
Это работает, потому что кто-то умный в Microsoft добавил следующую строку в конце CoreCompile
цель в Microsoft.[CSharp|VisualBasic][.Core].targets
(имя файла зависит от языка и версии MSBuild/Visual Studio).
<CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''"/>
Так что, если вы укажете имя цели в TargetsTriggeredByCompilation
свойство, ваша цель будет работать, если CoreCompile
работает - и ваша цель не будет работать, если CoreCompile
пропускается (например, потому что выходная сборка уже обновлена по отношению к коду).