Precompiled Header File Handling by Different Compilers
Recently, in order to implement precompiled header file support for xmake, I studied the mechanisms and differences of how major mainstream compilers handle precompiled headers.
Most c/c++ compilers now support precompiled headers, such as: gcc, clang, msvc, etc., to optimize c++ code compilation speed. After all, if c++ header files contain template definitions, compilation speed is very slow. If most common header files can be placed in a header.h and precompiled before other source code compilation, subsequent code can reuse this part of the precompiled header, which can greatly reduce frequent redundant header file compilation.
However, different compilers have different levels of support and handling methods for it, and it's not very universal. It took a lot of effort to encapsulate it into a unified interface and usage method in xmake.
MSVC Precompiled Header Handling
Precompiled headers are very common in msvc projects. You often see files like stdafx.cpp, stdafx.h, which are used for this purpose. The msvc compiler generates the precompiled header file stdafx.pch by compiling stdafx.cpp.
The command line to create a precompiled header is as follows:
$ cl.exe -c -Yc -Fpstdafx.pch -Fostdafx.obj stdafx.cppAmong them, -Yc means creating the precompiled header stdafx.pch, -Fp is used to specify the output file path of *.pch, and -Fo is used to specify the object file generated by compiling stdafx.cpp.
How do other source files use this stdafx.pch? By passing stdafx.h to -Yu to tell the compiler to compile the current code, ignore #include "stdafx.h", and directly use the already compiled stdafx.pch file.
$ cl.exe -c -Yustdafx.h -Fpstdafx.pch -Fotest.obj test.cppFinally, when linking, you need to link both: stdafx.obj and test.obj. This is also different from gcc and clang compilers.
$ link.exe -out:test test.obj stdafx.objNote: You must also link stdafx.obj. Although stdafx.cpp is only used to generate stdafx.pch, the object file is also needed.
Another difference from gcc and clang is that msvc's -Yu specifies that stdafx.h must be the header file name in #include "stdafx.h", not the file path.
Clang Precompiled Header File Handling
I personally feel that clang's precompiled header file support is the most friendly and simplest.
Compared to msvc, it doesn't need stdafx.cpp, only a header file stdafx.h can generate a pch file. Compared to gcc, it can flexibly control the pch file path, which is more flexible.
Compile header file to generate pch file:
$ clang -c -o stdafx.pch stdafx.hUse precompiled header file:
$ clang -c -include stdafx.h -include-pch stdafx.pch -o test.o test.cppAmong them, -include stdafx.h is used to ignore #include "stdafx.h" when compiling test.cpp, and use the precompiled stdafx.pch through -include-pch.
And the stdafx.h and stdafx.pch specified here can not only be files in the includedir search path, but also specify full path file names, which is very flexible, for example:
$ clang -c -include inc/stdafx.h -include-pch out/stdafx.pch -o test.o test.cppGCC Precompiled Header File Handling
gcc's precompiled header handling is basically similar to clang's. The only difference is: it doesn't support the -include-pch parameter, so it cannot specify the stdafx.pch file path to use.
It has its own search rules:
- Look for
stdafx.h.pchfile in the directory wherestdafx.his located - Look for
stdafx.h.pchin the-Iheader file search path
Compile header file to generate pch file:
$ gcc -c -o stdafx.pch stdafx.hUse precompiled header file:
$ gcc -c -include stdafx.h -o test.o test.cppIn order for the above code to compile normally, stdafx.h.pch must be placed in the same directory as stdafx.h, so that compilation can find it. I haven't found a method to specify the output directory yet.
Other Notes
For gcc and clang, compiling *.h header files by default is used as c precompiled headers, which is different from c++ pch and cannot be used by c++ code. If you want to generate c++ usable pch files, you must tell the compiler how to compile stdafx.h.
This can be solved through the -x c++-header parameter:
$ gcc -c -x c++-header -o stdafx.pch stdafx.hOf course, it can also be solved by modifying the suffix:
$ gcc -c -o stdafx.pch stdafx.hppxmake Support for Precompiled Header Files
xmake supports accelerating c/c++ program compilation through precompiled header files. Currently supported compilers are: gcc, clang and msvc.
The usage for c precompiled header files is as follows:
target("test")
set_pcheader("header.h")If it's precompilation of c++ header files, change to:
target("test")
set_pcxxheader("header.h")For more usage instructions, see: target.set_pcheader