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() == 2) {
74 // Compute the target to check.
75 if (!ResolveTargetsFromCommandLinePattern(setup
, args
[1], false,
78 if (targets_to_check
.size() == 0) {
79 OutputString("No matching targets.\n");
83 // No argument means to check everything allowed by the filter in
84 // the build config file.
85 if (setup
->check_patterns()) {
86 FilterTargetsByPatterns(all_targets
, *setup
->check_patterns(),
88 filtered_by_build_config
= targets_to_check
.size() != all_targets
.size();
90 // No global filter, check everything.
91 targets_to_check
= all_targets
;
95 const CommandLine
* cmdline
= CommandLine::ForCurrentProcess();
96 bool force
= cmdline
->HasSwitch("force");
98 if (!CheckPublicHeaders(&setup
->build_settings(), all_targets
,
99 targets_to_check
, force
))
102 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kQuiet
)) {
103 if (filtered_by_build_config
) {
104 // Tell the user about the implicit filtering since this is obscure.
105 OutputString(base::StringPrintf(
106 "%d targets out of %d checked based on the check_targets defined in"
108 static_cast<int>(targets_to_check
.size()),
109 static_cast<int>(all_targets
.size())));
111 OutputString("Header dependency check OK\n", DECORATION_GREEN
);
116 bool CheckPublicHeaders(const BuildSettings
* build_settings
,
117 const std::vector
<const Target
*>& all_targets
,
118 const std::vector
<const Target
*>& to_check
,
120 ScopedTrace
trace(TraceItem::TRACE_CHECK_HEADERS
, "Check headers");
122 scoped_refptr
<HeaderChecker
> header_checker(
123 new HeaderChecker(build_settings
, all_targets
));
125 std::vector
<Err
> header_errors
;
126 header_checker
->Run(to_check
, force_check
, &header_errors
);
127 for (size_t i
= 0; i
< header_errors
.size(); i
++) {
129 OutputString("___________________\n", DECORATION_YELLOW
);
130 header_errors
[i
].PrintToStdout();
132 return header_errors
.empty();
135 void FilterTargetsByPatterns(const std::vector
<const Target
*>& input
,
136 const std::vector
<LabelPattern
>& filter
,
137 std::vector
<const Target
*>* output
) {
138 for (const auto& target
: input
) {
139 for (const auto& pattern
: filter
) {
140 if (pattern
.Matches(target
->label())) {
141 output
->push_back(target
);
148 } // namespace commands