I realise that as time goes by, people are using my beloved C++ less and less. .NET (C# and VB.NET) and Java seem to be taking over the mainstream coding world. Languages such as Ruby and Python seem to be taking over the scripting world. For the most part, C and C++ seem to exist only in the gaming/entertainment, real-time and driver worlds.
In many colleges and univerties C++ is no longer taught as a core subject (along with Assembly language) which I find quite galling. It’s a great language to learn, even if you never use it again. But the purpose of this post is not to preach the virtues and failures of the C++ language, but instead to talk about something that might aid those people who are using C++.
Anyone who’s worked on a large C++ (or C) application has felt the pain of long build times. The first “big” C++ system that I worked on took 10 minutes to build. This was much bigger than anything I had experienced up until that point. Later in my career when I joined the games industry I really felt the pain of rebuilding a massive code base. The game took just under an hour to build from start to finish without any distributed compiling mechanism in place. When I finally got a copy of Incredibuild the build time dropped noticably, but not to a point where recompilation was an option every time I wanted it.
The solution that we implement: Unity builds (which I’ll refer to as UB from now on because I’m lazy).
Now, a lot of C and C++ that have used these before might consider the idea of a UB to be a bit of a hack. I’m not sure if I agree or disagree. There is an air of “hackyness” about it, but it solves the problem of huge compile times on most platforms with most compilers.
Before I go into the definition, and give instructions on how to set up a UB, let me just state for the record that this isn’t designed to replace normal builds for releasing code. The idea behind these is to dramatically reduce the build times for developers who are spending 8 hours a day modifying the code. Fixing bugs and adding enhancements generally means that a developer is constantly recompiling. Every time you compile, you have to wait (or perhaps entertain yourself in some way), and in waiting you are wasting precious time. Wasting time means a reduction in productivity. This can only be a bad thing. It’s bad enough with short build times, but with long build times it becomes a huge problem. So please bear in mind that the normal release and product builds, builds that happen on automated build servers, etc, do not need to have a UB in place, they can continue to use normal builds.
The principle behind a UB is quite simple. It’s all about reducing…
- … the number of times a file is opened.
- … the number of files that are opened.
In esssence, we’re going to abuse the power of the preprocessor to do the above.
Every source file (.c, .cxx, .cc, .cpp, etc) that is compiled results in the creation of an object file. When all of the source files are compiled into object files, the linker then collects up all these object files and links them together into an executable application. For those of you who don’t know: reading/writing to/from disk is the slowest thing you can do on a computer. Actually, it isn’t so much the reading and writing, it’s more the seeking. But the point remains the same. Disks are the only core parts of your system that have moving parts, so they’re going to be slow! So if you want to speed things up, a good place to start is reducing I/O.
I don’t want to turn this into a lesson on how C and C++ programs are compiled, so I’m going to cut to the chase. We know that the preprocessor parses each file before it’s compiled which means that each file is going to be opened. When those parsed source files are then compiled, they’re essentially opened again. Each of those files requires another seek. When the object file is generated, that’s another seek. When the file is linked, that’s another seek. There’s lots of disk activity going on here!
If you haven’t caught on yet, let me give you another hint. Each source file results in a couple of new files and a stack of seeks. We also have a neat preprocessor statement at our disposal (*cough* include *cough*).
That’s right guys, we don’t actually compile every file individually. We instead create a master file (or set of master files, depending on how big your source base is), which includes all of the other source files. This file (or set of files) is compiled instead.
To make it clear I’m going to show you the principle in action on a fake project in Visual Studio 2008. However, the principle can be applied regardless of the compiler and platform. Check out the screenshot on the left. This shows a standard C++ with a few files in it. Ordinarily each of those files will be compiled individually, and hence slowly.
The first step in creating a UB is to make a new project configuration which you can play with. Doing so will allow you to set up an area you can modify without breaking the “normal” project which will continue to be built as usual. So let’s do that now. Create a new project configuration based on the debug build. See the following screenies:
![]()
![]()
![]()
When you’ve created the new configuration, make sure you have it set as the active configuration as shown on the right.
Then, you need to add a new file which will be the master UB file. I usually create a sub-folder in the project and add the file there. Both folder and file I tend to call UnityBuild.
When the file is created, the first thing we need to do is make sure that we edit the UnityBuild.cpp so that it includes all of the other files in the project. Check out the image for the example.
If we attempted to compile at this point, we have all kinds of issues. Everything right now is being included twice. So we need to fix that so that we don’t have issues in every configuration. Let’s start by fixing up the Unity build project. Select all of the source files except UnityBuild.cpp, and exclude them from the project (right-click on them to see the properties). Check out the pics below to see how it’s done.
![]()
![]()
![]()
So that this point you’ve excluded the files from the UnityDebug configuration, and hence the unity configuration should build.
Note: if you’re implementing this in a large existing source base you may find that the UB doesn’t actually compile. You need to bear in mind that the preprocessor is making one large file out of all of your source files. Which means global variables, static variables, global functions, etc that appear more than once in the source code will now tread all over each other. Technically you shouldn’t have this problem if you’re writing “proper” code
But the harsh reality is that lots of devs copy and paste code, duplicate function names, and all kinds of other horrible things. To get it working, you’re going to have to do a bit of housekeeping! But since this is going to affect the source in a positive way, it can only be a good thing!
OK, next up let’s get the other builds working again. You need to exclude the UnityBuild.cpp file from the build in both the Debug and Release builds (not the UnityDebug configuration). I won’t show you how to do that, as it should be obvious. When you’re done, you should see similar to the image on the left when you use the Debug or Release configurations from this point on.
You’re done! The old builds should work just fine because your UB file isn’t included in the configuration. Once you’ve sorted out the code duplication issues with the UB configuration, you should have a perfectly working configuration.
You may find that the whole process is much easier if you’re building from the command line, especially using make on *nix machines, as you don’t have to worry about excluding things from configurations. Instead, you just simply need to pass in a single file to the compiler - the UB file!
So after all that, what kind of improvements should expect to find? Well let me give you a few stats. When the UB was implemented at the game company I worked for, the build time dropped from 55 minutes to just over 6 minutes. When I implemented UB in a previous job the build time dropped from 10 minutes to less than 3 minutes. When I put them in place at home the build times dropped on average by 60%.
I’d be very surprised if you didn’t notice a huge improvement in your build times if you use this mechanism.
Before I finish up, I need to highlight a few issues around housekeeping. As already stated, these builds are not used to replace the normal compilations. They should sit alongside to make it faster for the developer to do his or her work. This means that you need to make sure that both types of builds are working all the time. Keep your automatic builds using the normal build type, and you’ll soon find out if you’ve not been maintaining your configurations properly.
Make sure that every time you add a new source file you exclude it from the UB configuration, and that you add it to the content of the UnityBuild.cpp file otherwise it won’t be compiled and included in the build properly.
On the whole, UBs have really improved the speed in which I’ve been able to do things. My wait time for compilations is generally a third of what it was. That, in my view, is worth the “hack”
Thanks for reading!
PS. Please let me know of any typos, grammar errors, etc. It was a hefty post to put together and I might have missed a couple of obvious stuff-ups!
EDIT: I have fixed up a few grammar and spelling errors. Thank you Yoann and Bryce
This post is a bit old, and some of the images are missing. While it’s still got a valid description of Unity Builds it’s not really complete without the piccies. So I’ve created a full screencast and posted that over here to clear up any confusion. Cheers!










December 10, 2007
You’d think in the modern day and age we’d be able to cache the files in memory to avoid going to the actual hard disc everytime…
My current project puts the Unity.cpp files into a separate vcproj file, so that you don’t have to worry about the whole “exclude from build” stage that can easily trip you up, you can control that at the solution level. It also autogenerates the unity files so you don’t have to remember that stage either.
December 10, 2007
Yeah I was thinking the same mate. The issue is as things get really big then you’ll end up running out of memory. But they should be smart enough to get round that problem without any interaction from the user.
Having a different project for the unity builds is a neat idea! Thanks for that
December 25, 2007
Rather than doing the whole include/exclude from build thing - it gets rather tedious if you keep adding new files in and makes the project file rather large which makes merging it a bit of a pain - we added a separate project to our solution specifically for the unity build.
This way we can build that project for fast build times or the normal project for slow build times and don’t have to keep remembering to exclude new files.
March 16, 2008
If you want my opinion (and if you don’t, then I question the point of having a comments section), you missed one thing. If you’re using a unity build system, because you’re handing the compiler huge chunks of code, you’re giving the optimizer a better chance to make your code faster, as it has a larger scope in which to operate. Now, seeing as the unity build is not only faster to build, but also generates as good or better code, at this point, you have to start wondering what the point of the non-unity build is any more (apart from just being a maintenance burden). Most of my personal projects now only use unity builds, and I have no particular desire to make them non-unity. As a parting shot, I thought you might also be interested in http://www.sqlite.org/amalgamation.html, which appears to be an independent implementation of essentially the same idea.
March 16, 2008
Of course I want opinions
Otherwise I wouldn’t be blogging at all! This isn’t about preaching, it’s about learning, and I can’t learn unless people comment.
Thanks for the feedback! I hadn’t really considered the optimisation side, for me it was more to do with reducing time and increasing productivity. I also like the fact that your code has to be well written for unity builds to work (ie. you have to remove a lot of dirty code if you want it to build).
But now that you’ve mentioned it I might just do a bit more reading.
Cheers!
May 20, 2008
Thanks so much for this, if I’d known about this 5 years ago then I’d have saved so much of my actual life it doesn’t bear thinking about. I mean, all that time wasted waiting for code to compile; you’re not going to get it back.
This actually outperforms incredibuild in some circumstances - combining it with incredibuild gives the sort of compile times I used to enjoy using Borland Pascal.
This is particularly helpful if you’ve got a lot of one class = one header source in your code base. So, essentially, making your code nice and readable makes it compile slower.
The one thing that amazes me is how microsoft and other compiler makers don’t implement this sort of thing internally? Surely they must have thought of caching files in memory. Programmer man hours are too expensive to be waiting around for the stupid compiler to grind it way through files.
I’m sure many projects that have failed may have had more positive outcomes if there had been a quicker compile turn around. Some projects I’ve worked on could take over an hour to totally rebuild and that really, really adds up when you’re fixing things that get included everywhere.
Anyway, thanks buddy, you’re a life/project saver.
May 20, 2008
Hey Tim!
Wow
What a fantastic comment! I’m so happy that you’ve felt some of the benefits of Unity Builds already. Isn’t it amazing how quick they can be! And you’re right, the time you spent waiting in the past is time that you’re never going to get back. Shame it takes us so long to catch on to stuff like this eh? When I learned about them in ‘05 I was cursing myself for not knowing earlier.
Your feedback is greatly appreciated, I’m really chuffed to hear that you have benefitted from the post. Cheers mate and all the best!
June 2, 2008
My pleasure
We now use Unity builds at work and it’s improved productivity considerably. I’m a bit reluctant to say who I work for on line (I can never quite recall what my contract said about that sort of thing) but I can tell you that a number of high profile game projects know of your site and are very grateful for your pointing this technique out.
Tim.
June 2, 2008
Hi again Tim!
Thanks again for the feedback. I don’t blame you for holding back on where you work, it’s best to keep that kind of information to yourself. I’m very happy to hear that your company has benefitted from this technique as muchj as you have personally. That’s great news. It’s always good to know when your efforts help others!
Hrm, I have just noticed that the screenshots have just disappeared off the server, I don’t know what’s going on there. I’ll see if I can dig them up again.
Thanks again!
June 14, 2008
Hi OJ,
Thanks for posting this guide. I’ve been on projects that have used them before, but I never really paid attention to how it worked. Now I need to set this up for a very large project I’m having to frequently build. I’d be very happy to see the screen shots restored to show exactly how you’re doing this. Thanks
June 14, 2008
Hi Mr Smith!
I had totally forgotten about this! I had planned to restore those pics ages ago but it slipped my mind. Sorry for the tardiness. I’ll aim to have them back up online by the end of the day (Australian time ;)) and I’ll drop you an email when they’re up.
Cheers mate!
June 14, 2008
Thanks, OJ! I’m very much looking forward to seeing those shots. Please take your time, it’s Friday night here on the east coast of the US, and I won’t be working on this again until Monday.
Thanks again for sharing!
Cheers,
Mr. Smith
June 15, 2008
Mr Smith,
I haven’t had the chance to do it tonight, but I’ll aim to have it up for you Monday your time. Had a bitch of a day dealing with my son
I’ve decided I’m going to add not just the screenshots (which my server seems to have gobbled), but a screencast on how to do it, along with a C++ project (including a chunk of source code) demonstrating the speed up.
That should keep the masses happy
So watch this space! I’ll have it up shortly.
June 17, 2008
Sounds great, OJ. Thanks again for all your help - it’s appreciated. Good luck with your son
July 10, 2008
Does a unity build have a positive effect on link times?
July 10, 2008
Hi Code Tortoise,
Yes it most definitely does have a positive effect on link times for the same reason it improves compile times. Instead of linking many files it only links a few (or even one!). The link time drops dramatically.
Give it a shot
Hope that helps!
July 11, 2008
I think it’s worth noting that while full links are much quicker, incremental links are much slower, as it’s having to link in more stuff.
July 11, 2008
Yup, you’re dead right Iain. I should have made that clearer
Cheers!
July 16, 2008
Hi, oj
I heard UB other site, and I found your godd article.
If you don’t mind, I want this article translation to korean for my site.
July 16, 2008
Hi Swallow, drop me a line via the contact form and we’ll discuss it offline. Cheers!