- Хроники. - -

C# Типсы триксы MSBUILD и XBUILD

Posted By Ikutsin On 22 декабря 2011 @ 18:53 In .NET C#,Автоматизация и ИИ | Comments Disabled

[1]MSBuild как и его свободный брат XBuild предназначены для автоматизации процессов сборки решений. В этой статье я попробовал собрать самые интересные и полезные моменты их использования. Это не быстрый обзор для начинающего, а закрепление знания для практикующего. Возможно, некоторые советы вам пригодятся для написания своих скриптов.

Отладка

Мало кто знает, но XML MSBuild можно запустить в режиме отладки. С ее помощью можно просмотреть текущие значения параметров и групп. Включается отладка не тривиально, и требует изменений в реестре. Для включения недокументированного параметра — /debug, используйте следующую команду:


reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\4.0" /v debuggerenabled=true /d true

После этого, комманда MSBuild /? должна показать дополнительную опцию — debug. Если запустить скрипт с этим параметром, система предложит подключить Visual Studio к процессу. В ней можно выставлять точки прерывания (breakpoints) и анализировать скрипт.

Трансформации XML файлов с помощью Document Transform синтаксиса.

Я уже рассказывал о возможности трансформаций конфигурационных файлов с помощью упрощенного синтаксиса. Во время выполнения скрипта можно преобразовать XML файлы соответственно параметрам. Подробно трансформации можно узнать из моего предыдущего поста [2]. Тут правда есть несколько подводных камней, с которыми придется бороться:

  1. TransformXml не может изменять файл который читает. Destination  — это всегда новый файл.
  2. MSBuild не отпускает файлы до завершения скрипта, по этому сделать несколько преобразований с одним файлом просто так не получится. Как вариант, каждый раз копировать файл во временный каталог.

Логирование результатов в файл.

Самый простой способ, воспользоватся цепочками консоли и перевести весь вывод в отдельный файл: msbuild script.xml > out.txt. Но в некоторых случаях (continious integration, запись промежуточных результатов с целью их чтения или преобразования и т.д.) это может не подойти. Не надо писать велосипед. Присмотритесь к стандартной библиотеке скриптов! Все делается легко и просто:


<WriteLinestoFile File="log.txt" Lines="[$(NowDate)] Some log information." />

Вызов CLR методов, совсем как в PowerShell.

В предыдущем примере используется параметр NowDate. Получить текущую дату можно с помощью CLR:

<NowDate>$([System.DateTime]::Now.ToString("dd.MM.yyyy hh:mm"))</NowDate>

Переопределение переменных

Еще один полезный прием, это инициализация пустых переменных, значениями по умолчанию. Предположим, что есть основная конфигурация, которая может меняется в зависимости от локальных настроек или целевой системы, для который происходит сборка. Получается 3 файла:

  • Файл пользовательской конфигурации. Тут переопределяются значения, отличающиеся от стандартных.
  • Файл стандартной конфигурации (значения по умолчанию). Тут нужно задавать значения только пустым параметрам.
  • Собственно сама логика скрипта (включает 2 первых по порядку).

Вот таким образом декларируются значения по умолчанию:

<Param1 Condition=" '$(Param1)' == '' ">default value for Param1</Param1>
Может возникнуть вопрос: Почему нельзя просто поставить пользовательскую конфигурацию после стандартной, и таким образом переопределить все нужные значения?

Дело в том, что выражения получения значения переменной выполняется сразу. Если у вас составная переменная, например в этом случае

<BookFile>${ContentRoot}/Books.xml</BookFile>

нужно будет переопределять обе переменные и ContentRoot и BookFile.

Циклы

Это больная тема MSBuild скриптов. Предположим у нас есть набор конфигураций с которыми нужно выполнить таск:

<ItemGroup>
	<Configs Include="Name1">
		<Environment>Env1</Environment>
		<Url>env1.test.com</CmsUrl>
	</Configs>
	<Configs Include="Name2">
		<Environment>Env2</Environment>
		<Url>env2.test.com</CmsUrl>
	</Configs>
</ItemGroup>

Выполнить таск к каждому элементу из Configs можно так:

<Target Name="ConfigsTarget">
<Message Text="Target called for $(Name) Env: $(Environment) Url: $(Url)" />
</Target>
<MSBuild Projects="$(MSBuildProjectFile)"
Properties="Name=%(Configs.Identity);Environment=%(Configs.Environment);Url=%(Configs.Url)"
Targets="ConfigsTarget" />

Пользовательские таски.

Написать таск для MSBuild проще чем может показаться. Это класс-наследник от Microsoft.Build.Utilities.Task.

Чтобы таск можно было использовать в скрипте, его надо за декларировать с помощью UsingTask:

<UsingTask AssemblyFile="BinaryAnalysis.Tasks" TaskName="BinaryAnalysis.Tasks.MyTask"/>

После этого его можно использовать по названию.

Готовые таски

Прежде чем писать свой таск для билда, убедитесь что вы не изобретаете велосипед (в 80% случаев это именно так). Вот несколько сборок, которые могут пригодится:

  • Таски от Tigris [3]. Еще известен как Community Tasks.
  • MSBuild extension pack [4]
  • И еще куча в интернете для отдельных нужд.
Может возникнуть ситуация, когда собирать надо проект, написанный на разных языках программирования. Например backend на С#, а frontend на Flash, или backend на Java, а frontend на Silverlight (интересно, такое извращение бывает?). Так как Java и Flash лучше дружат с Ant, можно воспользоватся мостом для запуска Ant скриптов из MSBuild. Такое решение отлично работает как минимум в связке: MSBuild + NAnt.

Article printed from Хроники.:

URL to article: /2211-c-tipsy-triksy-msbuild-i-xbuild

URLs in this post:

[1] Image: /wp-content/uploads/2011/12/legos0026.jpg

[2] узнать из моего предыдущего поста: /2209-transformacii-web-config-i-app-config-dlya-c-prodolzhayushhix

[3] Tigris: http://msbuildtasks.tigris.org/

[4] MSBuild extension pack: http://msbuildextensionpack.codeplex.com/

Copyright © 2008 Все, что меня окружает. All rights reserved.