summaryrefslogtreecommitdiff
path: root/gn/docs/style_guide.md
diff options
context:
space:
mode:
Diffstat (limited to 'gn/docs/style_guide.md')
-rw-r--r--gn/docs/style_guide.md286
1 files changed, 286 insertions, 0 deletions
diff --git a/gn/docs/style_guide.md b/gn/docs/style_guide.md
new file mode 100644
index 00000000000..466f8727e0d
--- /dev/null
+++ b/gn/docs/style_guide.md
@@ -0,0 +1,286 @@
+# GN Style Guide
+
+[TOC]
+
+## Naming and ordering within the file
+
+### Location of build files
+
+It usually makes sense to have more build files closer to the code than
+fewer ones at the top level; this is in contrast with what we did with
+GYP. This makes things easier to find, and also makes the set of owners
+required for reviews smaller since changes are more focused to particular
+subdirectories.
+
+### Targets
+
+ * Most BUILD files should have a target with the same name as the
+ directory. This target should be the first target.
+ * Other targets should be in some logical order -- usually
+ more important targets will be first, and unit tests will follow the
+ corresponding target. If there's no clear ordering, consider
+ alphabetical order.
+ * Test support libraries should be static libraries named "test\_support".
+ For example, "//ui/compositor:test\_support". Test support libraries should
+ include as public deps the non-test-support version of the library
+ so tests need only depend on the test\_support target (rather than
+ both).
+
+Naming advice
+
+ * Targets and configs should be named using lowercase with underscores
+ separating words, unless there is a strong reason to do otherwise.
+ * Source sets, groups, and static libraries do not need globally unique names.
+ Prefer to give such targets short, non-redundant names without worrying
+ about global uniqueness. For example, it looks much better to write a
+ dependency as `"//mojo/public/bindings"` rather than
+ `"//mojo/public/bindings:mojo_bindings"
+ * Shared libraries (and by extension, components) must have globally unique
+ output names. Give such targets short non-unique names above, and then
+ provide a globally unique `output_name` for that target.
+ * Executables and tests should be given a globally unique name. Technically
+ only the output names must be unique, but since only the output names
+ appear in the shell and on bots, it's much less confusing if the name
+ matches the other places the executable appears.
+
+### Configs
+
+ * A config associated with a single target should be named the same as
+ the target with `_config` following it.
+ * A config should appear immediately before the corresponding target
+ that uses it.
+
+### Example
+
+Example for the `src/foo/BUILD.gn` file:
+
+```
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Config for foo is named foo_config and immediately precedes it in the file.
+config("foo_config") {
+}
+
+# Target matching path name is the first target.
+executable("foo") {
+}
+
+# Test for foo follows it.
+test("foo_unittests") {
+}
+
+config("bar_config") {
+}
+
+source_set("bar") {
+}
+```
+
+## Ordering within a target
+
+ 1. `output_name` / `visibility` / `testonly`
+ 2. `sources`
+ 3. `cflags`, `include_dirs`, `defines`, `configs` etc. in whatever
+ order makes sense to you.
+ 4. `public_deps`
+ 5. `deps`
+
+### Conditions
+
+Simple conditions affecting just one variable (e.g. adding a single
+source or adding a flag for one particular OS) can go beneath the
+variable they affect. More complicated conditions affecting more than
+one thing should go at the bottom.
+
+Conditions should be written to minimize the number of conditional blocks.
+
+## Formatting and indenting
+
+GN contains a built-in code formatter which defines the formatting style.
+Some additional notes:
+
+ * Variables are `lower_case_with_underscores`.
+ * Comments should be complete sentences with periods at the end.
+ * Compiler flags and such should always be commented with what they do
+ and why the flag is needed.
+
+### Sources
+
+Prefer to list sources only once. It is OK to conditionally include sources
+rather than listing them all at the top and then conditionally excluding them
+when they don't apply. Conditional inclusion is often clearer since a file is
+only listed once and it's easier to reason about when reading.
+
+```
+ sources = [
+ "main.cc",
+ ]
+ if (use_aura) {
+ sources += [ "thing_aura.cc" ]
+ }
+ if (use_gtk) {
+ sources += [ "thing_gtk.cc" ]
+ }
+```
+
+### Deps
+
+ * Deps should be in alphabetical order.
+ * Deps within the current file should be written first and not
+ qualified with the file name (just `:foo`).
+ * Other deps should always use fully-qualified path names unless
+ relative ones are required for some reason.
+
+```
+ deps = [
+ ":a_thing",
+ ":mystatic",
+ "//foo/bar:other_thing",
+ "//foo/baz:that_thing",
+ ]
+```
+
+### Import
+
+Use fully-qualified paths for imports:
+
+```
+import("//foo/bar/baz.gni") # Even if this file is in the foo/bar directory
+```
+
+## Usage
+
+### Source sets versus static libraries
+
+Source sets and static libraries can be used interchangeably in most cases. If
+you're unsure what to use, a source set is almost never wrong and is less likely
+to cause problems.
+
+Static libraries follow different linking rules. When a static library is
+included in a link, only the object files that contain unresolved symbols will
+be brought into the build. Source sets result in every object file being added
+to the link line of the final binary.
+
+ * If you're eventually linking code into a component, shared library, or
+ loadable module, you normally need to use source sets. This is because
+ object files with no symbols referenced from within the shared library will
+ not be linked into the final library at all. This omission will happen even
+ if that object file has a symbol marked for export that targets dependent
+ on that shared library need. This will result in undefined symbols when
+ linking later targets.
+
+ * Unit tests (and anything else with static initializers with side effects)
+ must use source sets. The gtest TEST macros create static initializers
+ that register the test. But since no code references symbols in the object
+ file, linking a test into a static library and then into a test executable
+ means the tests will get stripped.
+
+ * Static libraries involve duplicating all of the data in the object files
+ that comprise it. This takes more disk space and for certain very large
+ libraries in configurations with very large object files can cause
+ internal limits on the size of static libraries to be exceeded. Source
+ sets do not have this limitation. Some targets switch between source sets
+ and static libraries depending on the build configuration to avoid this
+ problem.
+
+ * Source sets can have no sources, while static libraries will give strange
+ platform-specific errors if they have no sources. If a target has only
+ headers (for include checking purposes) or conditionally has no sources on
+ sone platforms, use a source set.
+
+ * In cases where a lot of the symbols are not needed for a particular link
+ (this especially happens when linking test binaries), putting that code in
+ a static library can dramatically increase linking performance. This is
+ because the object files not needed for the link are never considered in
+ the first place, rather than forcing the linker to strip the unused code
+ in a later pass when nothing references it.
+
+### Loadable modules versus shared libraries versus components
+
+A component is a Chrome primitive (rather than a built-in GN concept) that
+expands either to a shared library or a static library / source set depending
+on the value of the `is_component_build` variable. This allows release builds
+to be linked statically in a large binary, but for developers to use shared
+libraries for most operations.
+
+A shared library will be listed on the link line of dependent targets and will
+be loaded automatically by the operating system when the application starts
+and symbols automatically resolved. A loadable module will not be linked
+directly and the application must manually load it.
+
+On Windows and Linux shared libraries and loadable modules result in the same
+type of file (`.dll` and `.so`, respectively). The only difference is in how
+they are linked to dependent targets. On these platforms, having a `deps`
+dependency on a loadable module is the same as having a `data_deps`
+(non-linked) dependency on a shared library.
+
+On Mac, these targets have different formats: a shared library will generate a
+`.dylib` file and a loadable module will generate a `.so` file.
+
+Use loadable modules for things like plugins. Shared libraries should be
+seldom-used outside of components because most Chrome code is shipped to the
+end-user as a small number of large binaries. In the case of plugin-like
+libraries, it's good practice to use both a loadable module for the target type
+(even for platforms where it doesn't matter) and data deps for targets that
+depend on it so it's clear from both places that how the library will be linked
+and loaded.
+
+## Build arguments
+
+### Scope
+
+Build arguments should be scoped to a unit of behavior, e.g. enabling a feature.
+Typically an argument would be declared in an imported file to share it with
+the subset of the build that could make use of it.
+
+Chrome has many legacy flags in `//build/config/features.gni`,
+`//build/config/ui.gni`. These locations are deprecated. Feature flags should
+go along with the code for the feature. Many browser-level features can go
+somewhere in `//chrome/` without lower-level code knowing about it. Some
+UI environment flags can go into `//ui/`, and many flags can also go with
+the corresponding code in `//components/`. You can write a `.gni` file in
+components and have build files in chrome or content import it if necessary.
+
+The way to think about things in the `//build` directory is that this is
+DEPSed into various projects like V8 and WebRTC. Build flags specific to
+code outside of the build directory shouldn't be in the build directory, and
+V8 shouldn't get feature defines for Chrome features.
+
+New feature defines should use the buildflag system. See
+`//build/buildflag_header.gni` which allows preprocessor defines to be
+modularized without many of the disadvantages that made us use global defines
+in the past.
+
+### Type
+
+Arguments support all the [GN language types](language.md#Language).
+
+In the vast majority of cases `boolean` is the preferred type, since most
+arguments are enabling or disabling features or includes.
+
+`String`s are typically used for filepaths. They are also used for enumerated
+types, though `integer`s are sometimes used as well.
+
+### Naming conventions
+
+While there are no hard and fast rules around argument naming there are
+many common conventions. If you ever want to see the current list of argument
+names and default values for your current checkout use
+`gn args out/Debug --list --short`.
+
+`use_foo` - indicates dependencies or major codepaths to include (e.g.
+`use_open_ssl`, `use_ozone`, `use_cups`)
+
+`enable_foo` - indicates feature or tools to be enabled (e.g.
+`enable_google_now`, `enable_nacl`, `enable_remoting`, `enable_pdf`)
+
+`disable_foo` - _NOT_ recommended, use `enable_foo` instead with swapped default
+value
+
+`is_foo` - usually a global state descriptor (e.g. `is_chrome_branded`,
+`is_desktop_linux`); poor choice for non-globals
+
+`foo_use_bar` - prefixes can be used to indicate a limited scope for an argument
+(e.g. `rtc_use_h264`, `v8_use_snapshot`)