Friday, May 20, 2005

Building native C++ projects with NAnt

I have not tried nant for a long time because I thought(wrongly) it is just for .NET, and my daily job involves only native C++.

My current build process use MPC, devenv command line and batch script. I like MPC a lot(especially the idea of inheritance used the build process). MPC's template approach can help me to create .sln and .vcproj with very little effort.

Devenv.com is helpful as well, although it is a little bit slow. vcbuild.exe is faster, but there are some small issues I do not like (the devil is always in the details).

I uses batch script(.bat) to glue the build process together, but I really hate to program in this old awkward langage. I resisted to put more error handling because it can easily mess up the script.

So I decided to switch to nant after I found it can handle c++ project as well. Even though it takes me a while to figure it out, using nant is quiet easy. The solution task is great idea (know how to live peacefully with others is important:)): no need to write verbose build script and no need to wot worry about keeping it in sync with visual studio.

If all the environment variables are setup correctly (I will take about the tricks later), the build file can be as simple as this(and it is faster than devenv):

<?xml version="1.0" ?>
<project name="myproject" default="all" xmlns="http://nant.sf.net/schemas/nant.xsd">
 <target name="all" depends="debug, release" />

 <target name="debug">
  <solution solutionfile="myproject.sln" configuration="Debug" />
 </target>

 <target name="release">
  <solution solutionfile="myproject.sln" configuration="Release" />
 </target>
</project>

Unless you run nant from Visual Stuio 2003 Command Prompt, you may see lots of erros about missing headers and libs. This is because you need a few more environment varibles(PATH, INCLUDE and LIB). Visual studio will set them up for itself (see vcvars32.bat) and nant are not aware of them (it knows only system level environment varibles).

Nant supports setenv task so it looks like good place to go. But it will bloat the build file. Why not just use vcvars32.bat? If you are following the installation procedure of nant, you can just add a line into your nant.bat:

@echo off
@call "C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat"
"C:\tools\nant-0.85-rc3\bin\NAnt.exe" %*

You can also use "HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun" so that vcvars32.bat is launched everytime cmd.exe is created. For cygwin users you know what to do:)

There is a small issue in the current release (0.85 Release Candidate 3): rc files can include c++ header files. Resource.h is one of them. And this practice uses it as well. But in the source code(nant-0.85-rc3\src\NAnt.VisualCpp\Tasks\RcTask.cs::NeedsCompiling), the date of the header files are not checked. So if you modified the include file, the resource will be rebuilt.

Btw, nant uses its own algorithm to calculate the dependencies between files, so you may see different compilation sequence between nant and devenv, it's even true for C# projetcs.

3 Comments:

Blogger D.J. Casper said...

Too bad this doesn't work with NAnt 0.85 and MSVC Express (9.0). It gives the following error:

Visual Studio Solution format version '10.0' is not supported.

Makes me sad, otherwise it would have been a real life-saver! :-)

8:28 AM  
Blogger robsadventures said...

Hi, wondering if you might be interested in doing some contract work with us. We are looking for someone to set up build automation for a cross platform C++ application (Linux 32 and 64 bit builds, windows and mac builds). Is this something you would be interested in? Please contact me on rob@timedoctor.com thanks.

1:11 PM  
Blogger Roland Reinl said...

Have a look at http://code.google.com/p/nant-cross-compile/

12:34 PM  

Post a Comment

<< Home