ninja_target_writer.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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_target_writer.h"
6
7#include <fstream>
8#include <sstream>
9
10#include "base/file_util.h"
11#include "tools/gn/err.h"
12#include "tools/gn/ninja_binary_target_writer.h"
13#include "tools/gn/ninja_copy_target_writer.h"
14#include "tools/gn/ninja_group_target_writer.h"
15#include "tools/gn/ninja_script_target_writer.h"
16#include "tools/gn/scheduler.h"
17#include "tools/gn/target.h"
18
19NinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out)
20    : settings_(target->settings()),
21      target_(target),
22      out_(out),
23      path_output_(settings_->build_settings()->build_dir(),
24                   ESCAPE_NINJA, true),
25      helper_(settings_->build_settings()) {
26}
27
28NinjaTargetWriter::~NinjaTargetWriter() {
29}
30
31// static
32void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
33  // External targets don't get written to disk, we assume they're managed by
34  // an external program. If we're not using an external generator, this is
35  // ignored.
36  if (target->settings()->build_settings()->using_external_generator() &&
37      target->external())
38    return;
39
40  const Settings* settings = target->settings();
41  NinjaHelper helper(settings->build_settings());
42
43  base::FilePath ninja_file(settings->build_settings()->GetFullPath(
44      helper.GetNinjaFileForTarget(target).GetSourceFile(
45          settings->build_settings())));
46
47  if (g_scheduler->verbose_logging())
48    g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
49
50  file_util::CreateDirectory(ninja_file.DirName());
51
52  // It's rediculously faster to write to a string and then write that to
53  // disk in one operation than to use an fstream here.
54  std::stringstream file;
55  if (file.fail()) {
56    g_scheduler->FailWithError(
57        Err(Location(), "Error writing ninja file.",
58            "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n"
59            "for writing."));
60    return;
61  }
62
63  // Call out to the correct sub-type of writer.
64  if (target->output_type() == Target::COPY_FILES) {
65    NinjaCopyTargetWriter writer(target, file);
66    writer.Run();
67  } else if (target->output_type() == Target::CUSTOM) {
68    NinjaScriptTargetWriter writer(target, file);
69    writer.Run();
70  } else if (target->output_type() == Target::GROUP) {
71    NinjaGroupTargetWriter writer(target, file);
72    writer.Run();
73  } else if (target->output_type() == Target::EXECUTABLE ||
74             target->output_type() == Target::STATIC_LIBRARY ||
75             target->output_type() == Target::SHARED_LIBRARY) {
76    NinjaBinaryTargetWriter writer(target, file);
77    writer.Run();
78  } else {
79    CHECK(0);
80  }
81
82  std::string contents = file.str();
83  file_util::WriteFile(ninja_file, contents.c_str(), contents.size());
84}
85
86void NinjaTargetWriter::WriteEnvironment() {
87  // TODO(brettw) have a better way to do the environment setup on Windows.
88  if (target_->settings()->IsWin())
89    out_ << "arch = environment.x86\n";
90}
91
92const Toolchain* NinjaTargetWriter::GetToolchain() const {
93  return target_->settings()->toolchain();
94}
95
96std::string NinjaTargetWriter::GetSourcesImplicitDeps() const {
97  std::ostringstream ret;
98  ret << " |";
99
100  // Input files are order-only deps.
101  const Target::FileList& prereqs = target_->source_prereqs();
102  bool has_files = !prereqs.empty();
103  for (size_t i = 0; i < prereqs.size(); i++) {
104    ret << " ";
105    path_output_.WriteFile(ret, prereqs[i]);
106  }
107
108  // Add on any direct deps marked as "hard".
109  const std::vector<const Target*>& deps = target_->deps();
110  for (size_t i = 0; i < deps.size(); i++) {
111    if (deps[i]->hard_dep()) {
112      has_files = true;
113      ret << " ";
114      path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i]));
115    }
116  }
117
118  if (has_files)
119    return ret.str();
120  return std::string();  // No files added.
121}
122