Managing build dependencies ... check them all in. All of them if you can.
There are many posts and deep thoughts on source code branching but little advice on how deep you should go into putting your build dependencies under source control.
Since I've not seen any general guidance on managing build dependencies I'll offer the following based my experinece:
Check in build dependencies rather than installing them on the build and development machines.
Any dependency that your build process has that is not under source control will undermine the benefit you get from branching.
The range of build dependencies that I'm calling out for you to check in usually fall into the 3 categories.
- Source – developer owned code that is required to create your product components. May include compiled and non-compiled code.
examples: c, c#, wix, sql scripts
- Tools/Applications – executables, build tools and scripts required to transform the source code in to the product that can be shipped to test (ideally the same as what is shipped to your customer)
examples: compilers, build scripts, packaging (MSI, CAP, ZIP) tools
- Libraries – SDK’s and 3rd party libraries
examples: headers and libs from windows SDK, .net framework
Several changes fall out from this since I'm recommending that all you need is an OS and your source code branch to build you product.
For managed code developers this means checking in the .Net framework and using the HINTPATH attribute in your proj files to refer the the checked in assembly instead of assuming you have it available in the GAC.
This also means that you may also want to steer away from tools that do not have an xcopy style deployment. Look for tools that offer a "stand alone" build or silent modes.
Once your build dependencies are under source control they can be branched with your product code. This will create a standard build environment, identify all of your projects dependencies and simplify servicing.
Standardized build environment
Having all dependencies under source control will assure that each individual developer build and the official builds are building using the same build environment. This will reduce the number of defects introduced from mismatched environments (i.e. “it builds on my machine…”).
Known set of dependencies
A secondary benefit of being able to build from a clean OS install is a complete understanding of your product dependencies. If there is a security defect, licensing or IP question related to a component your product depends on you can sync to the source tree and reliably enumerate through every components available at build time and take appropriate action.
Installed applications on a build machine can’t be branched. This means that even if you branch your source code for release, defects could be introduced as newer versions of applications are installed on the build machine.
Fear the magic build machine!
When dependencies are not understood some teams will marry a single machine for each release branch they maintain. This is not a good strategy as this is the first step in creating a build system that is only reproducible on a particular machine (i.e. the "magic" machine).
The servicing window for products is increasing as many businesses are seeing 7-10 year servicing windows. Relying on a particular machine (physical or virtual) to reproduce your build over that timeframe introduces unneeded risk.
What if I can't check in everything?
For many products is may not be feasible to change applications that are installed on the build machine to alternate apps that can be checked in. In this case I recommend that you document and automate the build machine setup.
Test your build machine setup by following the steps in your setup documentation on a clean OS install. Then build your product from a known state (i.e. your last release) and run the associated test pass against it. Most errors associated with an improper build machine setup generate a build break instead of more subtle run time defects.
Once you have confirmed the setup document is accurate treat this just like source code and check it in and branch it with your product releases. Also, make sure all build and dev machines owners use this document for machine setup and update as needed.
An optional step is to fully automate the build machine setup by using the unattended install of applications that must be installed on the build machine.
Consider checking in the binaries of the applications you need into source control as well. This may not be feasible considering the size of the application. The main cost and inconvenience here would be having each developer in your org having to sync these large install files so consider removing these from the standard client work space.
In addition to your sources, all tools, libraries and applications that your product depends on to build should be checked into source control. Relying on machine state and installed applications undermines the benefit of source code branching. Once all of your build dependencies are under source control you will benefit by having standard build environment, known project dependencies and simplified servicing. Dependencies that can not be checked in should be documented and their install automated.