1// Copyright (c) 2013 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.
4
5#include "tools/gn/commands.h"
6#include "tools/gn/filesystem_utils.h"
7#include "tools/gn/item.h"
8#include "tools/gn/label.h"
9#include "tools/gn/label_pattern.h"
10#include "tools/gn/setup.h"
11#include "tools/gn/standard_out.h"
12#include "tools/gn/target.h"
13
14namespace commands {
15
16CommandInfo::CommandInfo()
17    : help_short(NULL),
18      help(NULL),
19      runner(NULL) {
20}
21
22CommandInfo::CommandInfo(const char* in_help_short,
23                         const char* in_help,
24                         CommandRunner in_runner)
25    : help_short(in_help_short),
26      help(in_help),
27      runner(in_runner) {
28}
29
30const CommandInfoMap& GetCommands() {
31  static CommandInfoMap info_map;
32  if (info_map.empty()) {
33    #define INSERT_COMMAND(cmd) \
34        info_map[k##cmd] = CommandInfo(k##cmd##_HelpShort, \
35                                       k##cmd##_Help, \
36                                       &Run##cmd);
37
38    INSERT_COMMAND(Args)
39    INSERT_COMMAND(Check)
40    INSERT_COMMAND(Desc)
41    INSERT_COMMAND(Gen)
42    INSERT_COMMAND(Format)
43    INSERT_COMMAND(Help)
44    INSERT_COMMAND(Ls)
45    INSERT_COMMAND(Refs)
46
47    #undef INSERT_COMMAND
48  }
49  return info_map;
50}
51
52const Target* ResolveTargetFromCommandLineString(
53    Setup* setup,
54    const std::string& label_string) {
55  // Need to resolve the label after we know the default toolchain.
56  Label default_toolchain = setup->loader()->default_toolchain_label();
57  Value arg_value(NULL, label_string);
58  Err err;
59  Label label = Label::Resolve(SourceDirForCurrentDirectory(
60                                   setup->build_settings().root_path()),
61                               default_toolchain, arg_value, &err);
62  if (err.has_error()) {
63    err.PrintToStdout();
64    return NULL;
65  }
66
67  const Item* item = setup->builder()->GetItem(label);
68  if (!item) {
69    Err(Location(), "Label not found.",
70        label.GetUserVisibleName(false) + " not found.").PrintToStdout();
71    return NULL;
72  }
73
74  const Target* target = item->AsTarget();
75  if (!target) {
76    Err(Location(), "Not a target.",
77        "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
78        "is not a target. Somebody should probably implement this command for "
79        "other\nitem types.");
80    return NULL;
81  }
82
83  return target;
84}
85
86bool ResolveTargetsFromCommandLinePattern(
87    Setup* setup,
88    const std::string& label_pattern,
89    bool all_toolchains,
90    std::vector<const Target*>* matches) {
91  Value pattern_value(NULL, label_pattern);
92
93  Err err;
94  LabelPattern pattern = LabelPattern::GetPattern(
95      SourceDirForCurrentDirectory(setup->build_settings().root_path()),
96      pattern_value,
97      &err);
98  if (err.has_error()) {
99    err.PrintToStdout();
100    return false;
101  }
102
103  if (!all_toolchains) {
104    // By default a pattern with an empty toolchain will match all toolchains.
105    // IF the caller wants to default to the main toolchain only, set it
106    // explicitly.
107    if (pattern.toolchain().is_null()) {
108      // No explicit toolchain set.
109      pattern.set_toolchain(setup->loader()->default_toolchain_label());
110    }
111  }
112
113  std::vector<const Target*> all_targets =
114      setup->builder()->GetAllResolvedTargets();
115
116  for (size_t i = 0; i < all_targets.size(); i++) {
117    if (pattern.Matches(all_targets[i]->label()))
118      matches->push_back(all_targets[i]);
119  }
120  return true;
121}
122
123}  // namespace commands
124