Add more FAQ entries.
Change-Id: I77f578d2bdb8d84534009519a5de8a87353caa8c
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/12320
Reviewed-by: Petr Hosek <phosek@google.com>
Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/README.md b/README.md
index a581eba..8730fe1 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,14 @@
Related resources:
* Documentation in [docs/](https://gn.googlesource.com/gn/+/main/docs/). In
- particular [GN Quick Start
- guide](https://gn.googlesource.com/gn/+/main/docs/quick_start.md)
- and the [reference](https://gn.googlesource.com/gn/+/main/docs/reference.md)
- (the latter is all builtin help converted to a single file).
+ particular:
+ * [GN quick start guide](https://gn.googlesource.com/gn/+/main/docs/quick_start.md).
+ * [Frequently asked questions](https://gn.googlesource.com/gn/+/main/docs/faq.md)
+ * [Reference](https://gn.googlesource.com/gn/+/main/docs/reference.md)
+ (all builtin help converted to a single file).
* An introductory [presentation](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing).
* The [mailing list](https://groups.google.com/a/chromium.org/forum/#!forum/gn-dev).
+ * The [bug database](https://bugs.chromium.org/p/gn/issues/list).
## What GN is for
diff --git a/docs/faq.md b/docs/faq.md
index 27fead0..059e4dd 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -4,40 +4,20 @@
## 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).
+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 like native ones like GYP could.
+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 generate common build variants?
-
-In GN, args go with a build directory rather than being global in the
-environment. To edit the args for your `out/Default` build directory:
-
-```
-gn args out/Default
-```
-
-You can set variables in that file:
-
- * The default is a debug build. To do a release build add
- `is_debug = false`
- * The default is a static build. To do a component build add
- `is_component_build = true`
- * The default is a developer build. To do an official build, set
- `is_official_build = true`
- * The default is Chromium branding. To do Chrome branding, set
- `is_chrome_branded = true`
-
## How do I do cross-compiles?
GN has robust support for doing cross compiles and building things for
@@ -47,9 +27,9 @@
## 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.
+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?
@@ -57,6 +37,107 @@
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 sometime 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
@@ -89,3 +170,51 @@
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.
+
+## 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.