cxx_precompiled_header
name
def name(
*,
name: str,
default_target_platform: None | str = ...,
target_compatible_with: list[str] = ...,
compatible_with: list[str] = ...,
exec_compatible_with: list[str] = ...,
visibility: list[str] = ...,
within_view: list[str] = ...,
metadata: OpaqueMetadata = ...,
tests: list[str] = ...,
modifiers: OpaqueMetadata = ...,
_apple_platforms: dict[str, str] = ...,
contacts: list[str] = ...,
default_host_platform: None | str = ...,
deps: list[str] = ...,
labels: list[str] = ...,
licenses: list[str] = ...,
src: str,
version_universe: None | str = ...,
) -> None
A cxx_precompiled_header
rule specifies a single header file that can be precompiled and made available for use in other build rules such as a cxx_library()
or a cxx_binary()
.
Parameters
name
: name of the targetdefault_target_platform
: specifies the default target platform, used when no platforms are specified on the command linetarget_compatible_with
: a list of constraints that are required to be satisfied for this target to be compatible with a configurationcompatible_with
: a list of constraints that are required to be satisfied for this target to be compatible with a configurationexec_compatible_with
: a list of constraints that are required to be satisfied for this target to be compatible with an execution platformvisibility
: a list of visibility patterns restricting what targets can depend on this onewithin_view
: a list of visibility patterns restricting what this target can depend onmetadata
: a key-value map of metadata associated with this targettests
: a list of targets that provide tests for this onemodifiers
: an array of modifiers associated with this targetdeps
: Dependency rules which export headers used by the header specified insrc
.src
: The path to the header file that should be precompiled. Only one header file can be specified. But of course this header could include any number of other headers. The included headers could belong to -- that is, beexported_headers
from -- another rule, in which case, the rule would have to be added todeps
as usual.
Details
This header file is precompiled by the preprocessor on behalf of the
C, C++, Objective-C, or Objective-C++ rule using it, via its precompiled_header
parameter.
Afterwards the precompiled header is applied during the rule's own compilation
(often with an appreciable reduction in build time, the main benefit of PCH).
This PCH is built once per combination of build flags which might affect the PCH's compatibility.
For example, a distinct pre-compilation of the header occurs per combination of flags related to
optimization, debug, architecture, and so on, used by rules which employ PCH.
The flags used during the build of the dependent rule (that is, the "PCH-using rule")
are in effect while building the PCH itself. Similarly, to the same end, the include paths used
when building the PCH are applied to the dependent rule. For example, deps
in the
PCH rule are propagated back to the dependent rule, and the PCH's header search paths
(e.g. -I
or -isystem
options) are prefixed onto the list of
include paths for the dependent rule.
Examples:
The best way to see how the cxx_precompiled_header()
rule works is with an
example. Let there be a header called common.h
which has the following:
#pragma once
/* Include common C++ files. */
#include <string>
#include <map>
#include <set>
#include <type_traits>
#include <vector>
/* Some frequently-used headers from the Folly project. */
#include <folly/Conv.h>
#include <folly/Executor.h>
#include <folly/io/async/EventBase.h>
cxx_precompiled_header(
name = 'common_pch',
src = 'common.h',
deps = [
# Needed for standard C++ headers:
'//external/libcxx:headers',
# Needed for the Folly includes:
'//folly:folly',
'//folly/io/async:async',
],
)
cxx_binary(
name = 'main',
srcs = ['main.cpp'],
precompiled_header = ':common_pch',
deps = [ ... ],
compiler_flags = ['-g', '-O2', '-fPIC'],
)
The cxx_precompiled_header
rule declares a precompiled header "template"
containing the header file path, and dependencies.
In this example we indicate that common.h
is to be precompiled when used by another build rule.
Note that, by itself, this cxx_precompiled_header
rule will not result
in anything being built. The usage of this rule from another rule --
an "instantiation" of this precompiled header template -- is what will trigger the
PCH build.
In the example above, the build for the binary named "main"
will depend on
the header being precompiled in a separate step, prior to compiling main.cpp
,
and the resulting PCH will be used in main
's compilation.
The dependencies specified in this precompiled header rule's deps
are transitive; they
will propagate to rules using this PCH, so that during link time, any libraries which are
required by the code made available in the header will be included in the final binary build.
The precompiled header dynamically created from the "template" will be built with flags
which would be used in the dependent rule. In this case, main
's use of specific
compiler flags -g -O2 -fPIC
will result in the production of a precompiled header
with the same flags. This is so the precompiled code fully jives with rules using the PCH,
i.e. they will have the same debug, optimization, CPU, etc. options. (The compiler is usually
smart enough to reject a bad PCH, fortunately. But we want to ensure we take the appropriate
steps to ensure we always have a PCH which works with any build that uses it.)
Another effect of a rule using a precompiled header is that the rule's list of
build flags will change; not just to employ PCH with e.g. -include-pch
(if using Clang), but also, to alter the sequence of header search paths.
The rule using the precompiled header will "inherit" the lists of paths used
during the PCH build, applying them first in its own search paths.
This is to ensure that an #include
directive will resolve in exactly
the same way in this build as it would have in the PCH, to ensure full compatibility
between the PCH and other rule's builds. For example, if the PCH were to use one version
of stdcxx
and another rule use a different version, the version differences
won't clash, thereby avoiding different versions of the <cstring>
header
used between the precompiled header and the dependent rule, and preventing confused
structure definitions, ABI incompatibility, and so on (catastrophe, in other words).