About Me

Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

Automating Your Builds With NAnt - Part 3

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 477
This Year: 47
This Month: 2
This Week: 4
Comments: 1344

 Friday, April 07, 2006
Friday, April 07, 2006 1:03:58 PM (Mountain Standard Time, UTC-07:00) ( .Net 2.0 | C Sharp | Tools )

Ok, last time we left off being able to clean/create a staging area for the build. Let’s now work on actually compiling the projects in the solution. If you take a quick look at the solution structure SolutionStructure you will notice that there are 16 projects. More than half of these projects are test projects, and one of them is a web project. To be more specific, I am using the standard VS2005 web project model to organize my web project. Some of you may not be aware but there is another model called the Web Application Project model, that basically looks and behaves very similar to the way web projects worked pre VS2005. More on that another day!! Today I will focus on just building the supporting assemblies for the web project. Right now, I am talking about a build for test, not for deployment. These are 2 quite different animals. When I am doing a build for test I can choose to take a very simple route and just compile all of the code from the 8 supporting projects into a single dll, as opposed to compiling them the way studio does. This also keeps the build file a lot simpler. More often than not, as developers we utilize projects as a way to logically organize the application. Whether or not each of the individual projects actually resolves to one deployable unit is a choice that you have to make as a project team. Personally, once you have an automated deployment scenario in place, it really does not matter. As deploying becomes (almost) as simple as running a NAnt target.

Let’s get back to actually building the 8 projects we are interested in. It stands to reason that some of the projects in the solution have dependencies on other projects in the solution ProjectReferences. Obviously these projects will not be able to build properly unless those references are maintained and obligated within the build file. A better question to ask is how do you actually go about compiling the 8 projects using NAnt? If you have been taking a look at the NAnt NAnt Task Reference reference you will notice that one of the tasks in there is the csc  task. This is a dedicated task with the sole responsibility of compiling C# programs. It stands to reason that this would have to enter the mix somewhere!!

I am not even going to try and attempt to cover all of the attributes/flags that can be used in conjunction with the csc task. I believe an example will speak louder than words and get you going in the right direction. Let’s switch back to the build file and start working on adding in the compile task. In case you forgot what the build file currently looks like, here it is:

<?xml version="1.0"?>
<project name="DotNetRocks" default="all">

    <property name="debug" value="true" />

   <target name=”all”/>

   <target name="clean" description="remove all build products">
        <delete dir="build"  if="${directory::exists('build')}" />
    </target>

    <target name="init">
        <mkdir dir="build" />
    </target>

</project>

I’ll add the entire compile target and then discuss and dissect for the remainder of the post:

<?xml version="1.0"?>
<project name="DotNetRocks" default="all">

    <property name="debug" value="true" />

   <target name=”all”/>

   <target name="clean" description="remove all build products">
        <delete dir="build"  if="${directory::exists('build')}" />
    </target>

    <target name="init">
        <mkdir dir="build" />
    </target>

    <target name="compile"
            depends="init"
            description="compiles the application">
        <csc target="library" output="build\${nant.project.name}.dll" debug="${debug}">
            <sources>
                <include name="src\app\**\*.cs" />
                <exclude name="src\app\DotNetRocks.Web.UI\*.*" />
                <exclude name="src\app\**\AssemblyInfo.cs" />                               
            </sources>                       
        </csc>
    </target>

</project> 

First point of interest is the use of the new “depends” attribute in the compile target. This tells NAnt to ensure that the “init” target has been run before the compile target runs. If the init target has not already been executed in this NAnt session, then NAnt will ensure that the init target is run before it carries on processing the compile target. NAnt processes dependencies from left to right so you can have a target depend on multiple targets using comma-separated lists such as : depends = “clean,init”. If you have a dependency on a target that also has a dependency on init, NAnt will make sure that the init target is only executed once, as not to waste execution cycles. The rest of the target deals with the actual csc task itself.

First off, I tell NAnt that I am going to be compiling a “library” (dll) and that it should place the resulting dll in the build directory. What’s with the ${nant.project.name} syntax? This is the way you access properties in NAnt. We did not, however, define that particular property in our build file. This is because ${nant.project.name} is one of many predefined NAnt properties that we can make use of during the build process. The value of the ${nant.project.name} property will resolve to the name you give your project in the project element of the build file:

<project name="DotNetRocks" default="all">

So when this dll is compiled it will actually be compiled to : build\DotNetRocks.dll.

Finally I have to tell the csc task, what files (sources) to include in the compile process. The sources element is actually just a NAnt fileset. I can include/exclude files from the fileset. Notice how I am excluding everything in the Web.UI project? Why, this is because I am using the WSP model and a lot of the code for web projects, when using this model, is dynamically generated. In a future post, I will show one way to compile the Web.UI project. I am also excluding any AssemblyInfo.cs file from the list of sources. If I did not do this, the compiler would choke because there would be multiple classes of type AssemblyInfo attempting to be compiled into the assembly. MultipleAssemblyInfos When I usually compile multiple projects into a single assembly, I usually create a single AssemblyInfo file for that group of projects, and include that AssemblyInfo file into the compile process.

With that target completed, I can run the compile target from the command line and see the result placed into my build directory.BuildDirectoryWithNewAssembly 

Next up is testing the assembly!!

 





TODO