Kyle Baley - The Coding Hillbilly

Sponsors

The Lounge

Wicked Cool Jobs

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
How do you build your application?

The Hillbilly asks: How do you compile your application in your NAnt script for releases?

There are many options, you see, even though the <solution> task is no longer one of them. You could use the <msbuild> task to build the solution as it is built in VS (I think; the documentation is a little sketchy on this task if you don't know the inner workings of msbuild). Or you could use the <csc> or <vbc> tasks to compile a group of code files into an assembly (similar to a .csproj or .vbproj file). Or, for the ultimate control, you could use the <exec> task to call out to msbuild.exe, csc.exe, or vbc.exe directly though I couldn't tell you personally what that offers you that the imagecorresponding tasks don't. Future-proofing maybe.

Usually, for testing purposes at least, this entails using <csc> (or <exec> with csc.exe) to compile all the application code into a single assembly that I can run tests against. It's a practice I learned from JP Boodhoo and I've been happy with the results in the absence of anything better.

But I don't care much about the unit tests. I'm more interested in your releases. Assuming you've automated them in a NAnt script, how do you build the application in preparation for them?

Historically, I've usually used the <msbuild>/msbuild.exe scenario mostly because I couldn't wrap my head around writing a bunch of <csc> tasks to compile the code into the same structure I see in Visual Studio. For example, if your solution has a Domain project, a DataAccess project, and a UI project, I would need three <csc> tasks to create the individual assemblies. Or one <msbuild> task running against the solution. My reasoning was that it was the easiest way to build the application the same way I did in Visual Studio, which I assumed was how I wanted to deploy it.

Then I talked to Donald Belcham.

Conversations with Donald Belcham are always eye-opening (and I won't expand on that comment this time; happy belated birthday, dude). And during our chat, he admitted to using <csc> to create his releases. I expressed my surprise: "But Iggy, what if your solution has a dozen projects in it? I don't want to deal with the pain of a dozen <csc> tasks in the right order". To which he replied: "Dude, you don't need to deploy the same way you build. The Visual Studio solution is a file management mechanism, not a deployment mechanism." And my mind awakened like it did during my last visit to Brian Head.

The basic idea Donald described was thus: Just because you build your application one way in Visual Studio during development, doesn't mean you need to build your releases the same way. Especially if you are using NAnt to create your releases because then you can do it however you like.

And as if my mind wasn't expanded enough, he typically shoots for one assembly per physical location. Not one assembly for the domain, one for the data layer, one for the common utilities, and so on and so forth. One. Total. If I were building a WinForms application with no other physical layers, I'd have one file: MyApp.exe. If it were a WinForms app calling a web service, there would be two assemblies. One for the client and one for the web service (plus corresponding .asmx files).image

This is the extreme position of course and there are caveats. If the application depends on third-party libraries, naturally we won't bundle those up into the assembly. And if you're using an internal client library that is common to more than one project, you'd treat that as you would any other third-party library and keep them separate. But if your application-specific domain code and data access code sits on the same server, that all gets munged into one assembly regardless of how it is organized in the .sln file. NAnt gives us that flexibility.

I'm kind of putting Donald out there for potential ridicule so I'll expose myself ever so slightly and admit that I really like this idea. Why *do* we feel we have to ship a dozen assemblies for our application? If something changes in our domain, what difference does it make if we re-deploy MyCompany.MyApp.Domain.dll or MyCompand.MyApp.exe? And in speaking with Donald, he points out that even though we have the flexibility to deploy only parts of an application, rarely do we exercise it. In a typical scenario, new versions and hot fixes are deployed as an "all or nothing" in each physical layer anyway. This matches my experience. Even if nothing changed in certain assemblies, I typically re-deploy everything during an upgrade just to be safe.

Now, we still need to be practical about it. If the resulting executable is 300Mb, then ISDN line or not, you'll want to break that into something more manageable. But for the average application, one assembly should function just as easily as five, yesno?

Looking forward to hearing the counter-arguments because I haven't quite thought this through too much except from a maintenance point of view. In particular, are there performance differences with loading several smaller assemblies vs. one "larger" (but still manageable) one? What about issues with unloading an assembly from an application pool in IIS?

Enquiring minds want to know!

Kyle the Inquisitive


Posted Mon, Feb 11 2008 10:00 AM by Kyle Baley
Filed under: , ,

[Advertisement]

Comments

Adam Vandenberg wrote re: How do you build your application?
on Mon, Feb 11 2008 12:48 PM

The formatting here will probably get hosed, but for what it's worth:

<exec program="${vs.dir}\devenv.com">

<arg value="/rebuild" />

<arg value="${configuration}" />

<arg value="the_project_file.sln" />

</exec>

Josh wrote re: How do you build your application?
on Mon, Feb 11 2008 1:39 PM

My argument for breaking code up into assemblies. Is based off of reuse scenarios. If you will always need the full sebang your argument rings true. If you ever want to ship just parts than splitting them up maybe a good idea.

Software Theosophy wrote Should your production build be different than your development build?
on Mon, Feb 11 2008 2:28 PM

Kyle Bailey invited some criticism in his article, so I'm going to deliver it. You can read the...

Fregas wrote re: How do you build your application?
on Mon, Feb 11 2008 2:29 PM

No, I don't do what you're suggesting.  Here's my response:

dotnettricks.com/.../704.aspx

Ayende Rahien wrote re: How do you build your application?
on Mon, Feb 11 2008 2:34 PM

Kyle,

There are good reasons to want to have the same structure in both scenarios. Repeatability and consistency is one of them.

I don't want to have to deal with different release version when I need to solve a problem.

That said, I am beginning to lean toward the two projects system. One for the app, one for the tests, and that is it.

And creating a build script is usually a matter of few minutes.

alberto wrote re: How do you build your application?
on Mon, Feb 11 2008 2:50 PM

I'm all for the single-assembly-per-location approach. But as Ayende says, you want to test your build under the same circumstances. That's why I use nant to build (and test) before commiting and in the CI server. I just use msbuild(VS) when I am making quick changes and want to check that the thing compiles. But I always end up with a nant build.

Jeff Tucker wrote re: How do you build your application?
on Mon, Feb 11 2008 2:51 PM

I like the idea of one assembly per physical location, although there is a specific need for a single module in my application to be upgradeable (there's a really good reason, just trust me).  I may modify my production build to just make a single assembly after reading this.

 I hate relying on Visual Studio projects and solutions to tell me how to build also.  It's nice if ctrl-shift-b will build my project so I can debug it easily.  However, projects do not necessarily show all the files that are physically in the directory, so it's easy to have leftover files that are no longer in use but not part of the project.  A build script will detect these as long as it doesn't rely on the projects or solutions to tell it what to build.  Also, a build script is your environmental documentation and it's much easier to show how your application is structured and what is referenced in a build script (since you have to do it explicitly) than in Visual Studio (because then I have to open each project and click "references" and it doesn't show me where they are without clicking properties, etc.).  

Dot Net Tricks wrote Should your production build be different than your development build?
on Mon, Feb 11 2008 3:08 PM

Kyle Bailey invited some criticism in his article, so I&#39;m going to deliver it. You can read the original

Kyle Baley wrote re: How do you build your application?
on Mon, Feb 11 2008 3:10 PM

@Josh: Yes, you're absolutely right. If you are planning to re-use anything in the very near future. But that's another topic. The summary: Building re-usable components before you know how they'll be re-used will make them that much less re-usable.

@Fregas: You can set up NAnt to compile all .cs or .vb files in a folder into an assembly (including all subfolders). If I had to update my build file every time I added a class, I sure wouldn't be recommending this practise. And yes, you're right, doing this with the hopefully-now-defunct project-less web sites is likely to cause a world of hurt. But then, doing anything with project-less web sites is plenty painful. Let's not discard potentially useful practises because of a minor lapse in reasoning in Redmond.

@Ayende and Alberto: If you were to compile all your C# files into a single assembly, does that alter the structure of the underlying IL compared to if they were in different assemblies? That's not a rhetorical question because I honestly don't know. I.E. If you have three projects, each with a different namespace and a single C# file in them, and you compile them into three separate assemblies, are there any scenarios where that will act differently than if you were to compile all three files into a single assembly?

Craig Bowes wrote re: How do you build your application?
on Mon, Feb 11 2008 4:48 PM

@Kyle,

I wondered about the possibility of compiling a whole folder, and indeed what you mentioned sounds better, but i'm not entirely convinced--yet.  For example, you still run into issues if you've excluded a file in VS.NET but its still in the folder for the nant script to pick up.  I do this at times to remove code i don't want to compile at the moment or is going to worked on later.  Now you have to have some way of also excluding it from the nant build.  Not AS BIG of an issue, but still an issue.  The fact is, there's a chance that the behavior or your app is going to very slightly, from one build process to another.   Then you get surprises.  I don't like surprises.

Craig

Kyle Baley wrote re: How do you build your application?
on Mon, Feb 11 2008 5:10 PM

@Craig

Yes, you're right. That's an issue if you do exclude files from VS. On the other hand, I like the fact that NAnt includes everything because in the past, it's helped me locate stray classes that are either in the wrong physical location or that have been long-abandoned and just not deleted.

Also, I'm not talking about wild variations in my build process. Remember, this is a CI environment. As long as you use the same build process as my CI server before you check-in, surprises should be minimal. Besides which, surprises aren't a bad thing. After all, that *is* why you have a CI process: to catch them early.

Keep in mind that I'm not totally convinced yet either. I'm basing this solely on conversations with someone who I know would not use the practice if it didn't reduce a great deal of pain for him. My final judgement is still reserved but Donald's a smart guy. Which is probably why he left me to blog about this instead of doing it himself...

» Daily Bits - February 12, 2008 Alvin Ashcraft’s Daily Geek Bits: Daily links, development, gadgets and raising rugrats. wrote &raquo; Daily Bits - February 12, 2008 Alvin Ashcraft&#8217;s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.
on Tue, Feb 12 2008 9:56 AM

Pingback from  &raquo; Daily Bits - February 12, 2008 Alvin Ashcraft&#8217;s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.

Igor Brejc wrote re: How do you build your application?
on Tue, Feb 12 2008 10:01 AM

Currently I use the same method you described - exec msbuild on solution file, but now I have encountered a situation when I want to target my build separately for .NET and Mono. I want Mono to use different versions of some 3rd party libraries (log4net, for example), but I don't see a way to do this using the VS project structure.

One way of dealing with this would be to XSLT-translate VS project files into NAnt csc targets. This way you still get the benefits of maintaining your projects in one place (VS), but you can modify certain aspects of the build procedure (changing references, for example). The whole thing would have to be executed within the script, off course.

Craig Bowes wrote re: How do you build your application?
on Tue, Feb 12 2008 1:12 PM

Kyle,

Yeah I can see how CI would definitely catch that kind of stuff early on, rather than right before you go to production or testing. We don't use Ci at my work, but we integrate fairly regularly.  Right now our stuff  is mall enough and our team is small enough that it doesn't matter as much, but we're looking into getting CruiseControl going.

Craig

Bil Simser wrote re: How do you build your application?
on Tue, Feb 12 2008 2:58 PM

Kyle, we went through this last gig didn't we? We were compiling all the app code into one assembly, and another into a test one. I thought that was good for testing and when it came to deployment you didn't need the test assembly. Maybe one is too big and I would favor breaking it up for a pure Smart Client solution where you can trickle down individual assemblies for updating (rather than the big bang we would do). I personally thought creating csc tasks to mimic the VS structure was overkill and made things complicated.

Kyle Baley wrote re: How do you build your application?
on Tue, Feb 12 2008 3:19 PM

Yes, but that was my crappy implementation. I shouldn't have tried mimicking the VS structure via <csc> tasks. That was a bit of madness that I can't rightly justify now that I look back. To do it the way Donald suggests, I would have one <csc> task to compile all the WinForm code (i.e. all the Infrastructure projects plus the domain plus the data access) into a single executable (not including Windsor, CAB, etc, etc). Plus there would be one assembly for each of the web services. So five <csc> tasks total, if I remember correctly, which is one per physical location.

The good part about this is that as you mention, we were already compiling the app code for testing into single assemblies using <csc>. We just needed to expand that idea and compile them based on physical architecture. That way, we could have used the same task to compile the code for testing *and* to compile the code for releases.

But you bring up another interesting point. This doesn't take into consideration ClickOnce deployments which, frankly, I still don't understand completely. They seem to be more msbuild-oriented so if that's the deployment mechanism, this might not work as smoothly.

I'm hoping Donald will expand on this himself and maybe fill in the gaps because I think something may have got lost in my translation.

John wrote re: How do you build your application?
on Fri, Feb 15 2008 9:39 AM

You could always build the solution file using the msbuild task and then call ILMerge to merge certain assemblies into one.

John

John wrote re: How do you build your application?
on Tue, Feb 19 2008 2:41 AM

Can anyone please send me the entire (sample) build script for a web application project at my email id johvicky@gmail.com.

Ayende @ Rahien wrote The two project solution
on Thu, Feb 21 2008 5:09 PM

The two project solution

Coding in an Igloo wrote How do you build your application details
on Thu, Feb 21 2008 9:47 PM

How do you build your application details

DotNetKicks.com wrote How Do You Build Your Application
on Fri, Feb 22 2008 3:42 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us