ninja_target_writer.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "tools/gn/file_template.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_binary_target_writer.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_copy_target_writer.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_group_target_writer.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_script_target_writer.h"
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "tools/gn/string_utils.h"
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/trace.h"
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)NinjaTargetWriter::NinjaTargetWriter(const Target* target,
230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     const Toolchain* toolchain,
240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     std::ostream& out)
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    : settings_(target->settings()),
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      target_(target),
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      toolchain_(toolchain),
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      out_(out),
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      path_output_(settings_->build_settings()->build_dir(),
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                   ESCAPE_NINJA, true),
31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      helper_(settings_->build_settings()) {
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
34d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::~NinjaTargetWriter() {
35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NinjaTargetWriter::RunAndWriteFile(const Target* target,
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        const Toolchain* toolchain) {
40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Settings* settings = target->settings();
41d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  NinjaHelper helper(settings->build_settings());
42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    target->label().GetUserVisibleName(false));
450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  trace.SetToolchain(settings->toolchain_label());
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::FilePath ninja_file(settings->build_settings()->GetFullPath(
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      helper.GetNinjaFileForTarget(target).GetSourceFile(
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          settings->build_settings())));
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (g_scheduler->verbose_logging())
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CreateDirectory(ninja_file.DirName());
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // It's rediculously faster to write to a string and then write that to
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // disk in one operation than to use an fstream here.
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::stringstream file;
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Call out to the correct sub-type of writer.
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (target->output_type() == Target::COPY_FILES) {
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NinjaCopyTargetWriter writer(target, toolchain, file);
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::CUSTOM) {
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NinjaScriptTargetWriter writer(target, toolchain, file);
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::GROUP) {
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NinjaGroupTargetWriter writer(target, toolchain, file);
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::EXECUTABLE ||
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             target->output_type() == Target::STATIC_LIBRARY ||
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             target->output_type() == Target::SHARED_LIBRARY ||
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             target->output_type() == Target::SOURCE_SET) {
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NinjaBinaryTargetWriter writer(target, toolchain, file);
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    CHECK(0);
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string contents = file.str();
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  file_util::WriteFile(ninja_file, contents.c_str(),
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                       static_cast<int>(contents.size()));
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string NinjaTargetWriter::GetSourcesImplicitDeps() const {
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::ostringstream ret;
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ret << " |";
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Input files are order-only deps.
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const Target::FileList& prereqs = target_->source_prereqs();
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool has_files = !prereqs.empty();
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < prereqs.size(); i++) {
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ret << " ";
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    path_output_.WriteFile(ret, prereqs[i]);
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Add on any direct deps marked as "hard".
980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  const LabelTargetVector& deps = target_->deps();
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < deps.size(); i++) {
1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (deps[i].ptr->hard_dep()) {
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      has_files = true;
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      ret << " ";
1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      path_output_.WriteFile(ret, helper_.GetTargetOutputFile(deps[i].ptr));
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (has_files)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return ret.str();
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return std::string();  // No files added.
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)FileTemplate NinjaTargetWriter::GetOutputTemplate() const {
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const Target::FileList& outputs = target_->script_values().outputs();
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::vector<std::string> output_template_args;
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < outputs.size(); i++) {
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // All outputs should be in the output dir.
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    output_template_args.push_back(
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        RemovePrefix(outputs[i].value(),
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                     settings_->build_settings()->build_dir().value()));
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return FileTemplate(output_template_args);
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
123