Add more documentation for GN header checking

Several people have been confused how the header checker works. This
significantly expands the documentation.

Review URL: https://codereview.chromium.org/1820493002

Cr-Original-Commit-Position: refs/heads/master@{#382106}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: b24c0792cfe4babd048c7ba1d8031b4fd497a811
diff --git a/tools/gn/command_check.cc b/tools/gn/command_check.cc
index 9f89dc0..40931a6 100644
--- a/tools/gn/command_check.cc
+++ b/tools/gn/command_check.cc
@@ -16,12 +16,51 @@
 
 namespace commands {
 
+const char kNoGnCheck_Help[] =
+    "nogncheck: Skip an include line from checking.\n"
+    "\n"
+    "  GN's header checker helps validate that the includes match the build\n"
+    "  dependency graph. Sometimes an include might be conditional or\n"
+    "  otherwise problematic, but you want to specifically allow it. In this\n"
+    "  case, it can be whitelisted.\n"
+    "\n"
+    "  Include lines containing the substring \"nogncheck\" will be excluded\n"
+    "  from header checking. The most common case is a conditional include:\n"
+    "\n"
+    "    #if defined(ENABLE_DOOM_MELON)\n"
+    "    #include \"tools/doom_melon/doom_melon.h\"  // nogncheck\n"
+    "    #endif\n"
+    "\n"
+    "  If the build file has a conditional dependency on the corresponding\n"
+    "  target that matches the conditional include, everything will always\n"
+    "  link correctly:\n"
+    "\n"
+    "    source_set(\"mytarget\") {\n"
+    "      ...\n"
+    "      if (enable_doom_melon) {\n"
+    "        defines = [ \"ENABLE_DOOM_MELON\" ]\n"
+    "        deps += [ \"//tools/doom_melon\" ]\n"
+    "      }\n"
+    "\n"
+    "  But GN's header checker does not understand preprocessor directives,\n"
+    "  won't know it matches the build dependencies, and will flag this\n"
+    "  include as incorrect when the condition is false.\n"
+    "\n"
+    "More information\n"
+    "\n"
+    "  The topic \"gn help check\" has general information on how checking\n"
+    "  works and advice on fixing problems. Targets can also opt-out of\n"
+    "  checking, see \"gn help check_includes\".\n";
+
 const char kCheck[] = "check";
 const char kCheck_HelpShort[] =
     "check: Check header dependencies.";
 const char kCheck_Help[] =
     "gn check <out_dir> [<label_pattern>] [--force]\n"
     "\n"
+    "  GN's include header checker validates that the includes for C-like\n"
+    "  source files match the build dependency graph.\n"
+    "\n"
     "  \"gn check\" is the same thing as \"gn gen\" with the \"--check\" flag\n"
     "  except that this command does not write out any build files. It's\n"
     "  intended to be an easy way to manually trigger include file checking.\n"
@@ -31,17 +70,94 @@
     "  only those matching targets will be checked. See\n"
     "  \"gn help label_pattern\" for details.\n"
     "\n"
-    "  The .gn file may specify a list of targets to be checked. Only these\n"
-    "  targets will be checked if no label_pattern is specified on the\n"
-    "  command line. Otherwise, the command-line list is used instead. See\n"
-    "  \"gn help dotfile\".\n"
-    "\n"
     "Command-specific switches\n"
     "\n"
     "  --force\n"
     "      Ignores specifications of \"check_includes = false\" and checks\n"
     "      all target's files that match the target label.\n"
     "\n"
+    "What gets checked\n"
+    "\n"
+    "  The .gn file may specify a list of targets to be checked. Only these\n"
+    "  targets will be checked if no label_pattern is specified on the\n"
+    "  command line. Otherwise, the command-line list is used instead. See\n"
+    "  \"gn help dotfile\".\n"
+    "\n"
+    "  Targets can opt-out from checking with \"check_includes = false\"\n"
+    "  (see \"gn help check_includes\").\n"
+    "\n"
+    "  For targets being checked:\n"
+    "\n"
+    "    - GN opens all C-like source files in the targets to be checked and\n"
+    "      scans the top for includes.\n"
+    "\n"
+    "    - Includes with a \"nogncheck\" annotation are skipped (see\n"
+    "      \"gn help nogncheck\").\n"
+    "\n"
+    "    - Only includes using \"quotes\" are checked. <brackets> are assumed\n"
+    "      to be system includes.\n"
+    "\n"
+    "    - Include paths are assumed to be relative to either the source root\n"
+    "      or the \"root_gen_dir\" and must include all the path components.\n"
+    "      (It might be nice in the future to incorporate GN's knowledge of\n"
+    "      the include path to handle other include styles.)\n"
+    "\n"
+    "    - GN does not run the preprocessor so will not understand\n"
+    "      conditional includes.\n"
+    "\n"
+    "    - Only includes matching known files in the build are checked:\n"
+    "      includes matching unknown paths are ignored.\n"
+    "\n"
+    "  For an include to be valid:\n"
+    "\n"
+    "    - The included file must be in the current target, or there must\n"
+    "      be a path following only public dependencies to a target with the\n"
+    "      file in it (\"gn path\" is a good way to diagnose problems).\n"
+    "\n"
+    "    - There can be multiple targets with an included file: only one\n"
+    "      needs to be valid for the include to be allowed.\n"
+    "\n"
+    "    - If there are only \"sources\" in a target, all are considered to\n"
+    "      be public and can be included by other targets with a valid public\n"
+    "      dependency path.\n"
+    "\n"
+    "    - If a target lists files as \"public\", only those files are\n"
+    "      able to be included by other targets. Anything in the sources\n"
+    "      will be considered private and will not be includable regardless\n"
+    "      of dependency paths.\n"
+    "\n"
+    "    - Ouptuts from actions are treated like public sources on that\n"
+    "      target.\n"
+    "\n"
+    "    - A target can include headers from a target that depends on it\n"
+    "      if the other target is annotated accordingly. See\n"
+    "      \"gn help allow_circular_includes_from\".\n"
+    "\n"
+    "Advice on fixing problems\n"
+    "\n"
+    "  If you have a third party project that uses relative includes,\n"
+    "  it's generally best to exclude that target from checking altogether\n"
+    "  via \"check_includes = false\".\n"
+    "\n"
+    "  If you have conditional includes, make sure the build conditions\n"
+    "  and the preprocessor conditions match, and annotate the line with\n"
+    "  \"nogncheck\" (see \"gn help nogncheck\" for an example).\n"
+    "\n"
+    "  If two targets are hopelessly intertwined, use the\n"
+    "  \"allow_circular_includes_from\" annotation. Ideally each should have\n"
+    "  identical dependencies so configs inherited from those dependencies\n"
+    "  are consistent (see \"gn help allow_circular_includes_from\").\n"
+    "\n"
+    "  If you have a standalone header file or files that need to be shared\n"
+    "  between a few targets, you can consider making a source_set listing\n"
+    "  only those headers as public sources. With only header files, the\n"
+    "  source set will be a no-op from a build perspective, but will give a\n"
+    "  central place to refer to those headers. That source set's files\n"
+    "  will still need to pass \"gn check\" in isolation.\n"
+    "\n"
+    "  In rare cases it makes sense to list a header in more than one\n"
+    "  target if it could be considered conceptually a member of both.\n"
+    "\n"
     "Examples\n"
     "\n"
     "  gn check out/Debug\n"
diff --git a/tools/gn/command_help.cc b/tools/gn/command_help.cc
index a486a72..8c1659b 100644
--- a/tools/gn/command_help.cc
+++ b/tools/gn/command_help.cc
@@ -66,6 +66,7 @@
   PrintShortHelp(
       "input_conversion: Processing input from exec_script and read_file.");
   PrintShortHelp("label_pattern: Matching more than one label.");
+  PrintShortHelp("nogncheck: Annotating includes for checking.");
   PrintShortHelp("runtime_deps: How runtime dependency computation works.");
   PrintShortHelp("source_expansion: Map sources to outputs for scripts.");
   PrintShortHelp("switches: Show available command-line switches.");
@@ -126,6 +127,7 @@
   PrintLongHelp(kGrammar_Help);
   PrintLongHelp(kInputConversion_Help);
   PrintLongHelp(kLabelPattern_Help);
+  PrintLongHelp(kNoGnCheck_Help);
   PrintLongHelp(kRuntimeDeps_Help);
   PrintLongHelp(kSourceExpansion_Help);
   PrintSwitchHelp();
@@ -231,6 +233,7 @@
     PrintLongHelp(kInputConversion_Help);
   };
   random_topics["label_pattern"] = []() { PrintLongHelp(kLabelPattern_Help); };
+  random_topics["nogncheck"] = []() { PrintLongHelp(kNoGnCheck_Help); };
   random_topics["runtime_deps"] = []() { PrintLongHelp(kRuntimeDeps_Help); };
   random_topics["source_expansion"] = []() {
     PrintLongHelp(kSourceExpansion_Help);
diff --git a/tools/gn/commands.h b/tools/gn/commands.h
index ca4b0f2..9d8af5c 100644
--- a/tools/gn/commands.h
+++ b/tools/gn/commands.h
@@ -176,6 +176,9 @@
 void FilterAndPrintTargetSet(bool indent,
                              const std::set<const Target*>& targets);
 
+// Extra help from command_check.cc
+extern const char kNoGnCheck_Help[];
+
 }  // namespace commands
 
 #endif  // TOOLS_GN_COMMANDS_H_
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index 6edacfc..f136a97 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -281,6 +281,9 @@
 ## **gn check <out_dir> [<label_pattern>] [\--force]**
 
 ```
+  GN's include header checker validates that the includes for C-like
+  source files match the build dependency graph.
+
   "gn check" is the same thing as "gn gen" with the "--check" flag
   except that this command does not write out any build files. It's
   intended to be an easy way to manually trigger include file checking.
@@ -290,11 +293,6 @@
   only those matching targets will be checked. See
   "gn help label_pattern" for details.
 
-  The .gn file may specify a list of targets to be checked. Only these
-  targets will be checked if no label_pattern is specified on the
-  command line. Otherwise, the command-line list is used instead. See
-  "gn help dotfile".
-
 ```
 
 ### **Command-specific switches**
@@ -306,6 +304,94 @@
 
 ```
 
+### **What gets checked**
+
+```
+  The .gn file may specify a list of targets to be checked. Only these
+  targets will be checked if no label_pattern is specified on the
+  command line. Otherwise, the command-line list is used instead. See
+  "gn help dotfile".
+
+  Targets can opt-out from checking with "check_includes = false"
+  (see "gn help check_includes").
+
+  For targets being checked:
+
+    - GN opens all C-like source files in the targets to be checked and
+      scans the top for includes.
+
+    - Includes with a "nogncheck" annotation are skipped (see
+      "gn help nogncheck").
+
+    - Only includes using "quotes" are checked. <brackets> are assumed
+      to be system includes.
+
+    - Include paths are assumed to be relative to either the source root
+      or the "root_gen_dir" and must include all the path components.
+      (It might be nice in the future to incorporate GN's knowledge of
+      the include path to handle other include styles.)
+
+    - GN does not run the preprocessor so will not understand
+      conditional includes.
+
+    - Only includes matching known files in the build are checked:
+      includes matching unknown paths are ignored.
+
+  For an include to be valid:
+
+    - The included file must be in the current target, or there must
+      be a path following only public dependencies to a target with the
+      file in it ("gn path" is a good way to diagnose problems).
+
+    - There can be multiple targets with an included file: only one
+      needs to be valid for the include to be allowed.
+
+    - If there are only "sources" in a target, all are considered to
+      be public and can be included by other targets with a valid public
+      dependency path.
+
+    - If a target lists files as "public", only those files are
+      able to be included by other targets. Anything in the sources
+      will be considered private and will not be includable regardless
+      of dependency paths.
+
+    - Ouptuts from actions are treated like public sources on that
+      target.
+
+    - A target can include headers from a target that depends on it
+      if the other target is annotated accordingly. See
+      "gn help allow_circular_includes_from".
+
+```
+
+### **Advice on fixing problems**
+
+```
+  If you have a third party project that uses relative includes,
+  it's generally best to exclude that target from checking altogether
+  via "check_includes = false".
+
+  If you have conditional includes, make sure the build conditions
+  and the preprocessor conditions match, and annotate the line with
+  "nogncheck" (see "gn help nogncheck" for an example).
+
+  If two targets are hopelessly intertwined, use the
+  "allow_circular_includes_from" annotation. Ideally each should have
+  identical dependencies so configs inherited from those dependencies
+  are consistent (see "gn help allow_circular_includes_from").
+
+  If you have a standalone header file or files that need to be shared
+  between a few targets, you can consider making a source_set listing
+  only those headers as public sources. With only header files, the
+  source set will be a no-op from a build perspective, but will give a
+  central place to refer to those headers. That source set's files
+  will still need to pass "gn check" in isolation.
+
+  In rare cases it makes sense to list a header in more than one
+  target if it could be considered conceptually a member of both.
+
+```
+
 ### **Examples**
 
 ```
@@ -494,6 +580,16 @@
 ```
   Formats .gn file to a standard format.
 
+  The contents of some lists ('sources', 'deps', etc.) will be sorted to
+  a canonical order. To suppress this, you can add a comment of the form
+  "# NOSORT" immediately preceeding the assignment. e.g.
+
+  # NOSORT
+  sources = [
+    "z.cc",
+    "a.cc",
+  ]
+
 ```
 
 ### **Arguments**
@@ -3503,25 +3599,57 @@
   These targets will be permitted to include headers from the current
   target despite the dependency going in the opposite direction.
 
+  When you use this, both targets must be included in a final binary
+  for it to link. To keep linker errors from happening, it is good
+  practice to have all external dependencies depend only on one of
+  the two targets, and to set the visibility on the other to enforce
+  this. Thus the targets will always be linked together in any output.
+
 ```
 
-### **Tedious exposition**
+### **Details**
 
 ```
   Normally, for a file in target A to include a file from target B,
   A must list B as a dependency. This invariant is enforced by the
-  "gn check" command (and the --check flag to "gn gen").
+  "gn check" command (and the --check flag to "gn gen" -- see
+  "gn help check").
 
   Sometimes, two targets might be the same unit for linking purposes
   (two source sets or static libraries that would always be linked
-  together in a final executable or shared library). In this case,
-  you want A to be able to include B's headers, and B to include A's
-  headers.
+  together in a final executable or shared library) and they each
+  include headers from the other: you want A to be able to include B's
+  headers, and B to include A's headers. This is not an ideal situation
+  but is sometimes unavoidable.
 
   This list, if specified, lists which of the dependencies of the
   current target can include header files from the current target.
   That is, if A depends on B, B can only include headers from A if it is
-  in A's allow_circular_includes_from list.
+  in A's allow_circular_includes_from list. Normally includes must
+  follow the direction of dependencies, this flag allows them to go
+  in the opposite direction.
+
+```
+
+### **Danger**
+
+```
+  In the above example, A's headers are likely to include headers from
+  A's dependencies. Those dependencies may have public_configs that
+  apply flags, defines, and include paths that make those headers work
+  properly.
+
+  With allow_circular_includes_from, B can include A's headers, and
+  transitively from A's dependencies, without having the dependencies
+  that would bring in the public_configs those headers need. The result
+  may be errors or inconsistent builds.
+
+  So when you use allow_circular_includes_from, make sure that any
+  compiler settings, flags, and include directories are the same between
+  both targets (consider putting such things in a shared config they can
+  both reference). Make sure the dependencies are also the same (you
+  might consider a group to collect such dependencies they both
+  depend on).
 
 ```
 
@@ -3529,11 +3657,21 @@
 
 ```
   source_set("a") {
-    deps = [ ":b", ":c" ]
+    deps = [ ":b", ":a_b_shared_deps" ]
     allow_circular_includes_from = [ ":b" ]
     ...
   }
 
+  source_set("b") {
+    deps = [ ":a_b_shared_deps" ]
+    # Sources here can include headers from a despite lack of deps.
+    ...
+  }
+
+  group("a_b_shared_deps") {
+    public_deps = [ ":c" ]
+  }
+
 
 ```
 ## **args**: Arguments passed to an action.
@@ -3880,29 +4018,12 @@
   This does not affect other targets that depend on the current target,
   it just skips checking the includes of the current target's files.
 
-```
+  If there are a few conditionally included headers that trip up
+  checking, you can exclude headers individually by annotating them with
+  "nogncheck" (see "gn help nogncheck").
 
-### **Controlling includes individually**
-
-```
-  If only certain includes are problematic, you can annotate them
-  individually rather than disabling header checking on an entire
-  target. Add the string "nogncheck" to the include line:
-
-    #include "foo/something_weird.h"  // nogncheck (bug 12345)
-
-  It is good form to include a reference to a bug (if the include is
-  improper, or some other comment expressing why the header checker
-  doesn't work for this particular case.
-
-  The most common reason to need "nogncheck" is conditional includes.
-  The header checker does not understand the preprocessor, so may flag
-  some includes as improper even if the dependencies and #defines are
-  always matched correctly:
-
-    #if defined(ENABLE_DOOM_MELON)
-    #include "doom_melon/beam_controller.h"  // nogncheck
-    #endif
+  The topic "gn help check" has general information on how checking
+  works and advice on how to pass a check in problematic cases.
 
 ```
 
@@ -3933,6 +4054,9 @@
   for all dependencies in one complete package. Since GN does not unpack
   static libraries to forward their contents up the dependency chain,
   it is an error for complete static libraries to depend on other static
+
+  In rare cases it makes sense to list a header in more than one
+  target if it could be considered conceptually a member of both.
   libraries.
 
 ```
@@ -5371,6 +5495,47 @@
 
 
 ```
+## **nogncheck**: Skip an include line from checking.
+
+```
+  GN's header checker helps validate that the includes match the build
+  dependency graph. Sometimes an include might be conditional or
+  otherwise problematic, but you want to specifically allow it. In this
+  case, it can be whitelisted.
+
+  Include lines containing the substring "nogncheck" will be excluded
+  from header checking. The most common case is a conditional include:
+
+    #if defined(ENABLE_DOOM_MELON)
+    #include "tools/doom_melon/doom_melon.h"  // nogncheck
+    #endif
+
+  If the build file has a conditional dependency on the corresponding
+  target that matches the conditional include, everything will always
+  link correctly:
+
+    source_set("mytarget") {
+      ...
+      if (enable_doom_melon) {
+        defines = [ "ENABLE_DOOM_MELON" ]
+        deps += [ "//tools/doom_melon" ]
+      }
+
+  But GN's header checker does not understand preprocessor directives,
+  won't know it matches the build dependencies, and will flag this
+  include as incorrect when the condition is false.
+
+```
+
+### **More information**
+
+```
+  The topic "gn help check" has general information on how checking
+  works and advice on fixing problems. Targets can also opt-out of
+  checking, see "gn help check_includes".
+
+
+```
 ## **Runtime dependencies**
 
 ```
diff --git a/tools/gn/header_checker.cc b/tools/gn/header_checker.cc
index ada9d70..259f9f6 100644
--- a/tools/gn/header_checker.cc
+++ b/tools/gn/header_checker.cc
@@ -298,14 +298,11 @@
 }
 
 // If the file exists:
-//  - It must be in one or more dependencies of the given target.
-//  - Those dependencies must have visibility from the source file.
-//  - The header must be in the public section of those dependeices.
-//  - Those dependencies must either have no direct dependent configs with
-//    flags that affect the compiler, or those direct dependent configs apply
-//    to the "from_target" (it's one "hop" away). This ensures that if the
-//    include file needs needs compiler settings to compile it, that those
-//    settings are applied to the file including it.
+//  - The header must be in the public section of a target, or it must
+//    be in the sources with no public list (everything is implicitly public).
+//  - The dependency path to the included target must follow only public_deps.
+//  - If there are multiple targets with the header in it, only one need be
+//    valid for the check to pass.
 bool HeaderChecker::CheckInclude(const Target* from_target,
                                  const InputFile& source_file,
                                  const SourceFile& include_file,
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index fd7800f..81bb7e3 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -354,29 +354,68 @@
     "  These targets will be permitted to include headers from the current\n"
     "  target despite the dependency going in the opposite direction.\n"
     "\n"
-    "Tedious exposition\n"
+    "  When you use this, both targets must be included in a final binary\n"
+    "  for it to link. To keep linker errors from happening, it is good\n"
+    "  practice to have all external dependencies depend only on one of\n"
+    "  the two targets, and to set the visibility on the other to enforce\n"
+    "  this. Thus the targets will always be linked together in any output.\n"
+    "\n"
+    "Details\n"
     "\n"
     "  Normally, for a file in target A to include a file from target B,\n"
     "  A must list B as a dependency. This invariant is enforced by the\n"
-    "  \"gn check\" command (and the --check flag to \"gn gen\").\n"
+    "  \"gn check\" command (and the --check flag to \"gn gen\" -- see\n"
+    "  \"gn help check\").\n"
     "\n"
     "  Sometimes, two targets might be the same unit for linking purposes\n"
     "  (two source sets or static libraries that would always be linked\n"
-    "  together in a final executable or shared library). In this case,\n"
-    "  you want A to be able to include B's headers, and B to include A's\n"
-    "  headers.\n"
+    "  together in a final executable or shared library) and they each\n"
+    "  include headers from the other: you want A to be able to include B's\n"
+    "  headers, and B to include A's headers. This is not an ideal situation\n"
+    "  but is sometimes unavoidable.\n"
     "\n"
     "  This list, if specified, lists which of the dependencies of the\n"
     "  current target can include header files from the current target.\n"
     "  That is, if A depends on B, B can only include headers from A if it is\n"
-    "  in A's allow_circular_includes_from list.\n"
+    "  in A's allow_circular_includes_from list. Normally includes must\n"
+    "  follow the direction of dependencies, this flag allows them to go\n"
+    "  in the opposite direction.\n"
+    "\n"
+    "Danger\n"
+    "\n"
+    "  In the above example, A's headers are likely to include headers from\n"
+    "  A's dependencies. Those dependencies may have public_configs that\n"
+    "  apply flags, defines, and include paths that make those headers work\n"
+    "  properly.\n"
+    "\n"
+    "  With allow_circular_includes_from, B can include A's headers, and\n"
+    "  transitively from A's dependencies, without having the dependencies\n"
+    "  that would bring in the public_configs those headers need. The result\n"
+    "  may be errors or inconsistent builds.\n"
+    "\n"
+    "  So when you use allow_circular_includes_from, make sure that any\n"
+    "  compiler settings, flags, and include directories are the same between\n"
+    "  both targets (consider putting such things in a shared config they can\n"
+    "  both reference). Make sure the dependencies are also the same (you\n"
+    "  might consider a group to collect such dependencies they both\n"
+    "  depend on).\n"
     "\n"
     "Example\n"
     "\n"
     "  source_set(\"a\") {\n"
-    "    deps = [ \":b\", \":c\" ]\n"
+    "    deps = [ \":b\", \":a_b_shared_deps\" ]\n"
     "    allow_circular_includes_from = [ \":b\" ]\n"
     "    ...\n"
+    "  }\n"
+    "\n"
+    "  source_set(\"b\") {\n"
+    "    deps = [ \":a_b_shared_deps\" ]\n"
+    "    # Sources here can include headers from a despite lack of deps.\n"
+    "    ...\n"
+    "  }\n"
+    "\n"
+    "  group(\"a_b_shared_deps\") {\n"
+    "    public_deps = [ \":c\" ]\n"
     "  }\n";
 
 const char kArgs[] = "args";
@@ -480,7 +519,7 @@
 const char kBundleExecutableDir[] = "bundle_executable_dir";
 const char kBundleExecutableDir_HelpShort[] =
     "bundle_executable_dir: "
-        "Expansion of {{bundle_executable_dir}} in create_bundle.";
+        "Expansion of {{bundle_executable_dir}} in create_bundle";
 const char kBundleExecutableDir_Help[] =
     "bundle_executable_dir: "
         "Expansion of {{bundle_executable_dir}} in create_bundle.\n"
@@ -575,26 +614,12 @@
     "  This does not affect other targets that depend on the current target,\n"
     "  it just skips checking the includes of the current target's files.\n"
     "\n"
-    "Controlling includes individually\n"
+    "  If there are a few conditionally included headers that trip up\n"
+    "  checking, you can exclude headers individually by annotating them with\n"
+    "  \"nogncheck\" (see \"gn help nogncheck\").\n"
     "\n"
-    "  If only certain includes are problematic, you can annotate them\n"
-    "  individually rather than disabling header checking on an entire\n"
-    "  target. Add the string \"nogncheck\" to the include line:\n"
-    "\n"
-    "    #include \"foo/something_weird.h\"  // nogncheck (bug 12345)\n"
-    "\n"
-    "  It is good form to include a reference to a bug (if the include is\n"
-    "  improper, or some other comment expressing why the header checker\n"
-    "  doesn't work for this particular case.\n"
-    "\n"
-    "  The most common reason to need \"nogncheck\" is conditional includes.\n"
-    "  The header checker does not understand the preprocessor, so may flag\n"
-    "  some includes as improper even if the dependencies and #defines are\n"
-    "  always matched correctly:\n"
-    "\n"
-    "    #if defined(ENABLE_DOOM_MELON)\n"
-    "    #include \"doom_melon/beam_controller.h\"  // nogncheck\n"
-    "    #endif\n"
+    "  The topic \"gn help check\" has general information on how checking\n"
+    "  works and advice on how to pass a check in problematic cases.\n"
     "\n"
     "Example\n"
     "\n"
@@ -623,6 +648,9 @@
     "  for all dependencies in one complete package. Since GN does not unpack\n"
     "  static libraries to forward their contents up the dependency chain,\n"
     "  it is an error for complete static libraries to depend on other static\n"
+    "\n"
+    "  In rare cases it makes sense to list a header in more than one\n"
+    "  target if it could be considered conceptually a member of both.\n"
     "  libraries.\n"
     "\n"
     "Example\n"