Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
October 16, 2017
arrowPress Releases

If you enjoy reading this site, you might also want to check out these UBM Tech sites:


Long build times? You're doing it wrong.

by Bram Stolk on 07/10/14 12:39:00 am   Featured Blogs

The following blog post, unless otherwise noted, was written by a member of Gamasutras community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.


When I hear developers complain about long build times, it immediately makes me suspicious about the quality of their code base. They have simply built a big ball of mud, a.k.a. spaghetti code. What has happened is that the compiler gets bogged down by an avalanche of include files. Don't fight the symptom by using precompiled headers! Instead, fix the root cause: the crappy architecture of your game. What follows in this article, is a recipe for a clean code base that builds in a couple of seconds, not minutes.

Here's the TL;DR version of this article: do not include header files in header files. The dependencies that foo.cpp uses to implement its functionality should never leak into the foo.h interface. I'll state up front that a C-like programming style lends itself better for this than a C++ programming style. But even when using C++ classes, it is often possible to avoid include directives.

If the interface of class Foo only contains uses of class Bar that are references or pointers, then the compiler does not need to know what Bar looks like when parsing the header for Foo. All that is required is that Bar is forward declared for the Foo interface. You tell the compiler that there is a class named Bar, and leave it at that. Typically, there will be someclasses in your gamethat need to include large third party frameworks. It is paramount that these frameworks do not leak into the users of class Bar, like class Foo.

If you constantly ask yourself: "How can I keep the implementation details out of the interface?" then you can cut down on the include directives. Also preferring primitive types char/int/float/bool and pointers over custom object types is a great strategy for pruning include hierarchies.

So where can this get you? To illustrate this, I will examine the code base of the game I am currently creating. The only uses of middleware areOpenAL andOpenDE. It is a fully featured game with biplanes, AI, formation flying, dogfighting, explosions, menus, tutorials, whathaveyou, totaling roughly 50K lines of code. But building from scratch(including linking) takes less than three seconds.

real 0m2.687s
user 0m5.076s
sys 0m0.542s

This is because the include hierarchies are extremely flat. For instance, here is what gets pulled in to implement the logical representation of my game world.

And here is what the code that uses the game world sees when it includes wld.h:

In my code, dependencies are hidden, and almost never propagated throughout the system. The notable exceptions arethe leaking of my vector mathheader and my rendering context data into the interface. The latter includes no further files, and the former only three system headers.

The world contains terrain, planes, bullets, hangars, explosions and much more. But the code that uses (creates, destroys, renders) this world should not be bothered by these details.

Personally I think that distributed build systems, build caches, precompiled headers are all curses disguised as blessings. These mechanisms that make your build go faster, allow you to ignore the root problem for longer. The mud ball grows and grows, and when you are finally fed up with long build times, the tangled mess may be beyond repair. Top tip: disable precompiled headers!

Let me conclude with a tip on how to inspect the sanitation conditions in your code. Snowballing include directives are brutally exposed with the 'Doxygen' tool if you tell it to generate include graphs with graphviz's dot program. Use the following directives in your Doxygen configuration file:


If the Doxygen output includes huge dependency graphs, you know that you are on the wrong path. Also, cycles in the graph with lower level files pointing back to higher level files are a huge red flag.

I'm curious to know how my peers view this issue. Also, what is the longest build time that you have encountered? Drop your remarks in the comments, they are highly appreciated!

Related Jobs

Deck Nine Games
Deck Nine Games — Westminster, Colorado, United States

Mobile Programmer
Deck Nine Games
Deck Nine Games — Westminster, Colorado, United States

Senior Console Programmer
DigitalFish, Inc.
DigitalFish, Inc. — San Mateo, California, United States

Software Engineer - Machine Learning
DigitalFish, Inc.
DigitalFish, Inc. — Mountain View, California, United States

Software Engineer - AR/VR

Loading Comments

loader image