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.