About BLITZ and precompiled headers
Blitz is advanced compilation technique based on SCU approach, intended to speedup debug mode rebuilds of large applications. In fact, BLITZ is what allows U++ to keep libraries in sources form. You can consider BLITZ as an automated form SCU.
Blitz processes packages (not the whole program) - each package can have a single blitz-block (blitz block is SCU).
Only .cpp including files with inclusion guards (#ifdef NAME_H #define NAME_H .... #endif) can qualify to be part of blitz-block.
Alternatively, you can force inclusion by
(also works for header) or exclusion by
In addition only files older than one hour qualify for blitz-block. This simple heuristics excludes file that are being worked on - otherwise change in file would always require rebuilding of the whole package, which would be potentially slower.
The files in package that do not qualify for blitz-block are build the regular way.
It is also possible to disable blitz for individual packages, either on project basis (in Package organizer) or in Output mode dialog (machine specific setting).
Files in blitz-block are scanned for any #define, these are undefined after the file. blitz-block is in fact a file generated into output directory that include all blitz approved files and gets compiled instead of them (it is named $blitz.cpp, you can check the output directory for details).
BLITZ also includes one dirty trick to basically allow BLITZ compilation of packages that define static variables names based on the line number (macro __LINE__). Static variables are not visible outside the compilation unit using the normal build process, but when using BLITZ, more than single .cpp files are compiled into single unit and so there is the possibility that two such variables would have the same name.
Therefore BLITZ adds BLITZ_INDEX__ macro, which contains a unique number (index of file) for each .cpp. That way you can create "static" identifiers e.g. like this (and also make it compile without BLITZ):
#define MK__s__(x) s__s##x
#define MK__s_(x) MK__s__(x)
#define STATIC_ID MK__s_(COMBINE(BLITZ_INDEX__, __LINE__))
#define STATIC_ID MK__s_(__LINE__)
Precompiled headers is a compiler technique trying to solve the very same problem. In general, we have found BLITZ faster than any precompiled header use, however BLITZ tends to have one disadvantage: by combining all files into single object file, linker has less opportunity to remove unused code. This leads to (sometimes significantly) larger executable binaries. For this reason, we do not recommend (and have off by default) BLITZ for release builds and if possible, we use precompiled headers for release builds.
Precompiled headers have a set of its own problems. Notably, Microsoft C++ precompiled headers are hard to use with multiple processes building the code (Hydra) in debug mode. Also, precompiled headers in general are very bulky files, easily surpassing 100MB, which is a problem as we need to have single precompiled header per package.
For these reasons precompiled headers support works like this:
Precompiled headers are activated only in release mode without blitz.
You have to set "Precompile header" flag on header files candidates for precompilation. Only single candidate per package is allowed. Note that not all headers can be with this system. Header has to have include guards and it must be possible for all files in the package to include it first before all other headers.
Build method has to have "Allow precompiled headers" set.
When package is build, it first checks whether using precompiled header is possible (as per rules above). Then it checks how many files are to be rebuild. If there are 3 or more files to build, U++ precompiles the header and uses it to build the package. When the package is built, U++ deletes the header to conserve the space.
U++ supports precompiled headers for MSC, GCC and CLANG. However, practical benchmarks show that with CLANG using precompiled headers actually leads to worse compilation times.