dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 1 | # GN Quick Start guide |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | ## Running GN |
| 6 | |
| 7 | You just run `gn` from the command line. There is a script in |
Quinten Yearsley | 030b729 | 2017-07-18 16:13:31 +0000 | [diff] [blame] | 8 | `depot_tools`, which is presumably in your PATH, with this name. The |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 9 | script will find the binary in the source tree containing the current |
| 10 | directory and run it. |
| 11 | |
| 12 | ## Setting up a build |
| 13 | |
| 14 | In GYP, the system would generate `Debug` and `Release` build |
| 15 | directories for you and configure them accordingly. GN doesn't do this. |
| 16 | Instead, you set up whatever build directory you want with whatever |
| 17 | configuration you want. The Ninja files will be automatically |
| 18 | regenerated if they're out of date when you build in that directory. |
| 19 | |
| 20 | To make a build directory: |
| 21 | |
| 22 | ``` |
| 23 | gn gen out/my_build |
| 24 | ``` |
| 25 | |
| 26 | ## Passing build arguments |
| 27 | |
| 28 | Set build arguments on your build directory by running: |
| 29 | |
| 30 | ``` |
| 31 | gn args out/my_build |
| 32 | ``` |
| 33 | |
| 34 | This will bring up an editor. Type build args into that file like this: |
| 35 | |
| 36 | ``` |
| 37 | is_component_build = true |
| 38 | is_debug = false |
| 39 | ``` |
| 40 | |
| 41 | You can see the list of available arguments and their default values by |
| 42 | typing |
| 43 | |
| 44 | ``` |
| 45 | gn args --list out/my_build |
| 46 | ``` |
| 47 | |
Quinten Yearsley | 030b729 | 2017-07-18 16:13:31 +0000 | [diff] [blame] | 48 | on the command line. Note that you have to specify the build directory |
| 49 | for this command because the available arguments can change according |
| 50 | to what's set. |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 51 | |
brettw | b6392ef | 2015-09-11 13:09:27 -0700 | [diff] [blame] | 52 | Chrome developers can also read the [Chrome-specific build |
| 53 | configuration](http://www.chromium.org/developers/gn-build-configuration) |
| 54 | instructions for more information. |
| 55 | |
dmazzoni | 6fe6eb9 | 2015-07-16 12:46:05 -0700 | [diff] [blame] | 56 | ## Cross-compiling to a target OS or architecture |
| 57 | |
| 58 | Run `gn args out/Default` (substituting your build directory as needed) and |
| 59 | add one or more of the following lines for common cross-compiling options. |
| 60 | |
| 61 | ``` |
| 62 | target_os = "chromeos" |
| 63 | target_os = "android" |
| 64 | |
| 65 | target_cpu = "arm" |
| 66 | target_cpu = "x86" |
| 67 | target_cpu = "x64" |
| 68 | ``` |
| 69 | |
| 70 | See [GNCrossCompiles](cross_compiles.md) for more info. |
| 71 | |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 72 | ## Configuring goma |
| 73 | |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 74 | Run `gn args out/Default` (substituting your build directory as needed). |
| 75 | Add: |
| 76 | |
| 77 | ``` |
| 78 | use_goma = true |
andybons | 696d847 | 2015-07-30 15:38:01 -0700 | [diff] [blame] | 79 | goma_dir = "~/foo/bar/goma" |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 80 | ``` |
| 81 | |
| 82 | If your goma is in the default location (`~/goma`) then you can omit the |
| 83 | `goma_dir` line. |
| 84 | |
| 85 | ## Configuring component mode |
| 86 | |
| 87 | This is a build arg like the goma flags. run `gn args out/Default` and add: |
| 88 | |
| 89 | ``` |
| 90 | is_component_build = true |
| 91 | ``` |
| 92 | |
| 93 | ## Step-by-step |
| 94 | |
| 95 | ### Adding a build file |
| 96 | |
| 97 | Create a `tools/gn/tutorial/BUILD.gn` file and enter the following: |
| 98 | |
| 99 | ``` |
| 100 | executable("hello_world") { |
| 101 | sources = [ |
| 102 | "hello_world.cc", |
| 103 | ] |
| 104 | } |
| 105 | ``` |
| 106 | |
| 107 | There should already be a `hello_world.cc` file in that directory, |
| 108 | containing what you expect. That's it! Now we just need to tell the |
| 109 | build about this file. Open the `BUILD.gn` file in the root directory |
andybons | 696d847 | 2015-07-30 15:38:01 -0700 | [diff] [blame] | 110 | and add the label of this target to the dependencies of one of the root |
| 111 | groups (a "group" target is a meta-target that is just a collection of |
| 112 | other targets): |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 113 | |
| 114 | ``` |
| 115 | group("root") { |
| 116 | deps = [ |
| 117 | ... |
| 118 | "//url", |
| 119 | "//tools/gn/tutorial:hello_world", |
| 120 | ] |
| 121 | } |
| 122 | ``` |
| 123 | |
| 124 | You can see the label of your target is "//" (indicating the source |
| 125 | root), followed by the directory name, a colon, and the target name. |
| 126 | |
| 127 | ### Testing your addition |
| 128 | |
| 129 | From the command line in the source root directory: |
| 130 | |
| 131 | ``` |
| 132 | gn gen out/Default |
| 133 | ninja -C out/Default hello_world |
| 134 | out/Default/hello_world |
| 135 | ``` |
| 136 | |
| 137 | GN encourages target names for static libraries that aren't globally |
| 138 | unique. To build one of these, you can pass the label with no leading |
| 139 | "//" to ninja: |
| 140 | |
| 141 | ``` |
| 142 | ninja -C out/Default tools/gn/tutorial:hello_world |
| 143 | ``` |
| 144 | |
| 145 | ### Declaring dependencies |
| 146 | |
| 147 | Let's make a static library that has a function to say hello to random |
| 148 | people. There is a source file `hello.cc` in that directory which has a |
| 149 | function to do this. Open the `tools/gn/tutorial/BUILD.gn` file and add |
| 150 | the static library to the bottom of the existing file: |
| 151 | |
| 152 | ``` |
| 153 | static_library("hello") { |
| 154 | sources = [ |
| 155 | "hello.cc", |
| 156 | ] |
| 157 | } |
| 158 | ``` |
| 159 | |
| 160 | Now let's add an executable that depends on this library: |
| 161 | |
| 162 | ``` |
| 163 | executable("say_hello") { |
| 164 | sources = [ |
| 165 | "say_hello.cc", |
| 166 | ] |
| 167 | deps = [ |
| 168 | ":hello", |
| 169 | ] |
| 170 | } |
| 171 | ``` |
| 172 | |
andybons | 696d847 | 2015-07-30 15:38:01 -0700 | [diff] [blame] | 173 | This executable includes one source file and depends on the previous |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 174 | static library. The static library is referenced by its label in the |
| 175 | `deps`. You could have used the full label `//tools/gn/tutorial:hello` |
| 176 | but if you're referencing a target in the same build file, you can use |
| 177 | the shortcut `:hello`. |
| 178 | |
| 179 | ### Test the static library version |
| 180 | |
| 181 | From the command line in the source root directory: |
| 182 | |
| 183 | ``` |
| 184 | ninja -C out/Default say_hello |
| 185 | out/Default/say_hello |
| 186 | ``` |
| 187 | |
andybons | 696d847 | 2015-07-30 15:38:01 -0700 | [diff] [blame] | 188 | Note that you **didn't** need to re-run GN. GN will automatically rebuild |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 189 | the ninja files when any build file has changed. You know this happens |
| 190 | when ninja prints `[1/1] Regenerating ninja files` at the beginning of |
| 191 | execution. |
| 192 | |
| 193 | ### Compiler settings |
| 194 | |
| 195 | Our hello library has a new feature, the ability to say hello to two |
| 196 | people at once. This feature is controlled by defining `TWO_PEOPLE`. We |
| 197 | can add defines like so: |
| 198 | |
| 199 | ``` |
| 200 | static_library("hello") { |
| 201 | sources = [ |
| 202 | "hello.cc", |
| 203 | ] |
| 204 | defines = [ |
| 205 | "TWO_PEOPLE", |
| 206 | ] |
| 207 | } |
| 208 | ``` |
| 209 | |
| 210 | ### Putting settings in a config |
| 211 | |
| 212 | However, users of the library also need to know about this define, and |
| 213 | putting it in the static library target defines it only for the files |
| 214 | there. If somebody else includes `hello.h`, they won't see the new |
| 215 | definition. To see the new definition, everybody will have to define |
| 216 | `TWO_PEOPLE`. |
| 217 | |
| 218 | GN has a concept called a "config" which encapsulates settings. Let's |
| 219 | create one that defines our preprocessor define: |
| 220 | |
| 221 | ``` |
| 222 | config("hello_config") { |
| 223 | defines = [ |
| 224 | "TWO_PEOPLE", |
| 225 | ] |
| 226 | } |
| 227 | ``` |
| 228 | |
| 229 | To apply these settings to your target, you only need to add the |
| 230 | config's label to the list of configs in the target: |
| 231 | |
| 232 | ``` |
| 233 | static_library("hello") { |
| 234 | ... |
| 235 | configs += [ |
| 236 | ":hello_config", |
| 237 | ] |
| 238 | } |
| 239 | ``` |
| 240 | |
| 241 | Note that you need "+=" here instead of "=" since the build |
| 242 | configuration has a default set of configs applied to each target that |
| 243 | set up the default build stuff. You want to add to this list rather than |
| 244 | overwrite it. To see the default configs, you can use the `print` |
| 245 | function in the build file or the `desc` command-line subcommand (see |
| 246 | below for examples of both). |
| 247 | |
| 248 | ### Dependent configs |
| 249 | |
| 250 | This nicely encapsulates our settings, but still requires everybody that |
| 251 | uses our library to set the config on themselves. It would be nice if |
| 252 | everybody that depends on our `hello` library can get this |
| 253 | automatically. Change your library definition to: |
| 254 | |
| 255 | ``` |
| 256 | static_library("hello") { |
| 257 | sources = [ |
| 258 | "hello.cc", |
| 259 | ] |
| 260 | all_dependent_configs = [ |
| 261 | ":hello_config" |
| 262 | ] |
| 263 | } |
| 264 | ``` |
| 265 | |
| 266 | This applies the `hello_config` to the `hello` target itself, plus all |
machenbach | 86f9bc9 | 2016-01-14 07:43:09 -0800 | [diff] [blame] | 267 | targets that transitively depend on the current one. Now everybody that |
| 268 | depends on us will get our settings. You can also set `public_configs` |
| 269 | which applies only to targets that directly depend on your target (not |
| 270 | transitively). |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 271 | |
| 272 | Now if you compile and run, you'll see the new version with two people: |
| 273 | |
| 274 | ``` |
| 275 | > ninja -C out/Default say_hello |
| 276 | ninja: Entering directory 'out/Default' |
| 277 | [1/1] Regenerating ninja files |
| 278 | [4/4] LINK say_hello |
| 279 | > out/Default/say_hello |
andybons | 696d847 | 2015-07-30 15:38:01 -0700 | [diff] [blame] | 280 | Hello, Bill and Joy. |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 281 | ``` |
| 282 | |
jessicag | 2ab4742 | 2016-03-11 11:38:17 -0800 | [diff] [blame] | 283 | ## Add a new build argument |
| 284 | |
| 285 | You declare which arguments you accept and specify default values via |
| 286 | `declare_args`. |
| 287 | |
| 288 | ``` |
| 289 | declare_args() { |
| 290 | enable_teleporter = true |
| 291 | enable_doom_melon = false |
| 292 | } |
| 293 | ``` |
| 294 | |
| 295 | See `gn help buildargs` for an overview of how this works. |
| 296 | See `gn help declare_args` for specifics on declaring them. |
| 297 | |
| 298 | It is an error to declare a given argument more than once in a given scope, so |
| 299 | care should be used in scoping and naming arguments. |
| 300 | |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 301 | ## Don't know what's going on? |
| 302 | |
| 303 | You can run GN in verbose mode to see lots of messages about what it's |
| 304 | doing. Use `-v` for this. |
| 305 | |
| 306 | ### Print debugging |
| 307 | |
| 308 | There is a `print` command which just writes to stdout: |
| 309 | |
| 310 | ``` |
| 311 | static_library("hello") { |
| 312 | ... |
| 313 | print(configs) |
| 314 | } |
| 315 | ``` |
| 316 | |
| 317 | This will print all of the configs applying to your target (including |
| 318 | the default ones). |
| 319 | |
| 320 | ### The "desc" command |
| 321 | |
| 322 | You can run `gn desc <build_dir> <targetname>` to get information about |
| 323 | a given target: |
| 324 | |
| 325 | ``` |
| 326 | gn desc out/Default //tools/gn/tutorial:say_hello |
| 327 | ``` |
| 328 | |
| 329 | will print out lots of exciting information. You can also print just one |
| 330 | section. Lets say you wanted to know where your `TWO_PEOPLE` define |
| 331 | came from on the `say_hello` target: |
| 332 | |
| 333 | ``` |
| 334 | > gn desc out/Default //tools/gn/tutorial:say_hello defines --blame |
| 335 | ...lots of other stuff omitted... |
| 336 | From //tools/gn/tutorial:hello_config |
| 337 | (Added by //tools/gn/tutorial/BUILD.gn:12) |
| 338 | TWO_PEOPLE |
| 339 | ``` |
| 340 | |
| 341 | You can see that `TWO_PEOPLE` was defined by a config, and you can also |
machenbach | 86f9bc9 | 2016-01-14 07:43:09 -0800 | [diff] [blame] | 342 | see the which line caused that config to be applied to your target (in |
dpranke | c04440d | 2015-04-06 11:42:23 -0700 | [diff] [blame] | 343 | this case, the `all_dependent_configs` line). |
| 344 | |
| 345 | Another particularly interesting variation: |
| 346 | |
| 347 | ``` |
| 348 | gn desc out/Default //base:base_i18n deps --tree |
| 349 | ``` |
| 350 | |
| 351 | See `gn help desc` for more. |
| 352 | |
| 353 | ### Performance |
| 354 | |
| 355 | You can see what took a long time by running it with the --time command |
| 356 | line flag. This will output a summary of timings for various things. |
| 357 | |
| 358 | You can also make a trace of how the build files were executed: |
| 359 | |
| 360 | ``` |
| 361 | gn --tracelog=mylog.trace |
| 362 | ``` |
| 363 | |
| 364 | and you can load the resulting file in Chrome's `about:tracing` page to |
| 365 | look at everything. |