Build types#

While working with a compiled language (e.g. C++), you may have to select one of a few different build types.
Each one has its own pros and cons and should be used for specific purposes.

Predefined build types#

Standard build types are : Debug, Release, Release with Debug Information and Minimum Size Release.

Note

You can create your own easily. Feel free to be inspired by those shown below.

Different types are meant to alter the compilation flags to provide different binaries and other files, such as :

  • optimization level - if and how the code is optimized (speed, size)

  • debug informations - if must provide some data to be able to reuse the binaries and find the cause of a crash

  • assert and other outputs - if should disable the asserts or not, if the output is redirected somewhere or nulled

  • specific build tweaks - can enable better or faster FPU calculations, how the data is aligned, the dialect to use, enabling implicit conversions, language specifics warnings …

  • and many more …

In fact, the optimization level hides the use of multiple other flags that will tweak how the binaries are produced.

Optimization level#

The optimization level is set through a flag : -O/0/1/2/3/4, -Ofast, -Omin, -Os/z/g ....
Those are compiler dependent (see GCC’s compiler documentation), but the most common are :

Optimization level flag

Features

-O0 / none

Straightforward compilation. No rearrangement. Debugging produce the expected result (even dead code is compiled). Default level.

-O / -O1

Tries to reduce code size and execution time. No speed-space tradeoffs. No instruction scheduling (pipeline). May take longer to compile. Provide a good debug experience.

-O2

Same as -O1, with pipeline activated. Standard used for release.

-O3

Further optimizations such as function inlining. If the L1 cache is big enough, the code may run faster. Otherwise, it will slow down since the same procedure may be composed of more instructions.

-Os

Aim for code size reduction, with near -O2/3 performance.

-Ofast

Aim for the fastest code, with -O3 optimizations and fast maths applied.

Note

Higher optimization levels (may) need more time to compile.

Warning

-O3 may create some problems if you rely on undefined behaviors, problems not seen with lower optimization levels.

Debug#

The Debug build aims to provide debuggable binaries.
Common flags are -O0 and -g, to force no optimization and debug data output.
Asserts are enabled, and debug info (enabling step by step) are generated.
Common use case is development.

Warning

You must run tests in Release too. Since optimizations are applied, you must ensure that no bugs appear in your program.

Release with Debug Information#

The Release with Debug Information build aims to provide optimized, with debug info binaries.
Common flags are -O2, -g, and -DNDEBUG to force great optimization, with debug info.
Asserts are disabled. While debug info are produced, step by step will not work very well (but breakpoints are still usable).
Common use case is for internal use, to be able to trace the problem in case of a crash, or if you send it for a developer to reuse inside its program. You may choose to not ship debug info to the final client tho.

Release#

The Release build aims to provide optimized binaries.
Common flags are -O3 and -DNDEBUG to force great optimization.
Asserts are disabled. No debug info are produced.
Common use case is for distribution. Beware that it will not be possible to backtrace where the error occured.

Minimum Size Release#

The Minimum Size Release build aims to provide optimized, while as small as possible binaries.
Common flags are -Os and -DNDEBUG to force great optimization while aiming for small size.
Asserts are disabled. The binary is as small as possible to fit on more restrained devices.
Common use case are embedded environments. It can also be used to reduce DLL sizes if used by many processes.

DLL LIB Libraries