| # 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 whitelisted 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`). |