NAnt和双平台构建 - 在Windows和Mono / Linux上构建的最佳方式

时间:2021-03-30 05:54:23

I'm new to NAnt but have some experience with Ant and CruiseControl.

我是NAnt的新手,但对Ant和CruiseControl有一些经验。

What I want to do is have my SVN project include all tools needed (like NUnit and Mocks etc) so I can check out onto a fresh machine and build. This strategy is outlined by J.P Boodhoo here.

我想要做的是让我的SVN项目包括所需的所有工具(如NUnit和Mocks等),这样我就可以查看新机器并进行构建。 J.P Boodhoo在此概述了这一策略。

So far so good if I only want to run on Windows, but I want to be able to check out onto Linux and build/test/run against Mono too. I want no dependencies external to the SVN project. I don't mind having two sets of tools in the project but want only one NAnt build file

到目前为止,如果我只想在Windows上运行那么好,但我希望能够检查到Linux并对Mono进行构建/测试/运行。我不希望SVN项目外部有依赖项。我不介意在项目中有两套工具,但只想要一个NAnt构建文件

This must be possible - but how? what are the tricks / 'traps for young players'

这一定是可能的 - 但是怎么样?什么是技巧/'年轻球员的陷阱'

4 个解决方案

#1


8  

This shouldn't be a particularly difficult excercise. We do some fairly similar stuff on one of my projects since half of it runs on Java using Ant to run relevant targets, and the other half is .Net (C#) for the UI. The projects get run on windows machines for development, but the servers (Java) run linux, but in the UAT environment (linux) we need to run the nunits (integration tests). The real trick (not really a difficult trick) behind this is having a NAnt build file that can run in both environments which seems to be the same thing you're trying to do here.

这不应该是一个特别困难的练习。我们在其中一个项目上做了一些非常相似的事情,因为有一半是在Java上使用Ant来运行相关目标,而另一半是用于UI的.Net(C#)。这些项目在Windows机器上运行以进行开发,但服务器(Java)运行linux,但在UAT环境(linux)中我们需要运行nunits(集成测试)。这背后的真正技巧(并不是一个非常困难的技巧)是拥有一个可以在两个环境中运行的NAnt构建文件,这似乎与您在这里尝试做的事情相同。

Of course you realise you'll need to install NAnt on Mono first:

当然你意识到你需要先在Mono上安装NAnt:

$ export MONO_NO_UNLOAD=1
$ make clean
$ make
$ mono bin/NAnt.exe clean build

And then your build file needs to be written in such a way that it seperates concerns. Some parts of the build file written for windows will not work in linux for example. So you really just need to divide it up ito specific targets in the build file. After that, there are a number of ways you can run a specific targets from the command line. An example might look like this:

然后你的构建文件需要以一种分离问题的方式编写。例如,为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 &quot;ClientCoverage.xml&quot;" />
      <arg value="&quot;C:\Program Files\NUnit-Net-2.0 2.2.8\bin
                       \nunit-console.exe&quot; 
                       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>

For brevity, I've left both sides out. The neat thing is you can use NUnit as well as NAnt on both environments and that makes things really easy from a dependency point of view. And for each executable you can swap out for others that work in that environment, for example (xBuild for MSBuild, and svn for tortoise etc)

为简洁起见,我将双方都排除在外。巧妙的是你可以在两种环境中使用NUnit和NAnt,从依赖的角度来看,这很容易。对于每个可执行文件,您可以换掉在该环境中工作的其他可执行文件,例如(xBuild for MSBuild,svn for the tool等)

For more help on Nunit etc on Mono, check out this fantastic post.

有关Mono上Nunit等的更多帮助,请查看这篇精彩的帖子。

Hope that helps,

希望有所帮助,

Cheers,

Rob G

#2


2  

@Rob G - Hey! That's my post! ;)

@Rob G - 嘿!那是我的帖子! ;)

For some other good examples, be sure to browse the NUnit source code. I work closely with Charlie whenever I can to make sure it is building and testing on Mono. He tries to run whenever he can as well.

对于其他一些好例子,请务必浏览NUnit源代码。每当我能确保它在Mono上构建和测试时,我就与Charlie密切合作。他试图尽可能地跑。

#3


1  

It is worth noting that a lot of tools like Nant run on mono 'out of the box', i.e.

值得注意的是,像Nant这样的很多工具都是单声道的'开箱即用',即

mono nant.exe

works

#4


0  

I use the following template. It allows simple building on any platform (build on Win or ./build.sh on linux) and minimises duplication in the build scripts.

我使用以下模板。它允许在任何平台上构建简单的构建(在Linux上构建Win或./build.sh)并最小化构建脚本中的重复。


The NAnt executable is stored with the project in tools\nant.

NAnt可执行文件与tools \ nant中的项目一起存储。

The build config file determines which build tool to use, either MSBuild or xbuild (in this case, for Windows I require the VS2015 MSBuild version, change the path as required).

构建配置文件确定要使用的构建工具,MSBuild或xbuild(在这种情况下,对于Windows,我需要VS2015 MSBuild版本,根据需要更改路径)。

The build-csproj build target can be reused for when you have multiple projects within a solution.

当您在解决方案中有多个项目时,可以重用build-csproj构建目标。

The test-project target would need to be expanded upon for your needs.

测试项目目标需要根据您的需求进行扩展。

build.bat

@tools\nant\nant.exe %*

build.sh

#!/bin/sh

/usr/bin/cli tools/nant/NAnt.exe "$@"

default.build

<?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>

#1


8  

This shouldn't be a particularly difficult excercise. We do some fairly similar stuff on one of my projects since half of it runs on Java using Ant to run relevant targets, and the other half is .Net (C#) for the UI. The projects get run on windows machines for development, but the servers (Java) run linux, but in the UAT environment (linux) we need to run the nunits (integration tests). The real trick (not really a difficult trick) behind this is having a NAnt build file that can run in both environments which seems to be the same thing you're trying to do here.

这不应该是一个特别困难的练习。我们在其中一个项目上做了一些非常相似的事情,因为有一半是在Java上使用Ant来运行相关目标,而另一半是用于UI的.Net(C#)。这些项目在Windows机器上运行以进行开发,但服务器(Java)运行linux,但在UAT环境(linux)中我们需要运行nunits(集成测试)。这背后的真正技巧(并不是一个非常困难的技巧)是拥有一个可以在两个环境中运行的NAnt构建文件,这似乎与您在这里尝试做的事情相同。

Of course you realise you'll need to install NAnt on Mono first:

当然你意识到你需要先在Mono上安装NAnt:

$ export MONO_NO_UNLOAD=1
$ make clean
$ make
$ mono bin/NAnt.exe clean build

And then your build file needs to be written in such a way that it seperates concerns. Some parts of the build file written for windows will not work in linux for example. So you really just need to divide it up ito specific targets in the build file. After that, there are a number of ways you can run a specific targets from the command line. An example might look like this:

然后你的构建文件需要以一种分离问题的方式编写。例如,为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 &quot;ClientCoverage.xml&quot;" />
      <arg value="&quot;C:\Program Files\NUnit-Net-2.0 2.2.8\bin
                       \nunit-console.exe&quot; 
                       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>

For brevity, I've left both sides out. The neat thing is you can use NUnit as well as NAnt on both environments and that makes things really easy from a dependency point of view. And for each executable you can swap out for others that work in that environment, for example (xBuild for MSBuild, and svn for tortoise etc)

为简洁起见,我将双方都排除在外。巧妙的是你可以在两种环境中使用NUnit和NAnt,从依赖的角度来看,这很容易。对于每个可执行文件,您可以换掉在该环境中工作的其他可执行文件,例如(xBuild for MSBuild,svn for the tool等)

For more help on Nunit etc on Mono, check out this fantastic post.

有关Mono上Nunit等的更多帮助,请查看这篇精彩的帖子。

Hope that helps,

希望有所帮助,

Cheers,

Rob G

#2


2  

@Rob G - Hey! That's my post! ;)

@Rob G - 嘿!那是我的帖子! ;)

For some other good examples, be sure to browse the NUnit source code. I work closely with Charlie whenever I can to make sure it is building and testing on Mono. He tries to run whenever he can as well.

对于其他一些好例子,请务必浏览NUnit源代码。每当我能确保它在Mono上构建和测试时,我就与Charlie密切合作。他试图尽可能地跑。

#3


1  

It is worth noting that a lot of tools like Nant run on mono 'out of the box', i.e.

值得注意的是,像Nant这样的很多工具都是单声道的'开箱即用',即

mono nant.exe

works

#4


0  

I use the following template. It allows simple building on any platform (build on Win or ./build.sh on linux) and minimises duplication in the build scripts.

我使用以下模板。它允许在任何平台上构建简单的构建(在Linux上构建Win或./build.sh)并最小化构建脚本中的重复。


The NAnt executable is stored with the project in tools\nant.

NAnt可执行文件与tools \ nant中的项目一起存储。

The build config file determines which build tool to use, either MSBuild or xbuild (in this case, for Windows I require the VS2015 MSBuild version, change the path as required).

构建配置文件确定要使用的构建工具,MSBuild或xbuild(在这种情况下,对于Windows,我需要VS2015 MSBuild版本,根据需要更改路径)。

The build-csproj build target can be reused for when you have multiple projects within a solution.

当您在解决方案中有多个项目时,可以重用build-csproj构建目标。

The test-project target would need to be expanded upon for your needs.

测试项目目标需要根据您的需求进行扩展。

build.bat

@tools\nant\nant.exe %*

build.sh

#!/bin/sh

/usr/bin/cli tools/nant/NAnt.exe "$@"

default.build

<?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>