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
7#include "tools/gn/item.h"
8#include "tools/gn/item_node.h"
9#include "tools/gn/label.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(Desc)
39    INSERT_COMMAND(Gen)
40    INSERT_COMMAND(Help)
41
42    #undef INSERT_COMMAND
43  }
44  return info_map;
45}
46
47const Target* GetTargetForDesc(const std::vector<std::string>& args) {
48  // Deliberately leaked to avoid expensive process teardown.
49  Setup* setup = new Setup;
50  if (!setup->DoSetup())
51    return NULL;
52
53  // FIXME(brettw): set the output dir to be a sandbox one to avoid polluting
54  // the real output dir with files written by the build scripts.
55
56  // Do the actual load. This will also write out the target ninja files.
57  if (!setup->Run())
58    return NULL;
59
60  // Need to resolve the label after we know the default toolchain.
61  // TODO(brettw) find the current directory and resolve the input label
62  // relative to that.
63  Label default_toolchain = setup->build_settings().toolchain_manager()
64      .GetDefaultToolchainUnlocked();
65  Value arg_value(NULL, args[0]);
66  Err err;
67  Label label = Label::Resolve(SourceDir(), default_toolchain, arg_value, &err);
68  if (err.has_error()) {
69    err.PrintToStdout();
70    return NULL;
71  }
72
73  ItemNode* node;
74  {
75    base::AutoLock lock(setup->build_settings().item_tree().lock());
76    node = setup->build_settings().item_tree().GetExistingNodeLocked(label);
77  }
78  if (!node) {
79    Err(Location(), "",
80        "I don't know about this \"" + label.GetUserVisibleName(false) +
81        "\"").PrintToStdout();
82    return NULL;
83  }
84
85  const Target* target = node->item()->AsTarget();
86  if (!target) {
87    Err(Location(), "Not a target.",
88        "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
89        "is not a target. Somebody should probably implement this command for "
90        "other\nitem types.");
91    return NULL;
92  }
93
94  return target;
95}
96
97}  // namespace commands
98