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
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/strings/stringprintf.h"
7 #include "tools/gn/commands.h"
8 #include "tools/gn/header_checker.h"
9 #include "tools/gn/setup.h"
10 #include "tools/gn/standard_out.h"
11 #include "tools/gn/switches.h"
12 #include "tools/gn/target.h"
13 #include "tools/gn/trace.h"
17 const char kCheck
[] = "check";
18 const char kCheck_HelpShort
[] =
19 "check: Check header dependencies.";
20 const char kCheck_Help
[] =
21 "gn check <out_dir> [<label_pattern>] [--force]\n"
23 " \"gn check\" is the same thing as \"gn gen\" with the \"--check\" flag\n"
24 " except that this command does not write out any build files. It's\n"
25 " intended to be an easy way to manually trigger include file checking.\n"
27 " The <label_pattern> can take exact labels or patterns that match more\n"
28 " than one (although not general regular expressions). If specified,\n"
29 " only those matching targets will be checked. See\n"
30 " \"gn help label_pattern\" for details.\n"
32 " The .gn file may specify a list of targets to be checked. Only these\n"
33 " targets will be checked if no label_pattern is specified on the\n"
34 " command line. Otherwise, the command-line list is used instead. See\n"
35 " \"gn help dotfile\".\n"
37 "Command-specific switches\n"
40 " Ignores specifications of \"check_includes = false\" and checks\n"
41 " all target's files that match the target label.\n"
45 " gn check out/Debug\n"
46 " Check everything.\n"
48 " gn check out/Default //foo:bar\n"
49 " Check only the files in the //foo:bar target.\n"
51 " gn check out/Default \"//foo/*\n"
52 " Check only the files in targets in the //foo directory tree.\n";
54 int RunCheck(const std::vector
<std::string
>& args
) {
55 if (args
.size() != 1 && args
.size() != 2) {
56 Err(Location(), "You're holding it wrong.",
57 "Usage: \"gn check <out_dir> [<target_label>]\"").PrintToStdout();
61 // Deliberately leaked to avoid expensive process teardown.
62 Setup
* setup
= new Setup();
63 if (!setup
->DoSetup(args
[0], false))
68 std::vector
<const Target
*> all_targets
=
69 setup
->builder()->GetAllResolvedTargets();
71 bool filtered_by_build_config
= false;
72 std::vector
<const Target
*> targets_to_check
;
73 if (args
.size() > 1) {
74 // Compute the targets to check.
75 std::vector
<std::string
> inputs(args
.begin() + 1, args
.end());
76 UniqueVector
<const Target
*> target_matches
;
77 UniqueVector
<const Config
*> config_matches
;
78 UniqueVector
<const Toolchain
*> toolchain_matches
;
79 UniqueVector
<SourceFile
> file_matches
;
80 if (!ResolveFromCommandLineInput(setup
, inputs
, false,
81 &target_matches
, &config_matches
,
82 &toolchain_matches
, &file_matches
))
85 if (target_matches
.size() == 0) {
86 OutputString("No matching targets.\n");
89 targets_to_check
.insert(targets_to_check
.begin(),
90 target_matches
.begin(), target_matches
.end());
92 // No argument means to check everything allowed by the filter in
93 // the build config file.
94 if (setup
->check_patterns()) {
95 FilterTargetsByPatterns(all_targets
, *setup
->check_patterns(),
97 filtered_by_build_config
= targets_to_check
.size() != all_targets
.size();
99 // No global filter, check everything.
100 targets_to_check
= all_targets
;
104 const base::CommandLine
* cmdline
= base::CommandLine::ForCurrentProcess();
105 bool force
= cmdline
->HasSwitch("force");
107 if (!CheckPublicHeaders(&setup
->build_settings(), all_targets
,
108 targets_to_check
, force
))
111 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kQuiet
)) {
112 if (filtered_by_build_config
) {
113 // Tell the user about the implicit filtering since this is obscure.
114 OutputString(base::StringPrintf(
115 "%d targets out of %d checked based on the check_targets defined in"
117 static_cast<int>(targets_to_check
.size()),
118 static_cast<int>(all_targets
.size())));
120 OutputString("Header dependency check OK\n", DECORATION_GREEN
);
125 bool CheckPublicHeaders(const BuildSettings
* build_settings
,
126 const std::vector
<const Target
*>& all_targets
,
127 const std::vector
<const Target
*>& to_check
,
129 ScopedTrace
trace(TraceItem::TRACE_CHECK_HEADERS
, "Check headers");
131 scoped_refptr
<HeaderChecker
> header_checker(
132 new HeaderChecker(build_settings
, all_targets
));
134 std::vector
<Err
> header_errors
;
135 header_checker
->Run(to_check
, force_check
, &header_errors
);
136 for (size_t i
= 0; i
< header_errors
.size(); i
++) {
138 OutputString("___________________\n", DECORATION_YELLOW
);
139 header_errors
[i
].PrintToStdout();
141 return header_errors
.empty();
144 } // namespace commands