blob: 1585c2937516e34dab80a8c7adde31877549ba7f [file] [log] [blame] [view]
# GN toolchains and the Fuchsia Build
## Overview of GN toolchains
The GN build tool allows one build to compile the same target in different
ways, using multiple [toolchains][gn-toolchain]{:.external}.
Each `toolchain()` instance corresponds to:
- **A unique name, expressed as a [GN label][gn-label]{:.external}**.
For example '//build/toolchain/fuchsia:x64' names the toolchain instance
defined in the `//build/toolchain/fuchsia/BUILD.gn` file, with a
`toolchain("x64")` definition.
- **A set of commands and build flags used to compile the source code and link
binaries**.
For example, using one toolchain to invoke Clang, and another one to invoke
Microsoft Visual C++, allows a single build to generate binaries using both
compiler suites.
- **A build graph node namespace**.
Separating targets with the same GN path, but compiled with different
toolchain instances. This is reflected in the format of
_fully-qualified GN labels_, that look like
`"//<dir>:<target>(<toolchain_dir>:<toolchain_target>)"`.
For example `//src/foo:bar(//toolchain:debug)` corresponds to the `bar`
target defined in `//src/foo/BUILD.gn`, when it is compiled with the
commands of the `//toolchain:debug` toolchain.
- **A separate GN execution context**.
Each toolchain instance executes its own parse of the GN
[buildconfig file][gn-buildconfig]{:.external}, which sets up global
variables and default values for all rules defining targets in
that toolchain.
In practice, if the same target is built with two different toolchains,
the corresponding `BUILD.gn` file will be parsed twice, but each time
with a different set of global variables, default configs and custom
templates defined in `BUILDCONFIG.gn`.
- **A separate root directory for target outputs**.
While the targets built in the default toolchain are placed under
[`root_build_dir`][gn-root_build_dir]{:.external}, the ones that are built
with a `//<toolchain_dir>:<toolchain_name>` instance are placed
under `${root_build_dir}/<toolchain_name>` instead.
This location is available at GN gen time through the
[`root_out_dir`][gn-root_out_dir]{:.external} variable.
There is always at least one toolchain, called the _default toolchain_, which
is determined by calling
[`set_default_toolchain()`][gn-set_default_toolchain]{:.external}
from the [buildconfig file][gn-buildconfig]{:.external}.
For more information read the [`toolchain()`][gn-toolchain]{:.external}
reference documentation.
## How the Fuchsia build uses GN toolchains
The Fuchsia build uses GN toolchains in several ways:
- _To build host and device executables_.
The build currently defines `//build/toolchain/fuchsia:x64` and
`//build/toolchain/fuchsia:arm64` to build Fuchsia executable binaries
for the 64-bit Intel and ARM architectures.
It also defines `//build/toolchain:host_x64` to build code for the host machine
(i.e. the one where the build happens).
It also defines `//build/toolchain:linux_x64` and `//build/toolchain:linux_arm64`
to generate Linux 64-bit code as well, even if the host is not running one of
these architectures.
There are also a number of specialized toolchains used to compile bootloaders
and parts of the kernel, described later.
- _To build ELF shared libraries_.
On Fuchsia, machine code that goes into shared objects (i.e. `shared_library()`
and `loadable_module()` instances in GN speak) must be built with the `-fPIC`
compiler and linker option.
This is unlike executable code, that uses `-fPIE` instead.
To deal with this, separate toolchain instances are defined to compile
code for shared librarie.
See [ELF Shared Library Redirection](elf_shared_library_redirection.md) for
more details.
- _To build different variants (e.g. instrumented or optimized) of binaries_.
The Fuchsia build supports a number of "build variants" which allow building
machine code in a slightly different way, for example:
- The `asan` and `ubsan` variants are used to build machine code with
Clang's Address Sanitizer, and Undefined Behaviour Sanitizer, respectively.
There is even an `asan-ubsan` variant that combines both.
- The `coverage` variant is used to build machine code with Clang's
instrumentation-based profiling enabled, to support code coverage
collection.
- The `profile` variant is used to build instrumented code as well,
but to support profile-guided optimization.
- The `thinlto` and `lto` variants are used to build binaries with
link-time optimization enabled.
- The `gcc` variant is used to build certain pieces of the Zircon
kernel with the GCC compiler instead of Clang (which has been useful
to weed out subtle machine code generation issues that can affect
the kernel in very important ways).
There are many other variants defined in the build's `BUILDCONFIG.gn` file
as well.
- _To generate (or process) source files_.
The build requires generating source files to be used in other
targets in many places. For example, FIDL protocol definition
files are processed to generate bindings for various languages
(C++, Rust, Go and Dart), which are later used by other
`source_set()`, or similar, targets.
Because the targets that use these sources can be defined in
different toolchain instances, it is useful to ensure that this
generation is only performed once, instead of once per toolchain
instance, since the output will be exactly the same in all cases.
The Fuchsia build thus defines the `fidling` toolchain to perform
FIDL bindings generation. Note that this toolchain is only used to
run a few scripts using `action()` targets, never to actually compile
them.
Similarly, a number of other "basic" toolchains are defined in the
build to perform processing tasks that should not be repeated
needlessly.
## How the Fuchsia build defines `toolchain()` instances.
The Fuchsia build provides these templates that define `toolchain()` instances
with various features:
- `basic_toolchain()` defines a "basic" toolchain, i.e.
one that does only `copy()` or `action()` target, and never needs to
use GN's builtin support for C++ and Rust compilation.
These are used to generate outputs that are used by other targets in
several other toolchains (e.g. language bindings) to avoid duplicate work.
Note that one basic toolchain is used to build Go binaries, and another
one for Dart ones, since GN doesn't support these languages at all.
- `clang_toolchain()` defines a toolchain instances that invokes
the Clang compiler. It provides support for building C++ and Rust
sources using GN's builtin rules.
Supported target platforms are Fuchsia, Linux, MacOS, Win32 PE/COFF
(as required by the UEFI bootloader) and even WebAssembly!
- `clang_toolchain_suite()` defines one more toolchain instances
based on the current build variant configuration. It is preferred over
calling `clang_toolchain()` directly because this is what allows
build variants to work.
- `clang_host_toolchain_suite()` is used for toolchains that generate
host machine code.
- `zircon_toolchain()` defines a toolchain instances that can be used to
build part of the Zircon kernel, bootloaders or even the C library.
These binaries typically require non-standard compile and linker commands
(e.g. a different ABI, or lack of standard link environment).
One notable feature of this template is that it also supports
building binaries using the GCC compiler, instead of Clang. This has
proven useful to find low-level code generation issues that the
kernel is very sensitive about, by its nature.
NOTE: There is no plan to support building the rest of the platform with GCC.
- `zircon_toolchain_suite()` is used to define one or more toolchain
instances based on the current build variant configuration. It is
preferred over calling `zircon_toolchain()` directly.
Note that the distinction between `zircon_toolchain()` and
`clang_toolchain()` is mostly historical, they might be merged into
a common template in the future.
[gn-label]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#labels
[gn-toolchain]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#func_toolchain
[gn-buildconfig]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#other-help-topics-gn-file-variables
[gn-set_default_toolchain]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#func_set_default_toolchain
[gn-root_build_dir]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#var_root_build_dir
[gn-root_out_dir]: https://gn.googlesource.com/gn/+/HEAD/docs/reference.md#var_root_out_dir