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 "tools/gn/header_checker.h" | 5 #include "tools/gn/header_checker.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/strings/string_util.h" |
12 #include "base/threading/sequenced_worker_pool.h" | 13 #include "base/threading/sequenced_worker_pool.h" |
13 #include "tools/gn/build_settings.h" | 14 #include "tools/gn/build_settings.h" |
14 #include "tools/gn/builder.h" | 15 #include "tools/gn/builder.h" |
15 #include "tools/gn/c_include_iterator.h" | 16 #include "tools/gn/c_include_iterator.h" |
16 #include "tools/gn/config.h" | 17 #include "tools/gn/config.h" |
17 #include "tools/gn/err.h" | 18 #include "tools/gn/err.h" |
18 #include "tools/gn/filesystem_utils.h" | 19 #include "tools/gn/filesystem_utils.h" |
19 #include "tools/gn/scheduler.h" | 20 #include "tools/gn/scheduler.h" |
20 #include "tools/gn/source_file_type.h" | 21 #include "tools/gn/source_file_type.h" |
21 #include "tools/gn/target.h" | 22 #include "tools/gn/target.h" |
22 #include "tools/gn/trace.h" | 23 #include "tools/gn/trace.h" |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
| 27 struct PublicGeneratedPair { |
| 28 PublicGeneratedPair() : is_public(false), is_generated(false) {} |
| 29 bool is_public; |
| 30 bool is_generated; |
| 31 }; |
| 32 |
| 33 // If the given file is in the "gen" folder, trims this so it treats the gen |
| 34 // directory as the source root: |
| 35 // //out/Debug/gen/foo/bar.h -> //foo/bar.h |
| 36 // If the file isn't in the generated root, returns the input unchanged. |
| 37 SourceFile RemoveRootGenDirFromFile(const Target* target, |
| 38 const SourceFile& file) { |
| 39 const SourceDir& gen = target->settings()->toolchain_gen_dir(); |
| 40 if (StartsWithASCII(file.value(), gen.value(), true)) |
| 41 return SourceFile("//" + file.value().substr(gen.value().size())); |
| 42 return file; |
| 43 } |
| 44 |
26 // This class makes InputFiles on the stack as it reads files to check. When | 45 // This class makes InputFiles on the stack as it reads files to check. When |
27 // we throw an error, the Err indicates a locatin which has a pointer to | 46 // we throw an error, the Err indicates a locatin which has a pointer to |
28 // an InputFile that must persist as long as the Err does. | 47 // an InputFile that must persist as long as the Err does. |
29 // | 48 // |
30 // To make this work, this function creates a clone of the InputFile managed | 49 // To make this work, this function creates a clone of the InputFile managed |
31 // by the InputFileManager so the error can refer to something that | 50 // by the InputFileManager so the error can refer to something that |
32 // persists. This means that the current file contents will live as long as | 51 // persists. This means that the current file contents will live as long as |
33 // the program, but this is OK since we're erroring out anyway. | 52 // the program, but this is OK since we're erroring out anyway. |
34 LocationRange CreatePersistentRange(const InputFile& input_file, | 53 LocationRange CreatePersistentRange(const InputFile& input_file, |
35 const LocationRange& range) { | 54 const LocationRange& range) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 file_i != files.end(); ++file_i) { | 178 file_i != files.end(); ++file_i) { |
160 const TargetVector& vect = file_i->second; | 179 const TargetVector& vect = file_i->second; |
161 | 180 |
162 // Only check C-like source files (RC files also have includes). | 181 // Only check C-like source files (RC files also have includes). |
163 SourceFileType type = GetSourceFileType(file_i->first); | 182 SourceFileType type = GetSourceFileType(file_i->first); |
164 if (type != SOURCE_CC && type != SOURCE_H && type != SOURCE_C && | 183 if (type != SOURCE_CC && type != SOURCE_H && type != SOURCE_C && |
165 type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC) | 184 type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC) |
166 continue; | 185 continue; |
167 | 186 |
168 // Do a first pass to find if this should be skipped. All targets including | 187 // Do a first pass to find if this should be skipped. All targets including |
169 // this source file must exclude it from checking. | 188 // this source file must exclude it from checking, or it must be generated. |
170 if (!force_check) { | 189 if (!force_check) { |
171 bool check_includes = false; | 190 bool check_includes = false; |
172 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) | 191 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) { |
173 check_includes |= vect[vect_i].target->check_includes(); | 192 check_includes |= |
| 193 vect[vect_i].target->check_includes() && |
| 194 !vect[vect_i].is_generated; |
| 195 } |
174 if (!check_includes) | 196 if (!check_includes) |
175 continue; | 197 continue; |
176 } | 198 } |
177 | 199 |
178 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) { | 200 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) { |
179 pool->PostWorkerTaskWithShutdownBehavior( | 201 pool->PostWorkerTaskWithShutdownBehavior( |
180 FROM_HERE, | 202 FROM_HERE, |
181 base::Bind(&HeaderChecker::DoWork, this, | 203 base::Bind(&HeaderChecker::DoWork, this, |
182 vect[vect_i].target, file_i->first), | 204 vect[vect_i].target, file_i->first), |
183 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 205 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
(...skipping 11 matching lines...) Expand all Loading... |
195 errors_.push_back(err); | 217 errors_.push_back(err); |
196 } | 218 } |
197 } | 219 } |
198 | 220 |
199 // static | 221 // static |
200 void HeaderChecker::AddTargetToFileMap(const Target* target, FileMap* dest) { | 222 void HeaderChecker::AddTargetToFileMap(const Target* target, FileMap* dest) { |
201 // Files in the sources have this public bit by default. | 223 // Files in the sources have this public bit by default. |
202 bool default_public = target->all_headers_public(); | 224 bool default_public = target->all_headers_public(); |
203 | 225 |
204 // First collect the normal files, they get the default visibility. | 226 // First collect the normal files, they get the default visibility. |
205 std::map<SourceFile, bool> files_to_public; | 227 std::map<SourceFile, PublicGeneratedPair> files_to_public; |
206 const Target::FileList& sources = target->sources(); | 228 const Target::FileList& sources = target->sources(); |
207 for (size_t i = 0; i < sources.size(); i++) | 229 for (size_t i = 0; i < sources.size(); i++) |
208 files_to_public[sources[i]] = default_public; | 230 files_to_public[sources[i]].is_public = default_public; |
209 | 231 |
210 // Add in the public files, forcing them to public. This may overwrite some | 232 // Add in the public files, forcing them to public. This may overwrite some |
211 // entries, and it may add new ones. | 233 // entries, and it may add new ones. |
212 const Target::FileList& public_list = target->public_headers(); | 234 const Target::FileList& public_list = target->public_headers(); |
213 if (default_public) | 235 if (default_public) |
214 DCHECK(public_list.empty()); // List only used when default is not public. | 236 DCHECK(public_list.empty()); // List only used when default is not public. |
215 for (size_t i = 0; i < public_list.size(); i++) | 237 for (size_t i = 0; i < public_list.size(); i++) |
216 files_to_public[public_list[i]] = true; | 238 files_to_public[public_list[i]].is_public = true; |
| 239 |
| 240 // Add in outputs from actions. These are treated as public (since if other |
| 241 // targets can't use them, then there wouldn't be any point in outputting). |
| 242 std::vector<SourceFile> outputs; |
| 243 target->action_values().GetOutputsAsSourceFiles(target, &outputs); |
| 244 for (size_t i = 0; i < outputs.size(); i++) { |
| 245 // For generated files in the "gen" directory, add the filename to the |
| 246 // map assuming "gen" is the source root. This means that when files include |
| 247 // the generated header relative to there (the recommended practice), we'll |
| 248 // find the file. |
| 249 SourceFile output_file = RemoveRootGenDirFromFile(target, outputs[i]); |
| 250 PublicGeneratedPair* pair = &files_to_public[output_file]; |
| 251 pair->is_public = true; |
| 252 pair->is_generated = true; |
| 253 } |
217 | 254 |
218 // Add the merged list to the master list of all files. | 255 // Add the merged list to the master list of all files. |
219 for (std::map<SourceFile, bool>::const_iterator i = files_to_public.begin(); | 256 for (std::map<SourceFile, PublicGeneratedPair>::const_iterator i = |
220 i != files_to_public.end(); ++i) | 257 files_to_public.begin(); |
221 (*dest)[i->first].push_back(TargetInfo(target, i->second)); | 258 i != files_to_public.end(); ++i) { |
| 259 (*dest)[i->first].push_back(TargetInfo( |
| 260 target, i->second.is_public, i->second.is_generated)); |
| 261 } |
222 } | 262 } |
223 | 263 |
224 bool HeaderChecker::IsFileInOuputDir(const SourceFile& file) const { | 264 bool HeaderChecker::IsFileInOuputDir(const SourceFile& file) const { |
225 const std::string& build_dir = build_settings_->build_dir().value(); | 265 const std::string& build_dir = build_settings_->build_dir().value(); |
226 return file.value().compare(0, build_dir.size(), build_dir) == 0; | 266 return file.value().compare(0, build_dir.size(), build_dir) == 0; |
227 } | 267 } |
228 | 268 |
229 // This current assumes all include paths are relative to the source root | 269 // This current assumes all include paths are relative to the source root |
230 // which is generally the case for Chromium. | 270 // which is generally the case for Chromium. |
231 // | 271 // |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 chain[i]->forward_dependent_configs(); | 553 chain[i]->forward_dependent_configs(); |
514 if (std::find_if(forwarded.begin(), forwarded.end(), | 554 if (std::find_if(forwarded.begin(), forwarded.end(), |
515 LabelPtrPtrEquals<Target>(chain[i - 1])) == | 555 LabelPtrPtrEquals<Target>(chain[i - 1])) == |
516 forwarded.end()) | 556 forwarded.end()) |
517 return i; | 557 return i; |
518 } | 558 } |
519 | 559 |
520 CHECK(false) << "Unable to diagnose dependent config chain problem."; | 560 CHECK(false) << "Unable to diagnose dependent config chain problem."; |
521 return 0; | 561 return 0; |
522 } | 562 } |
OLD | NEW |