| --- |
| short-description: Using precompiled headers to reduce compilation time |
| ... |
| |
| # Precompiled headers |
| |
| Parsing header files of system libraries is surprisingly expensive. A |
| typical source file has less than one thousand lines of code. In |
| contrast the headers of large libraries can be tens of thousands of |
| lines. This is especially problematic with C++, where header-only |
| libraries are common and they may contain extremely complex code. This |
| makes them slow to compile. |
| |
| Precompiled headers are a tool to mitigate this issue. Basically what |
| they do is parse the headers and then serialize the compiler's |
| internal state to disk. The downside of precompiled headers is that |
| they are tricky to set up. Meson has native support for precompiled |
| headers, but using them takes a little work. |
| |
| A precompiled header file is relatively simple. It is a header file |
| that contains `#include` directives for the system headers to |
| precompile. Here is a C++ example. |
| |
| ```cpp |
| #include<vector> |
| #include<string> |
| #include<map> |
| ``` |
| |
| In Meson, precompiled header files are always per-target. That is, the |
| given precompiled header is used when compiling every single file in |
| the target. Due to limitations of the underlying compilers, this |
| header file must not be in the same subdirectory as any of the source |
| files. It is strongly recommended that you create a subdirectory |
| called `pch` in the target directory and put the header files (and |
| nothing else) there. |
| |
| Toggling the usage of precompiled headers |
| -- |
| |
| If you wish to compile your project without precompiled headers, you |
| can change the value of the pch option by passing `-Db_pch=false` |
| argument to Meson at configure time or later with `meson configure`. You can |
| also toggle the use of pch in a configured build directory with the |
| GUI tool. You don't have to do any changes to the source |
| code. Typically this is done to test whether your project compiles |
| cleanly without pch (that is, checking that its #includes are in |
| order) and working around compiler bugs. |
| |
| Using precompiled headers with GCC and derivatives |
| -- |
| |
| Once you have a file to precompile, you can enable the use of pch for |
| a given target with a *pch* keyword argument. As an example, let's assume |
| you want to build a small C binary with precompiled headers. |
| Let's say the source files of the binary use the system headers `stdio.h` |
| and `string.h`. Then you create a header file `pch/myexe_pch.h` with this |
| content: |
| |
| ```c |
| #include <stdio.h> |
| #include <string.h> |
| ``` |
| |
| And add this to meson: |
| |
| ```meson |
| executable('myexe', sources : sourcelist, c_pch : 'pch/myexe_pch.h') |
| ``` |
| |
| That's all. You should note that your source files must _not_ include |
| the file `myexe_pch.h` and you must _not_ add the pch subdirectory to |
| your search path. Any modification of the original program files is |
| not necessary. Meson will make the compiler include the pch with |
| compiler options. If you want to disable pch (because of, say, |
| compiler bugs), it can be done entirely on the build system side with |
| no changes to source code. |
| |
| You can use precompiled headers on any build target. If your target |
| has multiple languages, you can specify multiple pch files like this. |
| |
| ```meson |
| executable('multilang', sources : srclist, |
| c_pch : 'pch/c_pch.h', cpp_pch : 'pch/cpp_pch.h') |
| ``` |
| |
| Using precompiled headers with MSVC |
| -- |
| Since Meson version 0.50.0, precompiled headers with MSVC work just like |
| with GCC. Meson will automatically create the matching pch implementation |
| file for you. |
| |
| Before version 0.50.0, in addition to the header file, Meson |
| also requires a corresponding source file. If your header is called |
| `foo_pch.h`, the corresponding source file is usually called |
| `foo_pch.cpp` and it resides in the same `pch` subdirectory as the |
| header. Its contents are this: |
| |
| ```cpp |
| #if !defined(_MSC_VER) |
| #error "This file is only for use with MSVC." |
| #endif |
| |
| #include "foo_pch.h" |
| ``` |
| |
| To enable pch, simply list both files in the target definition: |
| |
| ```meson |
| executable('myexe', sources : srclist, |
| cpp_pch : ['pch/foo_pch.h', 'pch/foo_pch.cpp']) |
| ``` |
| |
| This form will work with both GCC and msvc, because Meson knows that |
| GCC does not need a `.cpp` file and thus just ignores it. |
| |
| It should be noted that due to implementation details of the MSVC |
| compiler, having precompiled headers for multiple languages in the |
| same target is not guaranteed to work. |