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