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/files/file_util.h" | 10 #include "base/files/file_util.h" |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 // our include finder is too primitive and returns all includes, even if | 313 // our include finder is too primitive and returns all includes, even if |
314 // they're in a #if not executed in the current build. In that case, it's | 314 // they're in a #if not executed in the current build. In that case, it's |
315 // not unusual for the buildfiles to not specify that header at all. | 315 // not unusual for the buildfiles to not specify that header at all. |
316 FileMap::const_iterator found = file_map_.find(include_file); | 316 FileMap::const_iterator found = file_map_.find(include_file); |
317 if (found == file_map_.end()) | 317 if (found == file_map_.end()) |
318 return true; | 318 return true; |
319 | 319 |
320 const TargetVector& targets = found->second; | 320 const TargetVector& targets = found->second; |
321 Chain chain; // Prevent reallocating in the loop. | 321 Chain chain; // Prevent reallocating in the loop. |
322 | 322 |
| 323 // If the file is unknown in the current toolchain (rather than being private |
| 324 // or in a target not visible to the current target), ignore it. This is a |
| 325 // bit of a hack to account for the fact that the include finder doesn't |
| 326 // understand the preprocessor. |
| 327 // |
| 328 // When not cross-compiling, if a platform specific header is conditionally |
| 329 // included in the build, and preprocessor conditions around #includes of |
| 330 // that match the build conditions, everything will be OK because the file |
| 331 // won't be known to GN even though the #include finder identified the file. |
| 332 // |
| 333 // Cross-compiling breaks this. When compiling Android on Linux, for example, |
| 334 // we might see both Linux and Android definitions of a target and know |
| 335 // about the union of all headers in the build. Since the #include finder |
| 336 // ignores preprocessor, we will find the Linux headers in the Android |
| 337 // build and note that a dependency from the Android target to the Linux |
| 338 // one is missing (these might even be the same target in different |
| 339 // toolchains!). |
| 340 bool present_in_current_toolchain = false; |
| 341 for (const auto& target : targets) { |
| 342 if (from_target->label().ToolchainsEqual(target.target->label())) { |
| 343 present_in_current_toolchain = true; |
| 344 break; |
| 345 } |
| 346 } |
| 347 if (!present_in_current_toolchain) |
| 348 return true; |
| 349 |
323 // For all targets containing this file, we require that at least one be | 350 // For all targets containing this file, we require that at least one be |
324 // a direct or public dependency of the current target, and that the header | 351 // a direct or public dependency of the current target, and that the header |
325 // is public within the target. | 352 // is public within the target. |
326 // | 353 // |
327 // If there is more than one target containing this header, we may encounter | 354 // If there is more than one target containing this header, we may encounter |
328 // some error cases before finding a good one. This error stores the previous | 355 // some error cases before finding a good one. This error stores the previous |
329 // one encountered, which we may or may not throw away. | 356 // one encountered, which we may or may not throw away. |
330 Err last_error; | 357 Err last_error; |
331 | 358 |
332 bool found_dependency = false; | 359 bool found_dependency = false; |
333 for (const auto& target : targets) { | 360 for (const auto& target : targets) { |
334 // We always allow source files in a target to include headers also in that | 361 // We always allow source files in a target to include headers also in that |
335 // target. | 362 // target. |
336 const Target* to_target = target.target; | 363 const Target* to_target = target.target; |
337 if (to_target == from_target) | 364 if (to_target == from_target) |
338 return true; | 365 return true; |
339 | 366 |
340 // Additionally, allow a target to include files from that same target | |
341 // in other toolchains. This is a bit of a hack to account for the fact that | |
342 // the include finder doesn't understand the preprocessor. | |
343 // | |
344 // If a source file conditionally depends on a platform-specific include in | |
345 // the same target, and there is a cross-compile such that GN sees | |
346 // definitions of the target both with and without that include, it would | |
347 // give an error that the target needs to depend on itself in the other | |
348 // toolchain (where the platform-specific header is defined as a source). | |
349 if (TargetLabelsMatchExceptToolchain(to_target, from_target)) | |
350 return true; | |
351 | |
352 bool is_permitted_chain = false; | 367 bool is_permitted_chain = false; |
353 if (IsDependencyOf(to_target, from_target, &chain, &is_permitted_chain)) { | 368 if (IsDependencyOf(to_target, from_target, &chain, &is_permitted_chain)) { |
354 DCHECK(chain.size() >= 2); | 369 DCHECK(chain.size() >= 2); |
355 DCHECK(chain[0].target == to_target); | 370 DCHECK(chain[0].target == to_target); |
356 DCHECK(chain[chain.size() - 1].target == from_target); | 371 DCHECK(chain[chain.size() - 1].target == from_target); |
357 | 372 |
358 found_dependency = true; | 373 found_dependency = true; |
359 | 374 |
360 if (target.is_public && is_permitted_chain) { | 375 if (target.is_public && is_permitted_chain) { |
361 // This one is OK, we're done. | 376 // This one is OK, we're done. |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 if (targets_with_other_toolchains.size() + | 574 if (targets_with_other_toolchains.size() + |
560 targets_with_matching_toolchains.size() > 1) | 575 targets_with_matching_toolchains.size() > 1) |
561 msg += "at least one of "; | 576 msg += "at least one of "; |
562 msg += "which should somehow be reachable."; | 577 msg += "which should somehow be reachable."; |
563 | 578 |
564 // Danger: must call CreatePersistentRange to put in Err. | 579 // Danger: must call CreatePersistentRange to put in Err. |
565 return Err(CreatePersistentRange(source_file, range), | 580 return Err(CreatePersistentRange(source_file, range), |
566 "Include not allowed.", msg); | 581 "Include not allowed.", msg); |
567 } | 582 } |
568 | 583 |
OLD | NEW |