Complicated Builds? You're Doing it Wrong
Over the last couple of years, I've become a bit of a fan of the Maven build system. I generally refer to it as the worst, except for everything else.
Most developers either love it or hate it (the way anything great should be). The folks that don't like it, generally find fault because it's not a very good tool for complicated builds (most are used to tools like Ant or Gradle). The folks that love it, love it because, it's not a very good tool for complicated builds.
My personal history with build tools? I started with shell scripts, then moved to Make, followed by Ant. More recently, as stated, I've switched to Maven. The path that these tools have taken me is toward a progressively simpler way to build projects.
The first signs of a dysfunctional build:
- several build systems and/or languages are required to assemble a project
- different builds are created for different environments (test/integration/production)
- the build needs to be scripted
- "training" is required to build the project
- "people" need to perform several steps to build the project
- only certain people can perform the build
I will be honest. I've not only worked in all of those types of environments; I've actually been responsible for creating them too (for this, I deeply apologize to the folks who've inherited those projects).
Nowadays, I expend great effort to ensure projects follow these guidelines for build/assembly:
- only one command is required to build (one step)
- builds are declarative (there is nothing conditional in a build)
- anyone should be able to run a build (with no training)
- easy to integrate with a development environment
Several Different Build Systems and Languages?
The problems with this are pretty obvious. The solution is generally pretty difficult.
It means the entire project needs to be refactored. Most likely, the project needs to be broken up into smaller pieces. Unfortunately, it's easier said than done. But, the effort expended to simplify the build has immediate payoff and will definitely pay for itself over and over.
There is no silver bullet type advice for this because every project is different. The worst part, you'll probably need to halt development to actually get it done. This is usually a task best reserved for week-end heroics. I wish I could offer better advice but, this task will suck. Also, the longer you wait to do it, the more it's going to suck. Just do it, you know you need to.
What's Wrong with Conditions in the Build?
First, it means you are not creating the same build every time. It means not everyone is creating the same build. It makes it difficult to integrate the build system with the development environment. It lacks predictability.
The same is true regarding creating environment specific builds.
Regarding Environment Specific Builds
When this happens, it's time to take a step back and look at the big picture. If you're writing Java, most every server supports JNDI. It's not a very complicated technology and it is a much better way to manage environment specific configuration. This could mean JDBC configuration or even just paths for other configuration files. Your build could create tar files that contain environment specific configuration (hint: maven users can use the: assembly plugin). This way, you ensure that there is only one single build used everywhere.
If you aren't using Java, practically every language/platform supports something similar. Learn it, use it.
No Simple Answers
Let's face it, sometimes you'll need to do something extra with a build (like generated SOAP stubs from a WSDL, the code will need to link to). The trick, is to find a way to prevent that type of thing from complicating the build. It's going to take some effort. There is no way around it.
But, if you take the "easy way out" (I'll just launch a shell script), by complicating the build, you are going to make everyone associated with the project pay the price, perpetually.
These kind of things will happen over and over as your project grows. Don't let it happen because it's "just one little thing". Tomorrow, it'll be two little things. Later, even more. The entire process will be out of control before you know it.
The fight for simplicity should be never ending. It needs to attack every tiny little thing. Projects rarely become complex overnight.