blob: 41a178de23a3c8a2fb3e740eb3a7b487da84ef9e [file] [log] [blame] [view]
# GN Frequently Asked Questions
[TOC]
## Where is the GN documentation?
GN has extensive built-in help, so you can run `gn help`, but you can also see
all of the help on [the reference page](reference.md). See also the [quick
start](quick_start.md) guide and the [language and operation
details](language.md).
## Can I generate XCode or Visual Studio projects?
You can generate skeleton (or wrapper) projects for Xcode, Visual Studio,
QTCreator, and Eclipse that will list the files and targets in the build, but
use Ninja to do the actual build. You cannot generate "real" projects that look
and compile like native ones.
Run `gn help gen` for more details.
## How do I do cross-compiles?
GN has robust support for doing cross compiles and building things for
multiple architectures in a single build.
See [GNCrossCompiles](cross_compiles.md) for more info.
## Can I control what targets are built by default?
Yes! If you create a group target called "default" in the top-level (root) build
file, i.e., "//:default", GN will tell Ninja to build that by default, rather
than building everything.
## Are there any public presentations on GN?
[There's at least one](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing), from 2015. There
haven't been big changes since then apart from moving it to a standalone
repo, so it should still be relevant.
## What is the order of flags and values given to the compiler?
The final values of compiler flags, linker flags, defines, and include
directories are collected from various sources by GN. The ordering is defined
as:
1. Those set directly on the current target (not in a config).
2. Those set on the `configs` on the target in order that the configs appear in the list.
3. Those set on the `all_dependent_configs` on the target in order that the configs appear in the list.
4. Those set on the `public_configs` on the target in order that those configs appear in the list.
5. `all_dependent_configs` pulled from dependencies, in the order of the `deps` list. This is done recursively. If a config appears more than once, only the first occurrence will be used.
6. `public_configs` pulled from dependencies, in the order of the `deps` list. If a dependency is public, they will be applied recursively.
If you need a specific relative ordering of values you may need to put those
flags in a config and prepend or append that config in a way that produces the
desired result.
## How can a target affect those that depend on it?
The main way that information flows up the dependency graph is via
`public_configs`. This allows a target to add preprocessor defines, compiler
flags, and linker flags to targets that depend on it. A typical example is a
library that requires `include_dirs` and `defines` to be set in a certain way
for its headers to work. It would put its values in a config:
```
config("icu_config") {
include_dirs = [ "//third_party/icu" ]
defines = [ "U_USING_ICU_NAMESPACE=0" ]
}
```
The library would then reference that as a `public_config` which will apply it
to any target that directly depends on the `icu` target:
```
shared_library("icu") {
sources = [ ... ]
deps = [ ... ]
public_configs = [ ":icu_config" ] # Label of config defined above.
}
```
A `public_config` applies only to direct dependencies of the target. If a target
wants to "republish" the `public_configs` from its dependencies, it would list
those dependencies in its `public_deps`. In this example, a "browser" library
might use ICU headers in its own headers, so anything that depends on it also
needs to get the ICU configuration:
```
shared_library("browser") {
...
# Anything that depends on this "browser" library will also get ICU's settings.
public_deps = [ "//third_party/icu" ]
}
```
Another way apply settings up the dependency graph is with
`all_dependent_configs` which works like `public_configs` except that it is
applied to all dependent targets regardless of `deps`/`public_deps`. Use of this
feature is discouraged because it is easy to accumulate lots of unnecessary
settings in a large project. Ideally all targets can define which information
their dependencies need and can control this explicitly with `public_deps`.
The last way that information can be collected across the dependency graph is
with the metadata feature. This allows data (see `gn help metadata`) to be
collected from targets to be written to disk (see `gn help generated_file`) for
the build to use. Computed metadata values are written after all BUILD.gn files
are processed and are not available to the GN script.
Sometimes people want to write conditional GN code based on values of a
dependency. This is not possible: GN has no defined order for loading BUILD.gn
files (this allows pararellism) so GN may not have even loaded the file
containing a dependency when you might want information about it. The only way
information flows around the dependency graph is if GN itself is propagating
that data after the targets are defined.
## How can a target affect its dependencies?
Sometimes you might have a dependency graph **A 🠲 Z** or a longer chain **A 🠲 B
🠲 C 🠲 Z** and want to control some aspect of **Z** when used from **A**. This is
not possible in GN: information only flows up the dependency chain.
Every label in GN is compiled once per _toolchain_. This means that every target
that depends on **B** gets the same version of **B**. If you need different
variants of **B** there are only two options:
1. Explicitly define two similar but differently named targets encoding the
variations you need. This can be done without specifying everything twice using
a template or by writing things like the sources to a variable and using that
variable in each version of the target.
2. Use different toolchains. This is commonly used to encode "host" versus
"target" differences or to compile parts of a project with something like ASAN.
It is possible to use toolchains to encode any variation you might desire but
this can be difficult to manage and might be impossible or discoraged depending
on how your project is set up (Chrome and Fuchsia use toolchains for specific
purposes only).
## How can I recursively copy a directory as a build step?
Sometimes people want to write a build action that expresses copying all files
(possibly recursively, possily not) from a source directory without specifying
all files in that directory in a BUILD file. This is not possible to express:
correct builds must list all inputs. Most approaches people try to work around
this break in some way for incremental builds, either the build step is run
every time (the build is always "dirty"), file modifications will be missed, or
file additions will be missed.
One thing people try is to write an action that declares an input directory and
an output directory and have it copy all files from the source to the
destination. But incremental builds are likely going to be incorrect if you do
this. Ninja determines if an output is in need of rebuilding by comparing the
last modified date of the source to the last modified date of the destination.
Since almost no filesystems propagate the last modified date of files to their
directory, modifications to files in the source will not trigger an incremental
rebuild.
Beware when testing this: most filesystems update the last modified date of the
parent directory (but not recursive parents) when adding to or removing a file
from that directory so this will appear to work in many cases. But no modern
production filesystems propagate modification times of the contents of the files
to any directories because it would be very slow. The result will be that
modifications to the source files will not be reflected in the output when doing
incremental builds.
Another thing people try is to write all of the source files to a "depfile" (see
`gn help depfile`) and to write a single stamp file that tracks the modified
date of the output. This approach also may appear to work but is subtly wrong:
the additions of new files to the source directory will not trigger the build
step and that addition will not be reflected in an incremental build.
## How can I reference all files in a directory (glob)?
Sometimes people want to automatically refer to all files in a directory,
typically something like `"*.cc"` for the sources. This is called a "glob."
Globs are not supported in GN. In order for Ninja to know when to re-run
GN, it would need to check the directory modification times of any
directories being globbed. Directory modification times that reflect
additions and removals of files are not as reliably implemented across
platforms and filesystems as file modification times (for example, it is
not supported on Windows FAT32 drives).
Even if directory modification times work properly on your build systems,
GN's philosophy prefers a very explicit build specification style that
is contrary to globs.
## Why does "gn check" complain about conditionally included headers?
The "gn check" feature (see `gn help check`) validates that the source code's
use of header files follows the requirements set up in the build. It can be a
very useful tool for ensuring build correctness.
GN scans the source code for `#include` directives and checks that the included
files are allowed given the specification of the build. But it is relatively
simplistic and does not understand the preprocessor. This means that some
headers that are correctly included for a different build variant might be
flagged by GN. To disable checking of an include, append a "nogncheck"
annotation to the include line:
```
#if defined(OS_ANDROID)
#include "src/android/foo/bar.h" // nogncheck
#endif
```
Correctly handling these cases requires a full preprocessor implementation
because many preprocessor conditions depend on values set by other headers.
Implementing this would require new code and complexity to define the toolchain
and run the preprocessor, and also means that a full build be done before doing
the check (since some headers will be generated at build-time). So far, the
complexity and disadvantages have outweighed the advantages of a perfectly
correct "gn check" implementation.
## Why does "gn check" miss my header?
The "gn check" feature (see previous question) only checks for headers that have
been declared in the current toolchain. So if your header never appears in a
`sources` or `public` list, any file will be able to include it without "gn
check" failing. As a result, targets should always list all headers they contain
even though listing them does not affect the build.
Sometimes a feature request is made to flag unknown headers so that people will
know they should be added to the build. But the silent omission of headers
outside of the current toolchain is an important feature that limits the
necessity of "nogncheck" annotations (see previous question).
In a large project like Chrome, many platform-specific headers will only be
defined in that platform's build (for example, Android-specific headers would
only be listed in the build when compiling for Android). Because the checking
doesn't understand the preprocessor, checking unknown files would flag uses of
these headers even if they were properly guarded by platform conditionals. By
ignoring headers outside of the current toolchain, the "nogncheck" annotations
can be omitted for most platform-specific files.