Recently at work I was tasked with updating our build system to be more stable and maintainable in the future. We had previously built a cobbled together Makefile based project that worked for a few specific types of builds but it was very fragile and interdependant. For example in order to build the version of our product that worked with the eclipse plugin we would have to run:
In order to build for the visualstudio extension:
The problem came when we wanted to support windows versions of the eclipse platform. This required that we be able to run:
But there was a snag, since some of the functionality for the visual studio build was flagged as being “windows” and some of it as being “vs”, this did not mix well with the “eclipse” functionality. At the time we hacked together a new target:
And we felt dirty ever since.
Come around to the next time we needed a new target (this time would be a CMDLINE_ON_WINDOWS=true abomination) and I said no. I am going to fix this situation. I went for orthogonal as much as I could, so that it would be possible to build all different configurations, such as a x64-Linux-VS build. I then wrote some error checking and the makefile was happy. In addition we have some shell scripts which are affected by the behaviour of the makefile, and so I thought it would be pertinent to try to make them both speak the same language.
In order achieve this I needed to figure out the semantics of Makefile variables/arguments.
- If a variable is defined in the environment, you need to use make -e to get it into a makefile variable
- If a variable is defined on the commandline, then it will overwrite the definition in the makefile.
- If a variable is not defined in either of the above, and it is in the file, use that definition.
So the desired order of evaluation goes:
- in file
- environment
- commandline
I start off by processing all the default values for the given variables:
the defaults file is a series of lines which look like VAR=val. These variable value pairs are extracted below
I need to be able to see if the variable has been set before, so here I use an eval to see what is in the current variable, and if it has, use that value and export the pair
Finally I go through the arguments array and overwrite any environment variables that are specified. The script that uses this one will have to refer to ALL_ARGS after they have been processed here.
This simplish hack has allowed me to standardise on a set of variables which control the logic of building, while maintaining orthogonality.