Archive for the ‘Build’ Category
Macros in nant
One of my favourite features of ant is the ability to create macros where you can define common behaviour and then call it from the rest of your build script.
Unfortunately that task doesn’t come with nant and it’s not available on nant-contrib either.
We were using a very roundabout way to build the various projects in our solution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<target name="compile">
<foreach item="Folder" property="folderName">
<in>
<items>
<include name="${project::get-base-directory()}\Project1" />
<include name="${project::get-base-directory()}\Project2" />
</items>
</in>
<do>
<property name="project.name" value="${path::get-file-name(folderName)}" />
<property name="project.file" value="${project.name}.csproj" />
<exec program="/path/to/msbuild3.5/">
<arg value="${folderName}\${project.file}" />
<arg value="/p:OutputPath=${build.dir}\${project.name}\" />
</exec>
</do>
</foreach>
</target>
|
Horrendous! Luckily I happened to be emailing back and forth with Bernardo about Stormwind at the time and he mentioned that there was in fact a task.
I added the Macros dll to the build file and voila:
1 2 3 4 |
<target name="compile"> <compile-project projectfile="\path\to\Project1\Project1.csproj" /> <compile-project projectfile="\path\to\Project2\Project2.csproj" /> </target> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<macrodef name="compile-project">
<attributes>
<attribute name="projectfile"/>
</attributes>
<sequential>
<property name="project.name" value="${path::get-file-name-without-extension(projectfile)}" />
<exec program="${msbuild}">
<arg value="${projectfile}" />
<arg value="/p:OutputPath=${build.dir}\${project.name}\" />
</exec>
</sequential>
</macrodef>
|
Further instructions on using the macrodef task are here.
msbuild – Use OutputPath instead of OutDir
We’ve been using msbuild to build our project files on my current project and a colleague and I noticed some strange behaviour when trying to set the directory that the output should be built to.
The problem was whenever we tried to set the output directory (using OutDir) to somewhere where there was a space in the directory name it would just fail catastrophically. We spent ages searching for the command line documentation before finding it here.
According to this though:
“OutputPath: This property is typically specified in the project file and resembles OutDir. OutputPath has been deprecated and OutDir should be used instead whenever possible. ”
We decided to try changing OutDir to OutputPath and it started working again! The code is simple, but for those wondering:
1 2 3 4 |
<exec program="\path\to\msbuild35">
<arg value="${projectfile}" />
<arg value="/p:OutputPath=${build.dir}\${project.name}\" />
</exec>
|
I can’t decide whether the documentation is just wrong or if it’s now a convention that you can’t have spaces in your build output path. Surely the former?
Getting the current working directory from DOS or Batch file
In the world of batch files I’ve been trying for ages to work out how to get the current/present working directory to make the batch script I’m working on a bit more flexible.
In Unix it’s easy, just call ‘pwd’ and you have it. I wasn’t expecting something that simple in Windows but it is! A call to ‘cd’ is all that’s needed. If you need to set it in a batch script the following line does the trick:
|
|
set WORKING_DIRECTORY=%cd% |
I was surprised that something so simple (I do now feel like an idiot) wasn’t easier to find on Google. I ended up going via Experts Exchange (how they end up with such high search results when you have to pay to see the information is beyond me) and several other verbose ways of solving the problem before finally coming across this article which explained it.
Spaces in batch scripts
Since reading The Pragmatic Programmer I’ve become a bit of an automation junkie and writing batch scripts falls right under that category.
Unfortunately, nearly every single time I write one I forget that Windows really hates it when you have spaces in variable assignments, and I forget how to print out a usage message if the right number of parameters are not passed in.
So as much for me as for everyone else, this is how you do it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@ECHO off IF [%1]==[] GOTO usage IF [%2]==[] GOTO usage set VAR1=%1 set VAR2=%2 rem important client stuff goto end :usage echo Usage: script.bat var1 var2 :end echo Script finished |
TeamCity’s strange default build location
We’ve been using TeamCity on my current project and it’s proven to be fairly impressive in general.
We’re running quite a few different builds which have dependencies on each other and it’s been pretty much one click on the web admin tool to get that set up.
One thing that had me really confused is the default location it chooses to build from. The problem is that it seems to change arbitrarily, with the folder name it builds in being calculated from a VSC hash (not sure quite how that’s worked out but there we go).
I had (naively) assumed that the default build location would always stay the same and was therefore referencing this location from our build script. Turns out it can change whenever it feels like it!
Our 15:38 build was built to c:/TeamCity/Agent/c734523aedrte but our 15:40 build was built to c:/TeamCity/Agent/d6420ghi2.
Cue much confusion as I repeatedly looked at the first folder trying desperately to work out why nothing was being checked out. Eventually, more by fluke than skill, I figured it out and our build is now being built to c:/WorkingDirectory every time.
Lesson learnt: Take control and set your default directory, don’t let TeamCity do it for you!