Сборка на NAnt и двух платформах - лучший способ сборки на Windows И Mono / Linux
-
09-06-2019 - |
Вопрос
Я новичок в NAnt, но имею некоторый опыт работы с Ant и CruiseControl.
Что я хочу сделать, так это включить в мой проект SVN все необходимые инструменты (например, NUnit, Mocks и т.д.), Чтобы я мог проверить их на новой машине и выполнить сборку.Эта стратегия изложена Дж.П. Будху вот.
Пока все хорошо, если я хочу работать только в Windows, но я хочу иметь возможность проверить на Linux и также создавать / тестировать / запускать на Mono.Я не хочу никаких зависимостей, внешних по отношению к проекту SVN.Я не возражаю против наличия двух наборов инструментов в проекте, но хочу только один файл сборки NAnt
Это должно быть возможно - но как?каковы хитрости / "ловушки для молодых игроков"
Решение
Это не должно быть особенно сложным упражнением.Мы делаем довольно похожие вещи в одном из моих проектов, поскольку половина из них выполняется на Java, используя Ant для запуска соответствующих целевых объектов, а другая половина - .Net (C #) для пользовательского интерфейса.Проекты запускаются на компьютерах с Windows для разработки, но серверы (Java) работают под управлением linux, но в среде UAT (linux) нам нужно запустить nunits (интеграционные тесты).Реальный трюк (на самом деле не сложный трюк), стоящий за этим, заключается в наличии файла сборки NAnt, который может запускаться в обеих средах, что, похоже, является тем же самым, что вы пытаетесь сделать здесь.
Конечно, вы понимаете, что сначала вам нужно будет установить NAnt на Mono:
$ export MONO_NO_UNLOAD=1
$ make clean
$ make
$ mono bin/NAnt.exe clean build
И затем ваш файл сборки должен быть написан таким образом, чтобы он разделял проблемы.Например, некоторые части файла сборки, написанные для Windows, не будут работать в Linux.Так что вам действительно просто нужно разделить его на конкретные цели в файле сборки.После этого есть несколько способов запустить определенные целевые объекты из командной строки.Пример может выглядеть следующим образом:
<project name="DualBuild">
<property name="windowsDotNetPath" value="C:\WINDOWS\Microsoft.NET\Framework\v3.5" />
<property name="windowsSolutionPath" value="D:\WorkingDirectory\branches\1234\source" />
<property name="windowsNUnitPath" value="C:\Program Files\NUnit-Net-2.0 2.2.8\bin" />
<property name="monoPath" value="You get the idea..." />
<target name="BuildAndTestOnWindows" depends="WinUpdateRevision, WinBuild, WinTest" />
<target name="BuildAndTestOnLinux" depends="MonoUpdateRevision, MonoBuild, MonoTest" />
<target name="WinUpdateRevision">
<delete file="${windowsSolutionPath}\Properties\AssemblyInfo.cs" />
<exec program="subwcrev.exe" basedir="C:\Program Files\TortoiseSVN\bin\"
workingdir="${windowsSolutionPath}\Properties"
commandline="${windowsSolutionPath} .\AssemblyInfoTemplate.cs
.\AssemblyInfo.cs" />
<delete file="${windowsSolutionPath}\Properties\AssemblyInfo.cs" />
<exec program="subwcrev.exe" basedir="C:\Program Files\TortoiseSVN\bin\"
workingdir="${windowsSolutionPath}\Properties"
commandline="${windowsSolutionPath} .\AssemblyInfoTemplate.cs
.\AssemblyInfo.cs" />
</target>
<target name="WinBuild">
<exec program="msbuild.exe"
basedir="${windowsDotNetPath}"
workingdir="${windowsSolutionPath}"
commandline="MySolution.sln /logger:ThoughtWorks.CruiseControl.MsBuild.XmlLogger,
ThoughtWorks.CruiseControl.MsBuild.dll;msbuild-output.xml
/nologo /verbosity:normal /noconsolelogger
/p:Configuration=Debug /target:Rebuild" />
</target>
<target name="WinTest">
<exec program="NCover.Console.exe"
basedir="C:\Program Files\NCover"
workingdir="${windowsSolutionPath}">
<arg value="//x "ClientCoverage.xml"" />
<arg value=""C:\Program Files\NUnit-Net-2.0 2.2.8\bin
\nunit-console.exe"
MySolution.nunit /xml=nunit-output.xml /nologo" />
</exec>
</target>
<target name="MonoUpdateRevision">
You get the idea...
</target>
<target name="MonoBuild">
You get the idea...
</target>
<target name="MonoTest">
You get the idea...
</target>
</project>
Для краткости я опустил обе стороны.Самое приятное, что вы можете использовать NUnit так же, как и NAnt, в обеих средах, и это действительно упрощает задачу с точки зрения зависимости.И для каждого исполняемого файла вы можете заменить его на другие, которые работают в этой среде, например (xBuild для MSBuild, svn для tortoise и т.д.)
Для получения дополнительной помощи по Nunit и т.д. в Mono ознакомьтесь этот фантастический пост.
Надеюсь, это поможет,
Ваше здоровье,
Роб Джи
Другие советы
@Роб Джи - Привет!Это мой пост!;)
Для получения некоторых других хороших примеров обязательно просмотрите исходный код NUnit.Я тесно сотрудничаю с Charlie, когда могу, чтобы убедиться, что он создается и тестируется на Mono.Он тоже пытается убежать, когда только может.
Стоит отметить, что многие инструменты, такие как Nant, запускаются на mono "из коробки", т.е.
mono nant.exe
работает
Я использую следующий шаблон.Это позволяет легко создавать на любой платформе (build
на Победу или ./build.sh
в Linux) и минимизирует дублирование в сценариях сборки.
Исполняемый файл NAnt хранится вместе с проектом в tools\nant
.
Файл конфигурации сборки определяет, какой инструмент сборки использовать, либо MSBuild, либо xbuild (в данном случае для Windows мне требуется версия VS2015 MSBuild, измените путь по мере необходимости).
Тот Самый build-csproj
цель сборки можно использовать повторно, если у вас есть несколько проектов в рамках решения.
Тот Самый test-project
цель должна быть расширена в соответствии с вашими потребностями.
build.летучая мышь
@tools\nant\nant.exe %*
build.sh
#!/bin/sh
/usr/bin/cli tools/nant/NAnt.exe "$@"
по умолчанию.сборка
<?xml version="1.0"?>
<project name="MyProject" default="all">
<if test="${not property::exists('configuration')}">
<property name="configuration" value="release" readonly="true" />
</if>
<if test="${platform::is-windows()}">
<property name="BuildTool" value="C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" readonly="true"/>
</if>
<if test="${platform::is-unix()}">
<property name="BuildTool" value="xbuild" readonly="true"/>
</if>
<property name="TestTool" value="tools/mytesttool.exe"/>
<target name="all" depends="myproject myprojectlib" />
<target name="build-csproj" description="Build a given csproj">
<!-- Must not be called standalone as it requires some properties set. -->
<exec program="${BuildTool}">
<arg path="src/${ProjectName}/${ProjectName}.csproj" />
<arg line="/property:Configuration=${configuration}" />
<arg value="/target:Rebuild" />
<arg value="/verbosity:normal" />
<arg value="/nologo" />
</exec>
</target>
<target name="test-project">
<!-- Must not be called standalone as it requires some properties set. -->
<exec program="${TestTool}">
<arg path="my/${ProjectName}/tests/path/for/tool" />
<arg value="/aproperty=value" />
</exec>
</target>
<target name="myproject" description="Build the project">
<property name="ProjectName" value="MyProject"/>
<call target="build-csproj" />
<call target="test-project" />
</target>
<target name="myprojectlib" description="Build the project's library dll">
<property name="ProjectName" value="MyProjectLib"/>
<call target="build-csproj" />
<call target="test-project" />
</target>
</project>