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/ninja_writer.h"
6
7#include "tools/gn/builder.h"
8#include "tools/gn/loader.h"
9#include "tools/gn/location.h"
10#include "tools/gn/ninja_build_writer.h"
11#include "tools/gn/ninja_toolchain_writer.h"
12#include "tools/gn/settings.h"
13
14NinjaWriter::NinjaWriter(const BuildSettings* build_settings,
15                         Builder* builder)
16    : build_settings_(build_settings),
17      builder_(builder) {
18}
19
20NinjaWriter::~NinjaWriter() {
21}
22
23// static
24bool NinjaWriter::RunAndWriteFiles(const BuildSettings* build_settings,
25                                   Builder* builder) {
26  NinjaWriter writer(build_settings, builder);
27
28  std::vector<const Settings*> all_settings;
29  std::vector<const Target*> default_targets;
30  if (!writer.WriteToolchains(&all_settings, &default_targets))
31    return false;
32  return writer.WriteRootBuildfiles(all_settings, default_targets);
33}
34
35// static
36bool NinjaWriter::RunAndWriteToolchainFiles(
37    const BuildSettings* build_settings,
38    Builder* builder,
39    std::vector<const Settings*>* all_settings) {
40  NinjaWriter writer(build_settings, builder);
41  std::vector<const Target*> default_targets;
42  return writer.WriteToolchains(all_settings, &default_targets);
43}
44
45bool NinjaWriter::WriteToolchains(std::vector<const Settings*>* all_settings,
46                                  std::vector<const Target*>* default_targets) {
47  // Categorize all targets by toolchain.
48  typedef std::map<Label, std::vector<const Target*> > CategorizedMap;
49  CategorizedMap categorized;
50
51  std::vector<const BuilderRecord*> all_records = builder_->GetAllRecords();
52  for (size_t i = 0; i < all_records.size(); i++) {
53    if (all_records[i]->type() == BuilderRecord::ITEM_TARGET &&
54        all_records[i]->should_generate()) {
55      categorized[all_records[i]->label().GetToolchainLabel()].push_back(
56          all_records[i]->item()->AsTarget());
57      }
58  }
59  if (categorized.empty()) {
60    Err(Location(), "No targets.",
61        "I could not find any targets to write, so I'm doing nothing.")
62        .PrintToStdout();
63    return false;
64  }
65
66  Label default_label = builder_->loader()->GetDefaultToolchain();
67
68  // Write out the toolchain buildfiles, and also accumulate the set of
69  // all settings and find the list of targets in the default toolchain.
70  for (CategorizedMap::const_iterator i = categorized.begin();
71       i != categorized.end(); ++i) {
72    const Settings* settings =
73        builder_->loader()->GetToolchainSettings(i->first);
74    const Toolchain* toolchain = builder_->GetToolchain(i->first);
75
76    all_settings->push_back(settings);
77    if (!NinjaToolchainWriter::RunAndWriteFile(settings, toolchain,
78                                               i->second)) {
79      Err(Location(),
80          "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
81      return false;
82    }
83  }
84
85  *default_targets = categorized[default_label];
86  return true;
87}
88
89bool NinjaWriter::WriteRootBuildfiles(
90    const std::vector<const Settings*>& all_settings,
91    const std::vector<const Target*>& default_targets) {
92  // All Settings objects should have the same default toolchain, and there
93  // should always be at least one settings object in the build.
94  CHECK(!all_settings.empty());
95  const Toolchain* default_toolchain =
96      builder_->GetToolchain(all_settings[0]->default_toolchain_label());
97
98  // Write the root buildfile.
99  if (!NinjaBuildWriter::RunAndWriteFile(build_settings_, all_settings,
100                                         default_toolchain, default_targets)) {
101    Err(Location(),
102        "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
103    return false;
104  }
105  return true;
106}
107