Overview of GN toolchains
The GN build tool allows one build to compile the same target in different ways, using multiple toolchains.
toolchain() instance corresponds to:
A unique name, expressed as a GN label.
For example '//build/toolchain/fuchsia:x64' names the toolchain instance defined in the
//build/toolchain/fuchsia/BUILD.gnfile, with a
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
//src/foo:bar(//toolchain:debug)corresponds to the
bartarget defined in
//src/foo/BUILD.gn, when it is compiled with the commands of the
A separate GN execution context.
Each toolchain instance executes its own parse of the GN buildconfig file, 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.gnfile will be parsed twice, but each time with a different set of global variables, default configs and custom templates defined in
A separate root directory for target outputs.
While the targets built in the default toolchain are placed under
root_build_dir, the ones that are built with a
//<toolchain_dir>:<toolchain_name>instance are placed under
This location is available at GN gen time through the
For more information read the
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:arm64to build Fuchsia executable binaries for the 64-bit Intel and ARM architectures.
It also defines
//build/toolchain:host_x64to build code for the host machine (i.e. the one where the build happens).
It also defines
//build/toolchain:linux_arm64to 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.
loadable_module()instances in GN speak) must be built with the
-fPICcompiler and linker option.
This is unlike executable code, that uses
To deal with this, separate toolchain instances are defined to compile code for shared librarie.
See ELF Shared Library Redirection 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:
ubsanvariants are used to build machine code with Clang's Address Sanitizer, and Undefined Behaviour Sanitizer, respectively. There is even an
asan-ubsanvariant that combines both.
coveragevariant is used to build machine code with Clang's instrumentation-based profiling enabled, to support code coverage collection.
profilevariant is used to build instrumented code as well, but to support profile-guided optimization.
ltovariants are used to build binaries with link-time optimization enabled.
gccvariant 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.gnfile 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
fidlingtoolchain 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
The Fuchsia build provides these templates that define
with various features:
basic_toolchain()defines a "basic" toolchain, i.e. one that does only
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 allow 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
Note that the distinction between
clang_toolchain() is mostly historical, they might be merged into
a common template in the future.