| # GN Language and Operation | |
| [TOC] | |
| ## Introduction | |
| This page describes many of the language details and behaviors. | |
| ### Use the built-in help! | |
| GN has an extensive built-in help system which provides a reference for | |
| every function and built-in variable. This page is more high-level. | |
| ``` | |
| gn help | |
| ``` | |
| You can also see the | |
| [slides](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing) | |
| from a March, 2016 introduction to GN. The speaker notes contain the full | |
| content. | |
| ### Design philosophy | |
| * Writing build files should not be a creative endeavour. Ideally two | |
| people should produce the same buildfile given the same | |
| requirements. There should be no flexibility unless it's absolutely | |
| needed. As many things should be fatal errors as possible. | |
| * The definition should read more like code than rules. I don't want | |
| to write or debug Prolog. But everybody on our team can write and | |
| debug C++ and Python. | |
| * The build language should be opinionated as to how the build should | |
| work. It should not necessarily be easy or even possible to express | |
| arbitrary things. We should be changing source and tooling to make | |
| the build simpler rather than making everything more complicated to | |
| conform to external requirements (within reason). | |
| * Be like Blaze when it makes sense (see "Differences and similarities | |
| to Blaze" below). | |
| ## Language | |
| GN uses an extremely simple, dynamically typed language. The types are: | |
| * Boolean (`true`, `false`). | |
| * 64-bit signed integers. | |
| * Strings. | |
| * Lists (of any other types). | |
| * Scopes (sort of like a dictionary, only for built-in stuff). | |
| There are some built-in variables whose values depend on the current | |
| environment. See `gn help` for more. | |
| There are purposefully many omissions in the language. There are no | |
| user-defined function calls, for example (templates are the closest thing). As | |
| per the above design philosophy, if you need this kind of thing you're probably | |
| doing it wrong. | |
| The full grammar for language nerds is available in `gn help grammar`. | |
| ### Strings | |
| Strings are enclosed in double-quotes and use backslash as the escape | |
| character. The only escape sequences supported are: | |
| * `\"` (for literal quote) | |
| * `\$` (for literal dollars sign) | |
| * `\\` (for literal backslash) | |
| Any other use of a backslash is treated as a literal backslash. So, for | |
| example, `\b` used in patterns does not need to be escaped, nor do most Windows | |
| paths like `"C:\foo\bar.h"`. | |
| Simple variable substitution is supported via `$`, where the word | |
| following the dollars sign is replaced with the value of the variable. | |
| You can optionally surround the name with `{}` if there is not a | |
| non-variable-name character to terminate the variable name. More complex | |
| expressions are not supported, only variable name substitution. | |
| ``` | |
| a = "mypath" | |
| b = "$a/foo.cc" # b -> "mypath/foo.cc" | |
| c = "foo${a}bar.cc" # c -> "foomypathbar.cc" | |
| ``` | |
| You can encode 8-bit characters using "$0xFF" syntax, so a string with newlines | |
| (hex 0A) would `"look$0x0Alike$0x0Athis"`. | |
| ### Lists | |
| Aside from telling empty lists from non empty lists (`a == []`), there is no | |
| way to get the length of a list. If you find yourself wanting to do this kind | |
| of thing, you're trying to do too much work in the build. | |
| Lists support appending: | |
| ``` | |
| a = [ "first" ] | |
| a += [ "second" ] # [ "first", "second" ] | |
| a += [ "third", "fourth" ] # [ "first", "second", "third", "fourth" ] | |
| b = a + [ "fifth" ] # [ "first", "second", "third", "fourth", "fifth" ] | |
| ``` | |
| Appending a list to another list appends the items in the second list | |
| rather than appending the list as a nested member. | |
| You can remove items from a list: | |
| ``` | |
| a = [ "first", "second", "third", "first" ] | |
| b = a - [ "first" ] # [ "second", "third" ] | |
| a -= [ "second" ] # [ "first", "third", "first" ] | |
| ``` | |
| The - operator on a list searches for matches and removes all matching | |
| items. Subtracting a list from another list will remove each item in the | |
| second list. | |
| If no matching items are found, an error will be thrown, so you need to | |
| know in advance that the item is there before removing it. Given that | |
| there is no way to test for inclusion, the main use-case is to set up a | |
| master list of files or flags, and to remove ones that don't apply to | |
| the current build based on various conditions. | |
| Stylistically, prefer to only add to lists and have each source file or | |
| dependency appear once. This is the opposite of the advice Chrome-team used to | |
| give for GYP (GYP would prefer to list all files, and then remove the ones you | |
| didn't want in conditionals). | |
| Lists support zero-based subscripting to extract values: | |
| ``` | |
| a = [ "first", "second", "third" ] | |
| b = a[1] # -> "second" | |
| ``` | |
| The \[\] operator is read-only and can not be used to mutate the | |
| list. The primary use-case of this is when an external script returns | |
| several known values and you want to extract them. | |
| There are some cases where it's easy to overwrite a list when you mean | |
| to append to it instead. To help catch this case, it is an error to | |
| assign a nonempty list to a variable containing an existing nonempty | |
| list. If you want to get around this restriction, first assign the | |
| destination variable to the empty list. | |
| ``` | |
| a = [ "one" ] | |
| a = [ "two" ] # Error: overwriting nonempty list with a nonempty list. | |
| a = [] # OK | |
| a = [ "two" ] # OK | |
| ``` | |
| Note that execution of the build script is done without intrinsic | |
| knowledge of the meaning of the underlying data. This means that it | |
| doesn't know that `sources` is a list of file names, for example. So if | |
| you remove an item, it must match the literal string rather than | |
| specifying a different name that will resolve to the same file name. | |
| ### Conditionals | |
| Conditionals look like C: | |
| ``` | |
| if (is_linux || (is_win && target_cpu == "x86")) { | |
| sources -= [ "something.cc" ] | |
| } else if (...) { | |
| ... | |
| } else { | |
| ... | |
| } | |
| ``` | |
| You can use them in most places, even around entire targets if the | |
| target should only be declared in certain circumstances. | |
| ### Looping | |
| You can iterate over a list with `foreach`. This is discouraged. Most things | |
| the build should do can normally be expressed without doing this, and if you | |
| find it necessary it may be an indication you're doing too much work in the | |
| metabuild. | |
| ``` | |
| foreach(i, mylist) { | |
| print(i) # Note: i is a copy of each element, not a reference to it. | |
| } | |
| ``` | |
| ### Function calls | |
| Simple function calls look like most other languages: | |
| ``` | |
| print("hello, world") | |
| assert(is_win, "This should only be executed on Windows") | |
| ``` | |
| Such functions are built-in and the user can not define new ones. | |
| Some functions take a block of code enclosed by `{ }` following them: | |
| ``` | |
| static_library("mylibrary") { | |
| sources = [ "a.cc" ] | |
| } | |
| ``` | |
| Most of these define targets. The user can define new functions like this | |
| with the template mechanism discussed below. | |
| Precisely, this expression means that the block becomes an argument to the | |
| function for the function to execute. Most of the block-style functions execute | |
| the block and treat the resulting scope as a dictionary of variables to read. | |
| ### Scoping and execution | |
| Files and function calls followed by `{ }` blocks introduce new scopes. Scopes | |
| are nested. When you read a variable, the containing scopes will be searched in | |
| reverse order until a matching name is found. Variable writes always go to the | |
| innermost scope. | |
| There is no way to modify any enclosing scope other than the innermost | |
| one. This means that when you define a target, for example, nothing you | |
| do inside of the block will "leak out" into the rest of the file. | |
| `if`/`else`/`foreach` statements, even though they use `{ }`, do not introduce | |
| a new scope so changes will persist outside of the statement. | |
| ## Naming things | |
| ### File and directory names | |
| File and directory names are strings and are interpreted as relative to | |
| the current build file's directory. There are three possible forms: | |
| Relative names: | |
| ``` | |
| "foo.cc" | |
| "src/foo.cc" | |
| "../src/foo.cc" | |
| ``` | |
| Source-tree absolute names: | |
| ``` | |
| "//net/foo.cc" | |
| "//base/test/foo.cc" | |
| ``` | |
| System absolute names (rare, normally used for include directories): | |
| ``` | |
| "/usr/local/include/" | |
| "/C:/Program Files/Windows Kits/Include" | |
| ``` | |
| ## Build configuration | |
| ## Targets | |
| A target is a node in the build graph. It usually represents some kind | |
| of executable or library file that will be generated. Targets depend on | |
| other targets. The built-in target types (see `gn help <targettype>` for | |
| more help) are: | |
| * `action`: Run a script to generate a file. | |
| * `action_foreach`: Run a script once for each source file. | |
| * `bundle_data`: Declare data to go into a Mac/iOS bundle. | |
| * `create_bundle`: Creates a Mac/iOS bundle. | |
| * `executable`: Generates an executable file. | |
| * `group`: A virtual dependency node that refers to one or more other | |
| targets. | |
| * `shared_library`: A .dll or .so. | |
| * `loadable_module`: A .dll or .so loadable only at runtime. | |
| * `source_set`: A lightweight virtual static library (usually | |
| preferrable over a real static library since it will build faster). | |
| * `static_library`: A .lib or .a file (normally you'll want a | |
| `source_set` instead). | |
| You can extend this to make custom target types using templates (see below). In | |
| Chrome some of the more commonly-used templates are: | |
| * `component`: Either a source set or shared library, depending on the | |
| build type. | |
| * `test`: A test executable. On mobile this will create the appropriate | |
| native app type for tests. | |
| * `app`: Executable or Mac/iOS application. | |
| * `android_apk`: Make an APK. There are a _lot_ of other Android ones, see | |
| `//build/config/android/rules.gni`. | |
| ## Configs | |
| Configs are named objects that specify sets of flags, include | |
| directories, and defines. They can be applied to a target and pushed to | |
| dependent targets. | |
| To define a config: | |
| ``` | |
| config("myconfig") { | |
| includes = [ "src/include" ] | |
| defines = [ "ENABLE_DOOM_MELON" ] | |
| } | |
| ``` | |
| To apply a config to a target: | |
| ``` | |
| executable("doom_melon") { | |
| configs = [ ":myconfig" ] | |
| } | |
| ``` | |
| It is common for the build config file to specify target defaults that | |
| set a default list of configs. Targets can add or remove to this list as | |
| needed. So in practice you would usually use `configs += ":myconfig"` to | |
| append to the list of defaults. | |
| See `gn help config` for more information about how configs are declared | |
| and applied. | |
| ### Public configs | |
| A target can apply settings to other targets that depend on it. The most | |
| common example is a third party target that requires some defines or | |
| include directories for its headers to compile properly. You want these | |
| settings to apply both to the compile of the third party library itself, | |
| as well as all targets that use the library. | |
| To do this, you write a config with the settings you want to apply: | |
| ``` | |
| config("my_external_library_config") { | |
| includes = "." | |
| defines = [ "DISABLE_JANK" ] | |
| } | |
| ``` | |
| Then this config is added to the target as a "public" config. It will | |
| apply both to the target as well as targets that directly depend on it. | |
| ``` | |
| shared_library("my_external_library") { | |
| ... | |
| # Targets that depend on this get this config applied. | |
| public_configs = [ ":my_external_library_config" ] | |
| } | |
| ``` | |
| Dependent targets can in turn forward this up the dependency tree | |
| another level by adding your target as a "public" dependency. | |
| ``` | |
| static_library("intermediate_library") { | |
| ... | |
| # Targets that depend on this one also get the configs from "my external library". | |
| public_deps = [ ":my_external_library" ] | |
| } | |
| ``` | |
| A target can forward a config to all dependents until a link boundary is | |
| reached by setting it as an `all_dependent_config`. This is strongly | |
| discouraged as it can spray flags and defines over more of the build than | |
| necessary. Instead, use public_deps to control which flags apply where. | |
| In Chrome, prefer the build flag header system (`build/buildflag_header.gni`) | |
| for defines which prevents most screw-ups with compiler defines. | |
| ## Templates | |
| Templates are GN's primary way to re-use code. Typically, a template | |
| would expand to one or more other target types. | |
| ``` | |
| # Declares a script that compiles IDL files to source, and then compiles those | |
| # source files. | |
| template("idl") { | |
| # Always base helper targets on target_name so they're unique. Target name | |
| # will be the string passed as the name when the template is invoked. | |
| idl_target_name = "${target_name}_generate" | |
| action_foreach(idl_target_name) { | |
| ... | |
| } | |
| # Your template should always define a target with the name target_name. | |
| # When other targets depend on your template invocation, this will be the | |
| # destination of that dependency. | |
| source_set(target_name) { | |
| ... | |
| deps = [ ":$idl_target_name" ] # Require the sources to be compiled. | |
| } | |
| } | |
| ``` | |
| Typically your template definition would go in a `.gni` file and users | |
| would import that file to see the template definition: | |
| ``` | |
| import("//tools/idl_compiler.gni") | |
| idl("my_interfaces") { | |
| sources = [ "a.idl", "b.idl" ] | |
| } | |
| ``` | |
| Declaring a template creates a closure around the variables in scope at | |
| that time. When the template is invoked, the magic variable `invoker` is | |
| used to read variables out of the invoking scope. The template would | |
| generally copy the values its interested in into its own scope: | |
| ``` | |
| template("idl") { | |
| source_set(target_name) { | |
| sources = invoker.sources | |
| } | |
| } | |
| ``` | |
| The current directory when a template executes will be that of the | |
| invoking build file rather than the template source file. This is so | |
| files passed in from the template invoker will be correct (this | |
| generally accounts for most file handling in a template). However, if | |
| the template has files itself (perhaps it generates an action that runs | |
| a script), you will want to use absolute paths ("//foo/...") to refer to | |
| these files to account for the fact that the current directory will be | |
| unpredictable during invocation. See `gn help template` for more | |
| information and more complete examples. | |
| ## Other features | |
| ### Imports | |
| You can import `.gni` files into the current scope with the `import` | |
| function. This is _not_ an include in the C++ sense. The imported file is | |
| executed independently and the resulting scope is copied into the current file | |
| (C++ executes the included file in the current context of when the | |
| include directive appeared). This allows the results of the import to be | |
| cached, and also prevents some of the more "creative" uses of includes like | |
| multiply-included files. | |
| Typically, a `.gni` would define build arguments and templates. See `gn | |
| help import` for more. | |
| Your `.gni` file can define temporary variables that are not exported files | |
| that include it by using a preceding underscore in the name like `_this`. | |
| ### Path processing | |
| Often you will want to make a file name or a list of file names relative | |
| to a different directory. This is especially common when running | |
| scripts, which are executed with the build output directory as the | |
| current directory, while build files usually refer to files relative to | |
| their containing directory. | |
| You can use `rebase_path` to convert directories. See `gn help | |
| rebase_path` for more help and examples. Typical usage to convert a file | |
| name relative to the current directory to be relative to the root build | |
| directory would be: ``` new_paths = rebase_path("myfile.c", | |
| root_build_dir) ``` | |
| ### Patterns | |
| Patterns are used to generate the output file names for a given set of | |
| inputs for custom target types, and to automatically remove files from | |
| the list values (see `gn help filter_include` and `gn help filter_exclude`). | |
| They are like simple regular expressions. See `gn help label_pattern` | |
| for more. | |
| ### Executing scripts | |
| There are two ways to execute scripts. All external scripts in GN are in | |
| Python. The first way is as a build step. Such a script would take some | |
| input and generate some output as part of the build. Targets that invoke | |
| scripts are declared with the "action" target type (see `gn help | |
| action`). | |
| The second way to execute scripts is synchronously during build file | |
| execution. This is necessary in some cases to determine the set of files | |
| to compile, or to get certain system configurations that the build file | |
| might depend on. The build file can read the stdout of the script and | |
| act on it in different ways. | |
| Synchronous script execution is done by the `exec_script` function (see | |
| `gn help exec_script` for details and examples). Because synchronously | |
| executing a script requires that the current buildfile execution be | |
| suspended until a Python process completes execution, relying on | |
| external scripts is slow and should be minimized. | |
| To prevent abuse, files permitted to call `exec_script` can be allowlisted in | |
| the toplevel `.gn` file. Chrome does this to require additional code review | |
| for such additions. See `gn help dotfile`. | |
| You can synchronously read and write files which is discouraged but | |
| occasionally necessary when synchronously running scripts. The typical use-case | |
| would be to pass a list of file names longer than the command-line limits of | |
| the current platform. See `gn help read_file` and `gn help write_file` for how | |
| to read and write files. These functions should be avoided if at all possible. | |
| Actions that exceed command-line length limits can use response files to | |
| get around this limitation without synchronously writing files. See | |
| `gn help response_file_contents`. | |
| # Differences and similarities to Blaze | |
| Blaze is Google's internal build system, now publicly released as | |
| [Bazel](http://bazel.io/). It has inspired a number of other systems such as | |
| [Pants](http://www.pantsbuild.org/) and [Buck](http://facebook.github.io/buck/). | |
| In Google's homogeneous environment, the need for conditionals is very | |
| low and they can get by with a few hacks (`abi_deps`). Chrome uses | |
| conditionals all over the place and the need to add these is the main | |
| reason for the files looking different. | |
| GN also adds the concept of "configs" to manage some of the trickier | |
| dependency and configuration problems which likewise don't arise on the | |
| server. Blaze has a concept of a "configuration" which is like a GN | |
| toolchain, but built into the tool itself. The way that toolchains work | |
| in GN is a result of trying to separate this concept out into the build | |
| files in a clean way. | |
| GN keeps some GYP concept like "all dependent" settings which work a bit | |
| differently in Blaze. This is partially to make conversion from the existing | |
| GYP code easier, and the GYP constructs generally offer more fine-grained | |
| control (which is either good or bad, depending on the situation). | |
| GN also uses GYP names like "sources" instead of "srcs" since | |
| abbreviating this seems needlessly obscure, although it uses Blaze's | |
| "deps" since "dependencies" is so hard to type. Chromium also compiles | |
| multiple languages in one target so specifying the language type on the | |
| target name prefix was dropped (e.g. from `cc_library`). |