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
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/strings/string_util.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/filesystem_utils.h"
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "tools/gn/ninja_action_target_writer.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_binary_target_writer.h"
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_copy_target_writer.h"
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "tools/gn/ninja_group_target_writer.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/ninja_utils.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "tools/gn/output_file.h"
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "tools/gn/string_utils.h"
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "tools/gn/substitution_writer.h"
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target.h"
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "tools/gn/trace.h"
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)NinjaTargetWriter::NinjaTargetWriter(const Target* target,
270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     std::ostream& out)
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    : settings_(target->settings()),
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      target_(target),
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      out_(out),
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA) {
32d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
34d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochNinjaTargetWriter::~NinjaTargetWriter() {
35d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
36d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
37d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
39d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Settings* settings = target->settings();
40d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    target->label().GetUserVisibleName(false));
430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  trace.SetToolchain(settings->toolchain_label());
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::FilePath ninja_file(settings->build_settings()->GetFullPath(
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      GetNinjaFileForTarget(target)));
47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (g_scheduler->verbose_logging())
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::CreateDirectory(ninja_file.DirName());
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // It's rediculously faster to write to a string and then write that to
54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // disk in one operation than to use an fstream here.
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::stringstream file;
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Call out to the correct sub-type of writer.
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (target->output_type() == Target::COPY_FILES) {
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NinjaCopyTargetWriter writer(target, file);
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else if (target->output_type() == Target::ACTION ||
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)             target->output_type() == Target::ACTION_FOREACH) {
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NinjaActionTargetWriter writer(target, file);
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::GROUP) {
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NinjaGroupTargetWriter writer(target, file);
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (target->output_type() == Target::EXECUTABLE ||
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)             target->output_type() == Target::STATIC_LIBRARY ||
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             target->output_type() == Target::SHARED_LIBRARY ||
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             target->output_type() == Target::SOURCE_SET) {
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    NinjaBinaryTargetWriter writer(target, file);
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    writer.Run();
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    CHECK(0);
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string contents = file.str();
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(ninja_file, contents.c_str(),
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                  static_cast<int>(contents.size()));
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void NinjaTargetWriter::WriteSharedVars(const SubstitutionBits& bits) {
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool written_anything = false;
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Target label.
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_LABEL]) {
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_LABEL] << " = "
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_LABEL)
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Root gen dir.
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_ROOT_GEN_DIR]) {
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_GEN_DIR] << " = "
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_ROOT_GEN_DIR)
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Root out dir.
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_ROOT_OUT_DIR]) {
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_ROOT_OUT_DIR] << " = "
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_ROOT_OUT_DIR)
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Target gen dir.
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_TARGET_GEN_DIR]) {
11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_GEN_DIR] << " = "
11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_TARGET_GEN_DIR)
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Target out dir.
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_TARGET_OUT_DIR]) {
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUT_DIR] << " = "
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_TARGET_OUT_DIR)
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Target output name.
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (bits.used[SUBSTITUTION_TARGET_OUTPUT_NAME]) {
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << kSubstitutionNinjaNames[SUBSTITUTION_TARGET_OUTPUT_NAME] << " = "
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << SubstitutionWriter::GetTargetSubstitution(
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                target_, SUBSTITUTION_TARGET_OUTPUT_NAME)
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         << std::endl;
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    written_anything = true;
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // If we wrote any vars, separate them from the rest of the file that follows
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // with a blank line.
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (written_anything)
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << std::endl;
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciOutputFile NinjaTargetWriter::WriteInputDepsStampAndGetDep(
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<const Target*>& extra_hard_deps) const {
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CHECK(target_->toolchain())
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Toolchain not set on target "
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << target_->label().GetUserVisibleName(true);
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // For an action (where we run a script only once) the sources are the same
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // as the source prereqs.
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool list_sources_as_input_deps = (target_->output_type() == Target::ACTION);
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Actions get implicit dependencies on the script itself.
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool add_script_source_as_dep =
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (target_->output_type() == Target::ACTION) ||
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (target_->output_type() == Target::ACTION_FOREACH);
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!add_script_source_as_dep &&
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extra_hard_deps.empty() &&
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      target_->inputs().empty() &&
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      target_->recursive_hard_deps().empty() &&
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (!list_sources_as_input_deps || target_->sources().empty()) &&
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      target_->toolchain()->deps().empty())
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return OutputFile();  // No input/hard deps.
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // One potential optimization is if there are few input dependencies (or
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // potentially few sources that depend on these) it's better to just write
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // all hard deps on each sources line than have this intermediate stamp. We
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // do the stamp file because duplicating all the order-only deps for each
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // source file can really explode the ninja file but this won't be the most
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // optimal thing in all cases.
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
17603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  OutputFile input_stamp_file(
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      RebaseSourceAbsolutePath(GetTargetOutputDir(target_).value(),
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                               settings_->build_settings()->build_dir()));
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_stamp_file.value().append(target_->label().name());
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  input_stamp_file.value().append(".inputdeps.stamp");
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out_ << "build ";
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  path_output_.WriteFile(out_, input_stamp_file);
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out_ << ": "
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       << GetNinjaRulePrefixForToolchain(settings_)
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Script file (if applicable).
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (add_script_source_as_dep) {
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    out_ << " ";
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    path_output_.WriteFile(out_, target_->action_values().script());
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Input files are order-only deps.
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const Target::FileList& prereqs = target_->inputs();
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (size_t i = 0; i < prereqs.size(); i++) {
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    out_ << " ";
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    path_output_.WriteFile(out_, prereqs[i]);
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (list_sources_as_input_deps) {
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const Target::FileList& sources = target_->sources();
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    for (size_t i = 0; i < sources.size(); i++) {
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      out_ << " ";
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      path_output_.WriteFile(out_, sources[i]);
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The different souces of input deps may duplicate some targets, so uniquify
20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // them (ordering doesn't matter for this case).
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::set<const Target*> unique_deps;
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Hard dependencies that are direct or indirect dependencies.
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::set<const Target*>& hard_deps = target_->recursive_hard_deps();
214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::set<const Target*>::const_iterator i = hard_deps.begin();
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       i != hard_deps.end(); ++i) {
21603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    unique_deps.insert(*i);
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Extra hard dependencies passed in.
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  unique_deps.insert(extra_hard_deps.begin(), extra_hard_deps.end());
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Toolchain dependencies. These must be resolved before doing anything.
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // This just writs all toolchain deps for simplicity. If we find that
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // toolchains often have more than one dependency, we could consider writing
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // a toolchain-specific stamp file and only include the stamp here.
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const LabelTargetVector& toolchain_deps = target_->toolchain()->deps();
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < toolchain_deps.size(); i++)
22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    unique_deps.insert(toolchain_deps[i].ptr);
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (std::set<const Target*>::const_iterator i = unique_deps.begin();
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       i != unique_deps.end(); ++i) {
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK(!(*i)->dependency_output_file().value().empty());
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    out_ << " ";
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    path_output_.WriteFile(out_, (*i)->dependency_output_file());
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  out_ << "\n";
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return input_stamp_file;
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void NinjaTargetWriter::WriteStampForTarget(
24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::vector<OutputFile>& files,
24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::vector<OutputFile>& order_only_deps) {
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const OutputFile& stamp_file = target_->dependency_output_file();
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // First validate that the target's dependency is a stamp file. Otherwise,
24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // we shouldn't have gotten here!
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CHECK(EndsWith(stamp_file.value(), ".stamp", false))
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "Output should end in \".stamp\" for stamp file output. Instead got: "
25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      << "\"" << stamp_file.value() << "\"";
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  out_ << "build ";
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  path_output_.WriteFile(out_, stamp_file);
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  out_ << ": "
25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       << GetNinjaRulePrefixForToolchain(settings_)
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)       << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  path_output_.WriteFiles(out_, files);
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!order_only_deps.empty()) {
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    out_ << " ||";
26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    path_output_.WriteFiles(out_, order_only_deps);
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  out_ << std::endl;
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
266