Search code examples
c++visual-studiocompilationglm-mathprecompiled-headers

How to reduce compilation time with GLM?


I'm using GLM, which is a library that provides some low level math types and functions I use everywhere. But using this Visual Studio addon revealed that GLM comprises about 50% of my compilation time, or around 30 seconds, during each build.

The documentation mentions using "precompiled headers" to speed up compilation, but I'm extremely unfamiliar with the concept, and haven't been able to find any further information on them. How might I get GLM to use precompiled headers? Would that alleviate the compilation time at all?

I do know how to create a static library .lib file, but I'm unsure if that'd be useful at all for a header/template heavy library.

(I also have trouble with chrono and mutex consuming a lot of time. Maybe that's just a cost that has to be paid though? I've done my best to restrict the compilation units they're included into at least.)


Solution

  • (Submitting an answer so others know what I did, but credit to @john for answering in the comments)

    Precompiled Headers got my build time down from 2 minutes to 10 seconds(!)

    In order to utilize "precompiled headers" in Visual Studio from an empty project, the steps I followed were:

    • Add a pch.h and pch.cpp file to the project.
    • In the properties of pch.cpp, under C++ -> precompiled header, set it to Create (/Yc) and set the the name of header file to pch.h (you can pick your own name if you want, stdafx.h and pch.h are just default names Visual Studio will pick.)
    • pch.cpp should have #include "pch.h" as it's only line. This compilation unit will be compiled first and generates the compiler state all the other compilation units can now reuse.
    • In the properties of every *.cpp file that you want to benefit from the precompiled header (it doesn't need to be all of them), you must go into their properties (ctrl+click or drag to do this for multiple files at once), and under C++ -> precompiled header set it to Use (/Yu) and use the same pch.h header name.
    • Every source file you set to use a precompiled header, must include pch.h as it's very first action. This is because when the compiler encounters that line, it'll discard it's current state (everything before #include "pch.h") and use the state it generated when it compiled the pch.cpp unit.
    • Finally, put all the headers and code you want to precompile into pch.h and that should be it.

    For me, my pch.h header ended up looking like this:

    #pragma once
    #include <vector>
    #include <string>
    #include <map>
    #include <queue>
    #include <mutex>
    #include <chrono>
    #include <atomic>
    #include <condition_variable>
    
    #include <cstdint>
    #include <cstdarg>
    #include <cctype>
    #include <cstring>
    #include <cstdlib>
    #include <utility>
    #include <cmath>
    #define GLM_FORCE_RADIANS
    #define GLM_FORCE_LEFT_HANDED
    #define GLM_ENABLE_EXPERIMENTAL
    #include <glm/glm.hpp>
    #include <glm/detail/func_common.hpp>
    #include <glm/trigonometric.hpp>
    #include <glm/gtc/constants.hpp>
    #include <glm/gtc/bitfield.hpp>
    #include <glm/gtc/round.hpp>
    #include <glm/gtx/rotate_vector.hpp>
    #include <glm/gtx/vector_angle.hpp>
    #include <glm/gtx/quaternion.hpp>
    

    Please note that I'm not speaking from authority on the subject though, just putting what I did for myself here if it's useful; I wouldn't be surprised if there were a more elegant way to do this.