I’ve seen a lot of code from different companies I’ve worked at. I have also seen a few open source projects on the web.
And a feature that I have seen in some of them, where no matter what build configuration you specify, the build gets written to the same place.
If you build a 32 bit build of something it goes to c:/build/exe.
If you build a 64 bit build of something it goes to c:/build/exe.
If you build a Debug build of something it goes to c:/build/exe.
If you build a Release build of something it goes to c:/build/exe.
Are you starting to notice a pattern here? No matter which configuration you choose, all build results go to the exact same folder. This is an especially grievous type of sin committed by those of the lowest caste of programmers: The disorderly ones.
This can be easily solved using any build system by just a little bit of common sense and organization:
If you build a 32 bit build of something it goes to c:/build/x32/*.
If you build a 64 bit build of something it goes to c:/build/x64/*.
If you build a Debug, 32 bit build of something it goes to c:/build/x32/debug/*.
If you build a Release 32 bit build of something it goes to c:/build/x32/release.
If you build a Debug, 64 bit build of something it goes to c:/build/x64/debug/*.
If you build a Release 64 bit build of something it goes to c:/build/x64/release.
Notice a pattern here?
Different build configuration artifacts should be able to sit side by side without interfering with each other.
- You don’t want half of your release build binaries to accidently have debug symbols in them (inflating their size).
- You don’t want to have a mixed build where memory is allocated in a debug heap, and freed in an incorrect release heap. Or vice versa. This corrupts memory at best and crashes at worst.
- You don’t want crashes at runtime robbing developers of their time chasing down mysterious heisenbugs that they could have simply solved by having a consistent build.
- You absolutely have to keep your intermediate files separated from each other too. This is the start of where subtle bugs can creep in. Thus intermediate files also need to be guarded too.
- I could go about how stupid that is.
So for example, here is a sample of what could be done for a project to keep source code, and artifacts highly organized:
Using an organization like this above makes a few things easier for the developer:
- They won’t have to clean the build as often. They can work all day long on a particular configuration and not interfere with other configurations.
- Don’t have to clean the build as often.
- Cleaning the build is simple. Just select a directory and hit the delete key. No need for a complicated build system invocation to clean the build.
Some other thoughts on the subject:
- Specify one well known, easily accessible and recognizable location for build artifacts. Put everything in there, and don’t make any exceptions. Don’t hide your build artifacts in a dozen different places. Don’t expect your developers to manually assemble the final product after the build is complete.
- Document that build location in a readme file found at the root of the project. If you haven’t moved on to readme files yet, then the 1970’s is calling, and wants it’s code back.
- Tell others to read the readme file.
- Even better make the build artifacts go to some location outside of the source control folder. This is beneficial for a few reasons. First it does not commingle the source code from the build artifacts. Second your .gitignore file doesn’t have to be so massive with files to ignore that were created as a byproduct of the build. I’ve worked on huge projects, and because we followed this principle, I’ve been able to keep the .gitignore files down to a few lines of code. A win win for everyone.