Every now and then we have to change something in our build procedure, and more often than not those changes are a real pain.
Build scripts are the step children of many software projects. Someone wrote them, nobody cares much about them, they just work and build the project. Until they don’t.
Be it because you have a new artifact that needs to be included in the build somehow, or because your build decides to stop working for curious reasons, the day will come where you have to open that build script in an editor and stare in awe at the gibberish that lies before you.
Know your build language
Whether it is a simple shell script, a make file, or a bunch of xml files for MSBuild, Maven or other build systems that control how your precious code is transformed into something executable, you have to know the syntax and semantics.
I don’t say you have to know it by heart and as well as your main programming language, but you should be able to read what it does and to google for the right keywords if you need to add something.
Not knowing the build language means not being in control of the build. In extreme situations that means you are not able to build – and guess how much your customers value a shipment of a bunch of source files instead of the real thing.
Make sure your team knows the language as well. There should not be just one or two persons knowing the build, everyone should, because the build is crucial for everyone. Like any code, the build files should be owned by the team, not by individuals.
That means, if you are to set up a new build system, make it a team decision which language to use. Don’t just whip up a Rake build because you heard it’s in these days. You don’t want to be the one stuck with maintaining the build when you could be working at the cool stuff.
If you already have a build system in place, consider reusing it for new builds as well.
Build scripts are code
You may hope that you don’t have to touch you build files as often as your usual source files. Nevertheless you will have to maintain or debug them some day, and you’d surely like that maintenance to go as smoothly and quickly as possible. Therefore you should treat them like any other code.
Use clean code principles
As far as possible, you should use meaningful names and a good structure in you build script. Nobody wants to sift through an unformatted 300 line DOS shell script with variable names AA to BM.
Use variables if the language allows it. Having a single block of configuration variables in the script allows you to easily change that configuration without having to skim the whole file in search of occurrences of some paths.
Break up the script and modularize it if that makes sense. Parts of your build scripts can often be reused in other locations, e.g. in different modules of the same project. The DRY principle applies to build scripts as well as to other code.
Build system languages often are not as expressive as general purpose languages and therefore lack some of the facilities that allow us to clearly cast our intent in code. In addition, readers usually are not too fluent in the language, so the intent of a given piece of build code may not be clear to everyone. Therefore make use of comments where needed to clarify, but take special care to not let the comments lie to the reader.
Check your scripts into source control
There is no reason why you would not want to check in your build scripts. There are tons of reasons why you would. People might not be as fluent in the build script language as they are in other languages, so it’s good to be able to roll back if changes don’t turn out the way you thought.
Checking in the build script alongside the application code also allows new programmers to get productive faster, and it allows everyone in the team to adopt easily to changed package structures, added dependencies and the like. It basically allows everyone to immediately start a build and the accompanying tests right after checking out the project.
If you have a build server like Jenkins that allows you to define shell commands, don’t be tempted to write a lengthy script right on that server. Instead, make it one or two lines that call a script that does the work and has been checked into version control.
Have one build only
It can be tempting to have two different build scripts: one for local builds in the development environment and another for the nightly build/CI server. Typically in such a situation people use a plain shell script or makefile on the server, while they rely on the built in facilities of their IDE for local builds.
This leads to double maintenance, and bugs in the build may only be reproducible on one of the systems. Therefore it is better to have the same script controlling both local and server side builds.
To achieve that, one ideally either has to get the IDE to execute the script used on the build server, or to use a build system on the server that can understand the IDE’s project files. Calling the build script from command line instead of from the IDE for local builds is an inferior option, since it is less comfortable and even may result in a executable that the IDE can not debug or is not aware of.
If those options are not available, the next best thing can be to either generate one build script from the other or have a single source and generate both of the build scripts from it.