views:

141

answers:

3

I have finally started to take the time out to grok the continuous integration process. I have started putting together a build server at home and trying to grok how to deal with different situations in building.

If I have component "A", which is used by application "B" - what is the "best practice" for telling the build server to compile "A" and then compile "B" using the newly compiled "A"

Obviously, I am looking to see how I integrate working components, I see lots of database examples but nothing on working with DLL's etc.

Thanks a lot!

A: 

Ant and nAnt are a couple of build tools for Java and .Net that are examples of scripts that may help. Msbuild or Cruise Control may also be useful tools if you want some more ideas.

I'd probably use some script that says in building B that A has to be built first, which is a dependency that most modern build tools support.

JB King
Do you have/can link to any examples where dependencies have been set up in a *build server* environment? Obviously VS (I'm a .NET dev) can have references, but they go out window on build server.
Rob Cooper
Within nAnt, there can be a .build file and in that you could set up a target that captures the dependencies. For example, having a target that makes calls to other targets so that the following sequence is done:1) Generate configs from templates.2) Compile code.3) Run unit tests.4) Run integration tests.5) Run WatiN tests.
JB King
+1  A: 

Pretty much all of the .net build servers work off of the solution in order to get the project references / dependencies. The main thing to take into consideration is that the build path must mirror your dev path.

Now, to be clear, if you are using GAC'd assemblies, then those assemblies must also be GAC'd on your build server. Otherwise you will run into problems.

Taking your example, your solution file should have both projects A and B in it. Further, there should be a project dependency on B for A. You accomplish this by right clicking on the References folder in project B, select the Projects tab, and select Project A.

That info get's stored with Project B. The solution maintains the link between B's reference and project A. I hope that makes sense.

Chris Lively
I will give this a go, thanks - very clear and concise :)
Rob Cooper
+1  A: 

There are two ways to approach this problem:

1 - Are your dependant components stand alone and reused everywhere
or
2 - Is this part of a large system that's co-dependant but well modularised into different projects.

I'm not 100% sure what the best practice would be in the first scenario but I can explain what I do in the second.

Say you have the following structure

/trunk
/trunk/Rob.Core
/trunk/Rob.MyCoolApplication.Server
/trunk/Ron.MyCoolApplication.Client

Each of those are "top level" applications, each with their own solution and targets, they compile independently but they're part of the same system.

In order to get "smooth" build integration with minimal fuss, I'd always recommend trying to reproduce the same environment on both dev and build servers. As such, when you check out to edit these applications, you should check out /trunk into /MyTrunkFolder.

Now, what I've tended to do, is as a post build action on any reusable .dll's or components, set up a post build action that xcopys it's build output (in release mode) to:

/trunk/CompiledOutputs/AppOrLibName/

It's important that this folder is never checked in, it should be generated by building the pre-requisite solutions.

Now, when adding references in Rob.MyCoolApplication.Server to Rob.Core, you actually add a reference to /trunk/CompiledOutputs/Rob.Core/some.dll.

This way your development environment looks exactly like your build server. Once you have your dependencies wired up correctly, you then need to add triggers in your CI system. In CCNET, for the above example, I'd put a trigger on the successful build of Rob.Core to trigger the build of Rob.MyCoolApplication.Server.

When you do a fresh checkout of your system, it's advisable to have a batch script that triggers msbuild in dependency order to build your environment.

The above is only valid when you always want your applications to be build against the latest versions of your components. If that wasn't the case, you'd probably want to have a checked in folder of the referenced assemblies as part of the application that used them, and then manually update to new versions of your compiled components as and when it's valid to do so.

There's very little written on this subject so most of this was just felt out and extrapolated over 3-4 projects, but it's certainly been repeatable and reliable on my last two LARGE projects. As ever, obviously, your mileage may vary.

DavidWhitney
Excellent answer, thanks David. Taking notes, will report back soon!
Rob Cooper