GN style guide on static_libs and source_sets

Updates usage advice on static libraries and source sets, and adds new advice
on using shared libraries and loadable modules.

Review-Url: https://codereview.chromium.org/2076703002
Cr-Original-Commit-Position: refs/heads/master@{#400257}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 9ac2fda6cf5a17902fbb42013e4137e219fb7901
diff --git a/tools/gn/docs/style_guide.md b/tools/gn/docs/style_guide.md
index cdb04ff..29d6b31 100644
--- a/tools/gn/docs/style_guide.md
+++ b/tools/gn/docs/style_guide.md
@@ -18,7 +18,7 @@
     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 source sets named "test\_support".
+  * Test support libraries should be static libraries named "test\_support".
     So "//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
@@ -53,7 +53,7 @@
 Example for the `src/foo/BUILD.gn` file:
 
 ```
-# Copyright 2013 The Chromium Authors. All rights reserved.
+# 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.
 
@@ -150,10 +150,75 @@
 
 ## Usage
 
-Use `source_set` rather than `static_library` unless you have a reason
-to do otherwise. A static library is a standalone library which can be
-slow to generate. A source set just links all the object files from that
-target into the targets depending on it, which saves the "lib" step.
+### 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 dependant
+    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.
+
+  * 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 dependant 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 dependant 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