Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: tools/gn/header_checker.cc

Issue 1142423004: Make GN header checker more lenient about toolchains. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/memory/BUILD.gn ('k') | tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « base/memory/BUILD.gn ('k') | tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698