ninja_target_writer.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file.
4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/ninja_target_writer.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <fstream>
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <sstream>
9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/file_util.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_binary_target_writer.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_copy_target_writer.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_group_target_writer.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_script_target_writer.h"
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h"
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
19d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out)
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    : settings_(target->settings()),
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      target_(target),
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      out_(out),
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      path_output_(settings_->build_settings()->build_dir(),
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                   ESCAPE_NINJA, true),
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      helper_(settings_->build_settings()) {
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
28d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::~NinjaTargetWriter() {
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NinjaTargetWriter::RunAndWriteFile(const Target* target) {
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // External targets don't get written to disk, we assume they're managed by
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // an external program. If we're not using an external generator, this is
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // ignored.
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (target->settings()->build_settings()->using_external_generator() &&
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      target->external())
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Settings* settings = target->settings();
41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  NinjaHelper helper(settings->build_settings());
42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::FilePath ninja_file(settings->build_settings()->GetFullPath(
44d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      helper.GetNinjaFileForTarget(target).GetSourceFile(
45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          settings->build_settings())));
46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (g_scheduler->verbose_logging())
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  file_util::CreateDirectory(ninja_file.DirName());
51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // It's rediculously faster to write to a string and then write that to
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // disk in one operation than to use an fstream here.
54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::stringstream file;
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (file.fail()) {
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    g_scheduler->FailWithError(
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        Err(Location(), "Error writing ninja file.",
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n"
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            "for writing."));
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return;
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Call out to the correct sub-type of writer.
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (target->output_type() == Target::COPY_FILES) {
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NinjaCopyTargetWriter writer(target, file);
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::CUSTOM) {
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NinjaScriptTargetWriter writer(target, file);
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::GROUP) {
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NinjaGroupTargetWriter writer(target, file);
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::EXECUTABLE ||
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             target->output_type() == Target::STATIC_LIBRARY ||
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             target->output_type() == Target::SHARED_LIBRARY) {
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    NinjaBinaryTargetWriter writer(target, file);
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    CHECK(0);
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string contents = file.str();
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  file_util::WriteFile(ninja_file, contents.c_str(), contents.size());
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void NinjaTargetWriter::WriteEnvironment() {
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // TODO(brettw) have a better way to do the environment setup on Windows.
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (target_->settings()->IsWin())
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    out_ << "arch = environment.x86\n";
90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const Toolchain* NinjaTargetWriter::GetToolchain() const {
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return target_->settings()->toolchain();
94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string NinjaTargetWriter::GetSourcesImplicitDeps() const {
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::ostringstream ret;
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ret << " |";
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Input files are order-only deps.
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Target::FileList& prereqs = target_->source_prereqs();
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool has_files = !prereqs.empty();
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < prereqs.size(); i++) {
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ret << " ";
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    path_output_.WriteFile(ret, prereqs[i]);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Add on any direct deps marked as "hard".
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const std::vector<const Target*>& deps = target_->deps();
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < deps.size(); i++) {
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (deps[i]->hard_dep()) {
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      has_files = true;
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ret << " ";
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i]));
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (has_files)
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return ret.str();
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return std::string();  // No files added.
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
122