| # GN Quick Start guide | |
| [TOC] | |
| Note: the gn repo has been ported from chromium, and the tutorial within this | |
| document has not yet been updated to reflect this. Building the tutorial files | |
| will require the chromium tree, even though gn is now independent of chromium. | |
| ## Running GN | |
| You just run `gn` from the command line. There is a script in | |
| `depot_tools`, which is presumably in your PATH, with this name. The | |
| script will find the binary in the source tree containing the current | |
| directory and run it. | |
| ## Setting up a build | |
| In GYP, the system would generate `Debug` and `Release` build | |
| directories for you and configure them accordingly. GN doesn't do this. | |
| Instead, you set up whatever build directory you want with whatever | |
| configuration you want. The Ninja files will be automatically | |
| regenerated if they're out of date when you build in that directory. | |
| To make a build directory: | |
| ``` | |
| gn gen out/my_build | |
| ``` | |
| ## Passing build arguments | |
| Set build arguments on your build directory by running: | |
| ``` | |
| gn args out/my_build | |
| ``` | |
| This will bring up an editor. Type build args into that file like this: | |
| ``` | |
| is_component_build = true | |
| is_debug = false | |
| ``` | |
| You can see the list of available arguments and their default values by | |
| typing | |
| ``` | |
| gn args --list out/my_build | |
| ``` | |
| on the command line. Note that you have to specify the build directory | |
| for this command because the available arguments can change according | |
| to what's set. | |
| Chrome developers can also read the [Chrome-specific build | |
| configuration](http://www.chromium.org/developers/gn-build-configuration) | |
| instructions for more information. | |
| ## Cross-compiling to a target OS or architecture | |
| Run `gn args out/Default` (substituting your build directory as needed) and | |
| add one or more of the following lines for common cross-compiling options. | |
| ``` | |
| target_os = "chromeos" | |
| target_os = "android" | |
| target_cpu = "arm" | |
| target_cpu = "x86" | |
| target_cpu = "x64" | |
| ``` | |
| See [GNCrossCompiles](cross_compiles.md) for more info. | |
| ## Configuring goma | |
| Run `gn args out/Default` (substituting your build directory as needed). | |
| Add: | |
| ``` | |
| use_goma = true | |
| goma_dir = "~/foo/bar/goma" | |
| ``` | |
| If your goma is in the default location (`~/goma`) then you can omit the | |
| `goma_dir` line. | |
| ## Configuring component mode | |
| This is a build arg like the goma flags. run `gn args out/Default` and add: | |
| ``` | |
| is_component_build = true | |
| ``` | |
| ## Step-by-step | |
| ### Adding a build file | |
| Create a `tools/gn/tutorial/BUILD.gn` file [in the chromium repo](https://cs.chromium.org/chromium/src/tools/gn/tutorial/) and enter | |
| the following: | |
| ``` | |
| executable("hello_world") { | |
| sources = [ | |
| "hello_world.cc", | |
| ] | |
| } | |
| ``` | |
| There should already be a `hello_world.cc` file in that directory, | |
| containing what you expect. That's it! Now we just need to tell the | |
| build about this file. Open the `BUILD.gn` file in the root directory | |
| and add the label of this target to the dependencies of one of the root | |
| groups (a "group" target is a meta-target that is just a collection of | |
| other targets): | |
| ``` | |
| group("root") { | |
| deps = [ | |
| ... | |
| "//url", | |
| "//tools/gn/tutorial:hello_world", | |
| ] | |
| } | |
| ``` | |
| You can see the label of your target is "//" (indicating the source | |
| root), followed by the directory name, a colon, and the target name. | |
| ### Testing your addition | |
| From the command line in the source root directory: | |
| ``` | |
| gn gen out/Default | |
| ninja -C out/Default hello_world | |
| out/Default/hello_world | |
| ``` | |
| You should see "Hello, world." output to the console. | |
| Side note: GN encourages target names for static libraries that aren't globally | |
| unique. To build one of these, you can pass the label with its path (but no leading | |
| "//") to ninja: | |
| ``` | |
| ninja -C out/Default tools/gn/tutorial:hello_world | |
| ``` | |
| ### Declaring dependencies | |
| Let's make a static library that has a function to say hello to random | |
| people. There is a source file `hello.cc` in that directory which has a | |
| function to do this. Open the `tools/gn/tutorial/BUILD.gn` file and add | |
| the static library to the bottom of the existing file: | |
| ``` | |
| static_library("hello") { | |
| sources = [ | |
| "hello.cc", | |
| ] | |
| } | |
| ``` | |
| Now let's add an executable that depends on this library: | |
| ``` | |
| executable("say_hello") { | |
| sources = [ | |
| "say_hello.cc", | |
| ] | |
| deps = [ | |
| ":hello", | |
| ] | |
| } | |
| ``` | |
| This executable includes one source file and depends on the previous | |
| static library. The static library is referenced by its label in the | |
| `deps`. You could have used the full label `//tools/gn/tutorial:hello` | |
| but if you're referencing a target in the same build file, you can use | |
| the shortcut `:hello`. | |
| ### Test the static library version | |
| From the command line in the source root directory: | |
| ``` | |
| ninja -C out/Default say_hello | |
| out/Default/say_hello | |
| ``` | |
| Note that you **didn't** need to re-run GN. GN will automatically rebuild | |
| the ninja files when any build file has changed. You know this happens | |
| when ninja prints `[1/1] Regenerating ninja files` at the beginning of | |
| execution. | |
| ### Compiler settings | |
| Our hello library has a new feature, the ability to say hello to two | |
| people at once. This feature is controlled by defining `TWO_PEOPLE`. We | |
| can add defines like so: | |
| ``` | |
| static_library("hello") { | |
| sources = [ | |
| "hello.cc", | |
| ] | |
| defines = [ | |
| "TWO_PEOPLE", | |
| ] | |
| } | |
| ``` | |
| ### Putting settings in a config | |
| However, users of the library also need to know about this define, and | |
| putting it in the static library target defines it only for the files | |
| there. If somebody else includes `hello.h`, they won't see the new | |
| definition. To see the new definition, everybody will have to define | |
| `TWO_PEOPLE`. | |
| GN has a concept called a "config" which encapsulates settings. Let's | |
| create one that defines our preprocessor define: | |
| ``` | |
| config("hello_config") { | |
| defines = [ | |
| "TWO_PEOPLE", | |
| ] | |
| } | |
| ``` | |
| To apply these settings to your target, you only need to add the | |
| config's label to the list of configs in the target: | |
| ``` | |
| static_library("hello") { | |
| ... | |
| configs += [ | |
| ":hello_config", | |
| ] | |
| } | |
| ``` | |
| Note that you need "+=" here instead of "=" since the build | |
| configuration has a default set of configs applied to each target that | |
| set up the default build stuff. You want to add to this list rather than | |
| overwrite it. To see the default configs, you can use the `print` | |
| function in the build file or the `desc` command-line subcommand (see | |
| below for examples of both). | |
| ### Dependent configs | |
| This nicely encapsulates our settings, but still requires everybody that | |
| uses our library to set the config on themselves. It would be nice if | |
| everybody that depends on our `hello` library can get this | |
| automatically. Change your library definition to: | |
| ``` | |
| static_library("hello") { | |
| sources = [ | |
| "hello.cc", | |
| ] | |
| all_dependent_configs = [ | |
| ":hello_config" | |
| ] | |
| } | |
| ``` | |
| This applies the `hello_config` to the `hello` target itself, plus all | |
| targets that transitively depend on the current one. Now everybody that | |
| depends on us will get our settings. You can also set `public_configs` | |
| which applies only to targets that directly depend on your target (not | |
| transitively). | |
| Now if you compile and run, you'll see the new version with two people: | |
| ``` | |
| > ninja -C out/Default say_hello | |
| ninja: Entering directory 'out/Default' | |
| [1/1] Regenerating ninja files | |
| [4/4] LINK say_hello | |
| > out/Default/say_hello | |
| Hello, Bill and Joy. | |
| ``` | |
| ## Add a new build argument | |
| You declare which arguments you accept and specify default values via | |
| `declare_args`. | |
| ``` | |
| declare_args() { | |
| enable_teleporter = true | |
| enable_doom_melon = false | |
| } | |
| ``` | |
| See `gn help buildargs` for an overview of how this works. | |
| See `gn help declare_args` for specifics on declaring them. | |
| It is an error to declare a given argument more than once in a given scope, so | |
| care should be used in scoping and naming arguments. | |
| ## Don't know what's going on? | |
| You can run GN in verbose mode to see lots of messages about what it's | |
| doing. Use `-v` for this. | |
| ### Print debugging | |
| There is a `print` command which just writes to stdout: | |
| ``` | |
| static_library("hello") { | |
| ... | |
| print(configs) | |
| } | |
| ``` | |
| This will print all of the configs applying to your target (including | |
| the default ones). | |
| ### The "desc" command | |
| You can run `gn desc <build_dir> <targetname>` to get information about | |
| a given target: | |
| ``` | |
| gn desc out/Default //tools/gn/tutorial:say_hello | |
| ``` | |
| will print out lots of exciting information. You can also print just one | |
| section. Lets say you wanted to know where your `TWO_PEOPLE` define | |
| came from on the `say_hello` target: | |
| ``` | |
| > gn desc out/Default //tools/gn/tutorial:say_hello defines --blame | |
| ...lots of other stuff omitted... | |
| From //tools/gn/tutorial:hello_config | |
| (Added by //tools/gn/tutorial/BUILD.gn:12) | |
| TWO_PEOPLE | |
| ``` | |
| You can see that `TWO_PEOPLE` was defined by a config, and you can also | |
| see the which line caused that config to be applied to your target (in | |
| this case, the `all_dependent_configs` line). | |
| Another particularly interesting variation: | |
| ``` | |
| gn desc out/Default //base:base_i18n deps --tree | |
| ``` | |
| See `gn help desc` for more. | |
| ### Performance | |
| You can see what took a long time by running it with the `--time` command | |
| line flag. This will output a summary of timings for various things. | |
| You can also make a trace of how the build files were executed: | |
| ``` | |
| gn --tracelog=mylog.trace | |
| ``` | |
| and you can load the resulting file in Chrome's `about:tracing` page to | |
| look at everything. |