OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "tools/gn/commands.h" | 9 #include "tools/gn/commands.h" |
10 #include "tools/gn/header_checker.h" | 10 #include "tools/gn/header_checker.h" |
11 #include "tools/gn/setup.h" | 11 #include "tools/gn/setup.h" |
12 #include "tools/gn/standard_out.h" | 12 #include "tools/gn/standard_out.h" |
13 #include "tools/gn/switches.h" | 13 #include "tools/gn/switches.h" |
14 #include "tools/gn/target.h" | 14 #include "tools/gn/target.h" |
15 #include "tools/gn/trace.h" | 15 #include "tools/gn/trace.h" |
16 | 16 |
17 namespace commands { | 17 namespace commands { |
18 | 18 |
| 19 const char kNoGnCheck_Help[] = |
| 20 "nogncheck: Skip an include line from checking.\n" |
| 21 "\n" |
| 22 " GN's header checker helps validate that the includes match the build\n" |
| 23 " dependency graph. Sometimes an include might be conditional or\n" |
| 24 " otherwise problematic, but you want to specifically allow it. In this\n" |
| 25 " case, it can be whitelisted.\n" |
| 26 "\n" |
| 27 " Include lines containing the substring \"nogncheck\" will be excluded\n" |
| 28 " from header checking. The most common case is a conditional include:\n" |
| 29 "\n" |
| 30 " #if defined(ENABLE_DOOM_MELON)\n" |
| 31 " #include \"tools/doom_melon/doom_melon.h\" // nogncheck\n" |
| 32 " #endif\n" |
| 33 "\n" |
| 34 " If the build file has a conditional dependency on the corresponding\n" |
| 35 " target that matches the conditional include, everything will always\n" |
| 36 " link correctly:\n" |
| 37 "\n" |
| 38 " source_set(\"mytarget\") {\n" |
| 39 " ...\n" |
| 40 " if (enable_doom_melon) {\n" |
| 41 " defines = [ \"ENABLE_DOOM_MELON\" ]\n" |
| 42 " deps += [ \"//tools/doom_melon\" ]\n" |
| 43 " }\n" |
| 44 "\n" |
| 45 " But GN's header checker does not understand preprocessor directives,\n" |
| 46 " won't know it matches the build dependencies, and will flag this\n" |
| 47 " include as incorrect when the condition is false.\n" |
| 48 "\n" |
| 49 "More information\n" |
| 50 "\n" |
| 51 " The topic \"gn help check\" has general information on how checking\n" |
| 52 " works and advice on fixing problems. Targets can also opt-out of\n" |
| 53 " checking, see \"gn help check_includes\".\n"; |
| 54 |
19 const char kCheck[] = "check"; | 55 const char kCheck[] = "check"; |
20 const char kCheck_HelpShort[] = | 56 const char kCheck_HelpShort[] = |
21 "check: Check header dependencies."; | 57 "check: Check header dependencies."; |
22 const char kCheck_Help[] = | 58 const char kCheck_Help[] = |
23 "gn check <out_dir> [<label_pattern>] [--force]\n" | 59 "gn check <out_dir> [<label_pattern>] [--force]\n" |
24 "\n" | 60 "\n" |
| 61 " GN's include header checker validates that the includes for C-like\n" |
| 62 " source files match the build dependency graph.\n" |
| 63 "\n" |
25 " \"gn check\" is the same thing as \"gn gen\" with the \"--check\" flag\n" | 64 " \"gn check\" is the same thing as \"gn gen\" with the \"--check\" flag\n" |
26 " except that this command does not write out any build files. It's\n" | 65 " except that this command does not write out any build files. It's\n" |
27 " intended to be an easy way to manually trigger include file checking.\n" | 66 " intended to be an easy way to manually trigger include file checking.\n" |
28 "\n" | 67 "\n" |
29 " The <label_pattern> can take exact labels or patterns that match more\n" | 68 " The <label_pattern> can take exact labels or patterns that match more\n" |
30 " than one (although not general regular expressions). If specified,\n" | 69 " than one (although not general regular expressions). If specified,\n" |
31 " only those matching targets will be checked. See\n" | 70 " only those matching targets will be checked. See\n" |
32 " \"gn help label_pattern\" for details.\n" | 71 " \"gn help label_pattern\" for details.\n" |
33 "\n" | 72 "\n" |
34 " The .gn file may specify a list of targets to be checked. Only these\n" | |
35 " targets will be checked if no label_pattern is specified on the\n" | |
36 " command line. Otherwise, the command-line list is used instead. See\n" | |
37 " \"gn help dotfile\".\n" | |
38 "\n" | |
39 "Command-specific switches\n" | 73 "Command-specific switches\n" |
40 "\n" | 74 "\n" |
41 " --force\n" | 75 " --force\n" |
42 " Ignores specifications of \"check_includes = false\" and checks\n" | 76 " Ignores specifications of \"check_includes = false\" and checks\n" |
43 " all target's files that match the target label.\n" | 77 " all target's files that match the target label.\n" |
44 "\n" | 78 "\n" |
| 79 "What gets checked\n" |
| 80 "\n" |
| 81 " The .gn file may specify a list of targets to be checked. Only these\n" |
| 82 " targets will be checked if no label_pattern is specified on the\n" |
| 83 " command line. Otherwise, the command-line list is used instead. See\n" |
| 84 " \"gn help dotfile\".\n" |
| 85 "\n" |
| 86 " Targets can opt-out from checking with \"check_includes = false\"\n" |
| 87 " (see \"gn help check_includes\").\n" |
| 88 "\n" |
| 89 " For targets being checked:\n" |
| 90 "\n" |
| 91 " - GN opens all C-like source files in the targets to be checked and\n" |
| 92 " scans the top for includes.\n" |
| 93 "\n" |
| 94 " - Includes with a \"nogncheck\" annotation are skipped (see\n" |
| 95 " \"gn help nogncheck\").\n" |
| 96 "\n" |
| 97 " - Only includes using \"quotes\" are checked. <brackets> are assumed\n" |
| 98 " to be system includes.\n" |
| 99 "\n" |
| 100 " - Include paths are assumed to be relative to either the source root\n" |
| 101 " or the \"root_gen_dir\" and must include all the path components.\n" |
| 102 " (It might be nice in the future to incorporate GN's knowledge of\n" |
| 103 " the include path to handle other include styles.)\n" |
| 104 "\n" |
| 105 " - GN does not run the preprocessor so will not understand\n" |
| 106 " conditional includes.\n" |
| 107 "\n" |
| 108 " - Only includes matching known files in the build are checked:\n" |
| 109 " includes matching unknown paths are ignored.\n" |
| 110 "\n" |
| 111 " For an include to be valid:\n" |
| 112 "\n" |
| 113 " - The included file must be in the current target, or there must\n" |
| 114 " be a path following only public dependencies to a target with the\n" |
| 115 " file in it (\"gn path\" is a good way to diagnose problems).\n" |
| 116 "\n" |
| 117 " - There can be multiple targets with an included file: only one\n" |
| 118 " needs to be valid for the include to be allowed.\n" |
| 119 "\n" |
| 120 " - If there are only \"sources\" in a target, all are considered to\n" |
| 121 " be public and can be included by other targets with a valid public\n" |
| 122 " dependency path.\n" |
| 123 "\n" |
| 124 " - If a target lists files as \"public\", only those files are\n" |
| 125 " able to be included by other targets. Anything in the sources\n" |
| 126 " will be considered private and will not be includable regardless\n" |
| 127 " of dependency paths.\n" |
| 128 "\n" |
| 129 " - Ouptuts from actions are treated like public sources on that\n" |
| 130 " target.\n" |
| 131 "\n" |
| 132 " - A target can include headers from a target that depends on it\n" |
| 133 " if the other target is annotated accordingly. See\n" |
| 134 " \"gn help allow_circular_includes_from\".\n" |
| 135 "\n" |
| 136 "Advice on fixing problems\n" |
| 137 "\n" |
| 138 " If you have a third party project that uses relative includes,\n" |
| 139 " it's generally best to exclude that target from checking altogether\n" |
| 140 " via \"check_includes = false\".\n" |
| 141 "\n" |
| 142 " If you have conditional includes, make sure the build conditions\n" |
| 143 " and the preprocessor conditions match, and annotate the line with\n" |
| 144 " \"nogncheck\" (see \"gn help nogncheck\" for an example).\n" |
| 145 "\n" |
| 146 " If two targets are hopelessly intertwined, use the\n" |
| 147 " \"allow_circular_includes_from\" annotation. Ideally each should have\n" |
| 148 " identical dependencies so configs inherited from those dependencies\n" |
| 149 " are consistent (see \"gn help allow_circular_includes_from\").\n" |
| 150 "\n" |
| 151 " If you have a standalone header file or files that need to be shared\n" |
| 152 " between a few targets, you can consider making a source_set listing\n" |
| 153 " only those headers as public sources. With only header files, the\n" |
| 154 " source set will be a no-op from a build perspective, but will give a\n" |
| 155 " central place to refer to those headers. That source set's files\n" |
| 156 " will still need to pass \"gn check\" in isolation.\n" |
| 157 "\n" |
| 158 " In rare cases it makes sense to list a header in more than one\n" |
| 159 " target if it could be considered conceptually a member of both.\n" |
| 160 "\n" |
45 "Examples\n" | 161 "Examples\n" |
46 "\n" | 162 "\n" |
47 " gn check out/Debug\n" | 163 " gn check out/Debug\n" |
48 " Check everything.\n" | 164 " Check everything.\n" |
49 "\n" | 165 "\n" |
50 " gn check out/Default //foo:bar\n" | 166 " gn check out/Default //foo:bar\n" |
51 " Check only the files in the //foo:bar target.\n" | 167 " Check only the files in the //foo:bar target.\n" |
52 "\n" | 168 "\n" |
53 " gn check out/Default \"//foo/*\n" | 169 " gn check out/Default \"//foo/*\n" |
54 " Check only the files in targets in the //foo directory tree.\n"; | 170 " Check only the files in targets in the //foo directory tree.\n"; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 header_checker->Run(to_check, force_check, &header_errors); | 253 header_checker->Run(to_check, force_check, &header_errors); |
138 for (size_t i = 0; i < header_errors.size(); i++) { | 254 for (size_t i = 0; i < header_errors.size(); i++) { |
139 if (i > 0) | 255 if (i > 0) |
140 OutputString("___________________\n", DECORATION_YELLOW); | 256 OutputString("___________________\n", DECORATION_YELLOW); |
141 header_errors[i].PrintToStdout(); | 257 header_errors[i].PrintToStdout(); |
142 } | 258 } |
143 return header_errors.empty(); | 259 return header_errors.empty(); |
144 } | 260 } |
145 | 261 |
146 } // namespace commands | 262 } // namespace commands |
OLD | NEW |