View on GitHub

Prelude

A path through the jungle of Chromium source

GN 101

Previously, we demonstrated how to build Prelude with just a few commands. However, to truly be able to reuse Chromium code, you need to learn a bit more about the build system - GN. GN is a command line tool similar to git. It supports several sub-commands, such as gen, args used before. GN works with build files named BUILD.gn whose syntax is similar to Python, in which defines targets to be built with GN jargon, e.g., bundle_data, config.

Basic

Using GN is to write a number of BUILD.gn files organized in a tree-like structure. Here’s a quick starter from Chromium.

To get our hands dirty, let’s play with hello_bogart executable, which spits out the following when executed:

Hello, Bogart.
Woof Woof
ou-ooooooo
whif whif

Open the BUILD.gn under hello_puppy directory, it shows four types of built-in targets:

Take the executable target for example:

executable("hello_puppy") {
  output_name = "hello_bogart"
  sources = ["hello_bogart.cpp", ]
  deps = [
    ":bark_food",
    ":bark_ambulance",
  ]
}

*sources specifies all the source files to be compiled. *output_name tells GN that the output binary should be named “hello_bogart” instead of the target name “hello_puppy” by default. *deps lists all the libraries (or targets) required to build the binary.

Pay attention to how the executable specify the targets it depends on: ":bark_food". The format :target_name is used to point to the target within the same BUILD.gn file. There are three ways to refer a target:

Label type Example Meaning
Implicit label //base short for //base:base, look for target “base” in //base/BUILD.gn
Full label //chrome/browser:version look for target “version” in //chrome/browser/BUILD.gn
Local label :foo look for target “foo” within the same file

In the shared library target, defines is used to store the list of preprocessor defines:

shared_library("bark_ambulance") {
  sources = [
    "bark_ambulance.cpp",
  ]
  defines = [ "HOWL_IMPLEMENTATION" ]
}

Here, HOWL_IMPLEMENTATION is defined, which is used in c++ code bark_ambulance.h

#if defined(HOWL_IMPLEMENTATION)
#define HOWL_EXPORT __declspec(dllexport)
#define HOWL_EXPORT_PRIVATE __declspec(dllexport)
#else
#define HOWL_EXPORT __declspec(dllimport)
#define HOWL_EXPORT_PRIVATE __declspec(dllimport)
#endif  // defined(HOWL_IMPLEMENTATION)

This BUILD.gn file contains all the instructions required to build the executable. However, it alone does not “trigger” the build because it’s just a “leaf” in the build tree.

build tree

Take a look at the figure above, there is a BUILD.gn file at each level from root directory all the way to the folder that contains the source files. When we run gn gen, GN goes through all BUILD.gn files starting from the top level, pick up all the targets defined in there, then move to the next level recursively. For simplicity, all non-leaf BUILD.gn files in this example only define one built-in target - group.

group conceptually is equivalent to the shortcut or symbolic link in OS. It contains nothing but a point to a set of dependencies, causing those targets to be picked up for the build. In the figure above, the chain of targets is highlighted in red. The root build file (//BUILD.gn) depends on "//prelude". This means gn expects there will be a //prelude/BUILD.gn file, which defines a target named "prelude". // always point to the root directory in GN.

In //prelude/BUILD.gn, it depends on a target "excerpt01_gn". This tells gn there is a subdirectory named "excerpt01_gn" under //prelude. excerpt01_gn subdirectory also has a BUILD.gn file which defines a target named “excerpt01_gn”.

Assume the build directory specified is out/debug, the intermediate outputs can be found in out/debug/obj/prelude/excerpt01_gn/hello_puppy directory:

hellO puppy intermediate output

“bark_food” is built as a static library, so a bark_food.lib is generated. “sleep_run” is built as a source set, which does not generate a .lib file.

Advanced features

GN is a huge topic on its own. Frequently you may run into unknowns when browsing BUILD.gn files. The easiest way to find the answer is to use GN’s help command. For example, you see the word template for the first time and want to know what it does. Go to the root directory and type:

gn help template

Another useful resource highly recommended is this presentation by Brett Wilson. It covers advanced topics such as toolchain, as well as many useful tricks for daily tasks, such as how to find out where is an argument set in the build tree. Hopefully, these materials will get you started with GN and keep getting more comfortable with GN by using it.

Home