// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/ninja_c_binary_target_writer.h"

#include <stddef.h>
#include <string.h>

#include <cstring>
#include <set>
#include <sstream>

#include "base/strings/string_util.h"
#include "gn/c_substitution_type.h"
#include "gn/config_values_extractors.h"
#include "gn/deps_iterator.h"
#include "gn/err.h"
#include "gn/escape.h"
#include "gn/filesystem_utils.h"
#include "gn/general_tool.h"
#include "gn/ninja_target_command_util.h"
#include "gn/ninja_utils.h"
#include "gn/pool.h"
#include "gn/scheduler.h"
#include "gn/settings.h"
#include "gn/string_utils.h"
#include "gn/substitution_writer.h"
#include "gn/target.h"

struct ModuleDep {
  ModuleDep(const SourceFile* modulemap,
            const std::string& module_name,
            const OutputFile& pcm,
            bool is_self)
      : modulemap(modulemap),
        module_name(module_name),
        pcm(pcm),
        is_self(is_self) {}

  // The input module.modulemap source file.
  const SourceFile* modulemap;

  // The internal module name, in GN this is the target's label.
  std::string module_name;

  // The compiled version of the module.
  OutputFile pcm;

  // Is this the module for the current target.
  bool is_self;
};

namespace {

// Returns the proper escape options for writing compiler and linker flags.
EscapeOptions GetFlagOptions() {
  EscapeOptions opts;
  opts.mode = ESCAPE_NINJA_COMMAND;
  return opts;
}

// Returns the language-specific lang recognized by gcc’s -x flag for
// precompiled header files.
const char* GetPCHLangForToolType(const char* name) {
  if (name == CTool::kCToolCc)
    return "c-header";
  if (name == CTool::kCToolCxx)
    return "c++-header";
  if (name == CTool::kCToolObjC)
    return "objective-c-header";
  if (name == CTool::kCToolObjCxx)
    return "objective-c++-header";
  NOTREACHED() << "Not a valid PCH tool type: " << name;
  return "";
}

const SourceFile* GetModuleMapFromTargetSources(const Target* target) {
  for (const SourceFile& sf : target->sources()) {
    if (sf.IsModuleMapType())
      return &sf;
  }
  return nullptr;
}

std::vector<ModuleDep> GetModuleDepsInformation(
    const Target* target,
    const ResolvedTargetData& resolved) {
  std::vector<ModuleDep> ret;

  auto add = [&ret](const Target* t, bool is_self) {
    const SourceFile* modulemap = GetModuleMapFromTargetSources(t);
    CHECK(modulemap);

    std::string label;
    CHECK(SubstitutionWriter::GetTargetSubstitution(
        t, &SubstitutionLabelNoToolchain, &label));

    const char* tool_type;
    std::vector<OutputFile> modulemap_outputs;
    CHECK(
        t->GetOutputFilesForSource(*modulemap, &tool_type, &modulemap_outputs));
    // Must be only one .pcm from .modulemap.
    CHECK(modulemap_outputs.size() == 1u);
    ret.emplace_back(modulemap, label, modulemap_outputs[0], is_self);
  };

  if (target->source_types_used().Get(SourceFile::SOURCE_MODULEMAP)) {
    add(target, true);
  }

  for (const Target* dep : resolved.GetLinkedDeps(target)) {
    // Having a .modulemap source means that the dependency is modularized.
    if (dep->source_types_used().Get(SourceFile::SOURCE_MODULEMAP)) {
      add(dep, false);
    }
  }

  return ret;
}

}  // namespace

NinjaCBinaryTargetWriter::NinjaCBinaryTargetWriter(const Target* target,
                                                   std::ostream& out)
    : NinjaBinaryTargetWriter(target, out),
      tool_(target->toolchain()->GetToolForTargetFinalOutputAsC(target)) {}

NinjaCBinaryTargetWriter::~NinjaCBinaryTargetWriter() = default;

void NinjaCBinaryTargetWriter::Run() {
  std::vector<ModuleDep> module_dep_info =
      GetModuleDepsInformation(target_, resolved());

  WriteCompilerVars(module_dep_info);

  size_t num_stamp_uses = target_->sources().size();

  std::vector<OutputFile> input_deps = WriteInputsStampAndGetDep(
      num_stamp_uses);

  // The input dependencies will be an order-only dependency. This will cause
  // Ninja to make sure the inputs are up to date before compiling this source,
  // but changes in the inputs deps won't cause the file to be recompiled.
  //
  // This is important to prevent changes in unrelated actions that are
  // upstream of this target from causing everything to be recompiled.
  //
  // Why can we get away with this rather than using implicit deps ("|", which
  // will force rebuilds when the inputs change)? For source code, the
  // computed dependencies of all headers will be computed by the compiler,
  // which will cause source rebuilds if any "real" upstream dependencies
  // change.
  //
  // If a .cc file is generated by an input dependency, Ninja will see the
  // input to the build rule doesn't exist, and that it is an output from a
  // previous step, and build the previous step first. This is a "real"
  // dependency and doesn't need | or || to express.
  //
  // The only case where this rule matters is for the first build where no .d
  // files exist, and Ninja doesn't know what that source file depends on. In
  // this case it's sufficient to ensure that the upstream dependencies are
  // built first. This is exactly what Ninja's order-only dependencies
  // expresses.
  //
  // The order only deps are referenced by each source file compile,
  // but also by PCH compiles.  The latter are annoying to count, so omit
  // them here.  This means that binary targets with a single source file
  // that also use PCH files won't have a stamp file even though having
  // one would make output ninja file size a bit lower. That's ok, binary
  // targets with a single source are rare.
  std::vector<OutputFile> order_only_deps = WriteInputDepsStampAndGetDep(
      std::vector<const Target*>(), num_stamp_uses);

  // For GCC builds, the .gch files are not object files, but still need to be
  // added as explicit dependencies below. The .gch output files are placed in
  // |pch_other_files|. This is to prevent linking against them.
  std::vector<OutputFile> pch_obj_files;
  std::vector<OutputFile> pch_other_files;
  WritePCHCommands(input_deps, order_only_deps, &pch_obj_files,
                   &pch_other_files);
  std::vector<OutputFile>* pch_files =
      !pch_obj_files.empty() ? &pch_obj_files : &pch_other_files;

  // Treat all pch output files as explicit dependencies of all
  // compiles that support them. Some notes:
  //
  //  - On Windows, the .pch file is the input to the compile, not the
  //    precompiled header's corresponding object file that we're using here.
  //    But Ninja's depslog doesn't support multiple outputs from the
  //    precompiled header compile step (it outputs both the .pch file and a
  //    corresponding .obj file). So we consistently list the .obj file and the
  //    .pch file we really need comes along with it.
  //
  //  - GCC .gch files are not object files, therefore they are not added to the
  //    object file list.
  std::vector<OutputFile> obj_files;
  std::vector<SourceFile> other_files;
  if (!target_->source_types_used().SwiftSourceUsed()) {
    WriteSources(*pch_files, input_deps, order_only_deps, module_dep_info,
                 &obj_files, &other_files);
  } else {
    WriteSwiftSources(input_deps, order_only_deps, &obj_files);
  }

  // Link all MSVC pch object files. The vector will be empty on GCC toolchains.
  obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end());
  if (!CheckForDuplicateObjectFiles(obj_files))
    return;

  if (target_->output_type() == Target::SOURCE_SET) {
    WriteSourceSetStamp(obj_files);
#ifndef NDEBUG
    // Verify that the function that separately computes a source set's object
    // files match the object files just computed.
    UniqueVector<OutputFile> computed_obj;
    AddSourceSetFiles(target_, &computed_obj);
    DCHECK_EQ(obj_files.size(), computed_obj.size());
    for (const auto& obj : obj_files)
      DCHECK(computed_obj.Contains(obj));
#endif
  } else {
    WriteLinkerStuff(obj_files, other_files, input_deps);
  }
}

void NinjaCBinaryTargetWriter::WriteCompilerVars(
    const std::vector<ModuleDep>& module_dep_info) {
  const SubstitutionBits& subst = target_->toolchain()->substitution_bits();

  WriteCCompilerVars(subst, /*indent=*/false,
                     /*respect_source_types_used=*/true);

  if (!module_dep_info.empty()) {
    // TODO(scottmg): Currently clang modules only working for C++.
    if (target_->source_types_used().Get(SourceFile::SOURCE_CPP) ||
        target_->source_types_used().Get(SourceFile::SOURCE_MODULEMAP)) {
      WriteModuleDepsSubstitution(&CSubstitutionModuleDeps, module_dep_info,
                                  true);
      WriteModuleDepsSubstitution(&CSubstitutionModuleDepsNoSelf,
                                  module_dep_info, false);
    }
  }

  WriteSharedVars(subst);
}

void NinjaCBinaryTargetWriter::WriteModuleDepsSubstitution(
    const Substitution* substitution,
    const std::vector<ModuleDep>& module_dep_info,
    bool include_self) {
  if (target_->toolchain()->substitution_bits().used.count(
          substitution)) {
    EscapeOptions options;
    options.mode = ESCAPE_NINJA_COMMAND;

    out_ << substitution->ninja_name << " = -Xclang ";
    EscapeStringToStream(out_, "-fmodules-embed-all-files", options);

    for (const auto& module_dep : module_dep_info) {
      if (!module_dep.is_self || include_self) {
        out_ << " ";
        EscapeStringToStream(out_, "-fmodule-file=", options);
        path_output_.WriteFile(out_, module_dep.pcm);
      }
    }

    out_ << std::endl;
  }
}

void NinjaCBinaryTargetWriter::WritePCHCommands(
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* object_files,
    std::vector<OutputFile>* other_files) {
  if (!target_->config_values().has_precompiled_headers())
    return;

  const CTool* tool_c = target_->toolchain()->GetToolAsC(CTool::kCToolCc);
  if (tool_c && tool_c->precompiled_header_type() != CTool::PCH_NONE &&
      target_->source_types_used().Get(SourceFile::SOURCE_C)) {
    WritePCHCommand(&CSubstitutionCFlagsC, CTool::kCToolCc,
                    tool_c->precompiled_header_type(), input_deps,
                    order_only_deps, object_files, other_files);
  }
  const CTool* tool_cxx = target_->toolchain()->GetToolAsC(CTool::kCToolCxx);
  if (tool_cxx && tool_cxx->precompiled_header_type() != CTool::PCH_NONE &&
      target_->source_types_used().Get(SourceFile::SOURCE_CPP)) {
    WritePCHCommand(&CSubstitutionCFlagsCc, CTool::kCToolCxx,
                    tool_cxx->precompiled_header_type(), input_deps,
                    order_only_deps, object_files, other_files);
  }

  const CTool* tool_objc = target_->toolchain()->GetToolAsC(CTool::kCToolObjC);
  if (tool_objc && tool_objc->precompiled_header_type() == CTool::PCH_GCC &&
      target_->source_types_used().Get(SourceFile::SOURCE_M)) {
    WritePCHCommand(&CSubstitutionCFlagsObjC, CTool::kCToolObjC,
                    tool_objc->precompiled_header_type(), input_deps,
                    order_only_deps, object_files, other_files);
  }

  const CTool* tool_objcxx =
      target_->toolchain()->GetToolAsC(CTool::kCToolObjCxx);
  if (tool_objcxx && tool_objcxx->precompiled_header_type() == CTool::PCH_GCC &&
      target_->source_types_used().Get(SourceFile::SOURCE_MM)) {
    WritePCHCommand(&CSubstitutionCFlagsObjCc, CTool::kCToolObjCxx,
                    tool_objcxx->precompiled_header_type(), input_deps,
                    order_only_deps, object_files, other_files);
  }
}

void NinjaCBinaryTargetWriter::WritePCHCommand(
    const Substitution* flag_type,
    const char* tool_name,
    CTool::PrecompiledHeaderType header_type,
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* object_files,
    std::vector<OutputFile>* other_files) {
  switch (header_type) {
    case CTool::PCH_MSVC:
      WriteWindowsPCHCommand(flag_type, tool_name, input_deps, order_only_deps,
                             object_files);
      break;
    case CTool::PCH_GCC:
      WriteGCCPCHCommand(flag_type, tool_name, input_deps, order_only_deps,
                         other_files);
      break;
    case CTool::PCH_NONE:
      NOTREACHED() << "Cannot write a PCH command with no PCH header type";
      break;
  }
}

void NinjaCBinaryTargetWriter::WriteGCCPCHCommand(
    const Substitution* flag_type,
    const char* tool_name,
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* gch_files) {
  // Compute the pch output file (it will be language-specific).
  std::vector<OutputFile> outputs;
  GetPCHOutputFiles(target_, tool_name, &outputs);
  if (outputs.empty())
    return;

  gch_files->insert(gch_files->end(), outputs.begin(), outputs.end());

  std::vector<OutputFile> extra_deps;
  std::copy(input_deps.begin(), input_deps.end(),
            std::back_inserter(extra_deps));

  // Build line to compile the file.
  WriteCompilerBuildLine({target_->config_values().precompiled_source()},
                         extra_deps, order_only_deps, tool_name, outputs);

  // This build line needs a custom language-specific flags value. Rule-specific
  // variables are just indented underneath the rule line.
  out_ << "  " << flag_type->ninja_name << " =";

  // Each substitution flag is overwritten in the target rule to replace the
  // implicitly generated -include flag with the -x <header lang> flag required
  // for .gch targets.
  EscapeOptions opts = GetFlagOptions();
  if (tool_name == CTool::kCToolCc) {
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::cflags_c, opts,
                                         out_);
  } else if (tool_name == CTool::kCToolCxx) {
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::cflags_cc,
                                         opts, out_);
  } else if (tool_name == CTool::kCToolObjC) {
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::cflags_objc,
                                         opts, out_);
  } else if (tool_name == CTool::kCToolObjCxx) {
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::cflags_objcc,
                                         opts, out_);
  }

  // Append the command to specify the language of the .gch file.
  out_ << " -x " << GetPCHLangForToolType(tool_name);

  // Write two blank lines to help separate the PCH build lines from the
  // regular source build lines.
  out_ << std::endl << std::endl;
}

void NinjaCBinaryTargetWriter::WriteWindowsPCHCommand(
    const Substitution* flag_type,
    const char* tool_name,
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* object_files) {
  // Compute the pch output file (it will be language-specific).
  std::vector<OutputFile> outputs;
  GetPCHOutputFiles(target_, tool_name, &outputs);
  if (outputs.empty())
    return;

  object_files->insert(object_files->end(), outputs.begin(), outputs.end());

  std::vector<OutputFile> extra_deps;
  std::copy(input_deps.begin(), input_deps.end(),
            std::back_inserter(extra_deps));

  // Build line to compile the file.
  WriteCompilerBuildLine({target_->config_values().precompiled_source()},
                         extra_deps, order_only_deps, tool_name, outputs);

  // This build line needs a custom language-specific flags value. Rule-specific
  // variables are just indented underneath the rule line.
  out_ << "  " << flag_type->ninja_name << " =";

  // Append the command to generate the .pch file.
  // This adds the value to the existing flag instead of overwriting it.
  out_ << " ${" << flag_type->ninja_name << "}";
  out_ << " /Yc" << target_->config_values().precompiled_header();

  // Write two blank lines to help separate the PCH build lines from the
  // regular source build lines.
  out_ << std::endl << std::endl;
}

void NinjaCBinaryTargetWriter::WriteSources(
    const std::vector<OutputFile>& pch_deps,
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    const std::vector<ModuleDep>& module_dep_info,
    std::vector<OutputFile>* object_files,
    std::vector<SourceFile>* other_files) {
  DCHECK(!target_->source_types_used().SwiftSourceUsed());
  object_files->reserve(object_files->size() + target_->sources().size());

  std::vector<OutputFile> tool_outputs;  // Prevent reallocation in loop.
  std::vector<OutputFile> deps;
  for (const auto& source : target_->sources()) {
    DCHECK_NE(source.GetType(), SourceFile::SOURCE_SWIFT);

    // Clear the vector but maintain the max capacity to prevent reallocations.
    deps.resize(0);
    const char* tool_name = Tool::kToolNone;
    if (!target_->GetOutputFilesForSource(source, &tool_name, &tool_outputs)) {
      if (source.IsDefType())
        other_files->push_back(source);
      continue;  // No output for this source.
    }

    std::copy(input_deps.begin(), input_deps.end(), std::back_inserter(deps));

    if (tool_name != Tool::kToolNone) {
      // Only include PCH deps that correspond to the tool type, for instance,
      // do not specify target_name.precompile.cc.obj (a CXX PCH file) as a dep
      // for the output of a C tool type.
      //
      // This makes the assumption that pch_deps only contains pch output files
      // with the naming scheme specified in GetWindowsPCHObjectExtension or
      // GetGCCPCHOutputExtension.
      const CTool* tool = target_->toolchain()->GetToolAsC(tool_name);
      if (tool->precompiled_header_type() != CTool::PCH_NONE) {
        for (const auto& dep : pch_deps) {
          const std::string& output_value = dep.value();
          size_t extension_offset = FindExtensionOffset(output_value);
          if (extension_offset == std::string::npos)
            continue;
          std::string output_extension;
          if (tool->precompiled_header_type() == CTool::PCH_MSVC) {
            output_extension = GetWindowsPCHObjectExtension(
                tool_name, output_value.substr(extension_offset - 1));
          } else if (tool->precompiled_header_type() == CTool::PCH_GCC) {
            output_extension = GetGCCPCHOutputExtension(tool_name);
          }
          if (output_value.compare(
                  output_value.size() - output_extension.size(),
                  output_extension.size(), output_extension) == 0) {
            deps.push_back(dep);
          }
        }
      }

      for (const auto& module_dep : module_dep_info) {
        if (tool_outputs[0] != module_dep.pcm)
          deps.push_back(module_dep.pcm);
      }

      WriteCompilerBuildLine({source}, deps, order_only_deps, tool_name,
                             tool_outputs);
      WritePool(out_);
    }

    // It's theoretically possible for a compiler to produce more than one
    // output, but we'll only link to the first output.
    if (!source.IsModuleMapType()) {
      object_files->push_back(tool_outputs[0]);
    }
  }

  out_ << std::endl;
}

void NinjaCBinaryTargetWriter::WriteSwiftSources(
    const std::vector<OutputFile>& input_deps,
    const std::vector<OutputFile>& order_only_deps,
    std::vector<OutputFile>* object_files) {
  DCHECK(target_->source_types_used().SwiftSourceUsed());
  object_files->reserve(object_files->size() + target_->sources().size());

  // If the target contains .swift source files, they needs to be compiled as
  // a single unit but still can produce more than one object file (if the
  // whole module optimization is disabled).
  if (target_->source_types_used().SwiftSourceUsed()) {
    const Tool* tool =
        target_->toolchain()->GetToolForSourceType(SourceFile::SOURCE_SWIFT);

    const OutputFile swiftmodule_output_file =
        target_->swift_values().module_output_file();

    std::vector<OutputFile> additional_outputs;
    SubstitutionWriter::ApplyListToLinkerAsOutputFile(
        target_, tool, tool->outputs(), &additional_outputs);

    additional_outputs.erase(
        std::remove(additional_outputs.begin(), additional_outputs.end(),
                    swiftmodule_output_file),
        additional_outputs.end());

    for (const OutputFile& output : additional_outputs) {
      const SourceFile output_as_source =
          output.AsSourceFile(target_->settings()->build_settings());

      if (output_as_source.IsObjectType()) {
        object_files->push_back(output);
      }
    }

    const SubstitutionList& partial_outputs_subst = tool->partial_outputs();
    if (!partial_outputs_subst.list().empty()) {
      // Avoid re-allocation during loop.
      std::vector<OutputFile> partial_outputs;
      for (const auto& source : target_->sources()) {
        if (!source.IsSwiftType())
          continue;

        partial_outputs.resize(0);
        SubstitutionWriter::ApplyListToCompilerAsOutputFile(
            target_, source, partial_outputs_subst, &partial_outputs);

        for (const OutputFile& output : partial_outputs) {
          additional_outputs.push_back(output);
          SourceFile output_as_source =
              output.AsSourceFile(target_->settings()->build_settings());
          if (output_as_source.IsObjectType()) {
            object_files->push_back(output);
          }
        }
      }
    }

    UniqueVector<OutputFile> swift_order_only_deps;
    swift_order_only_deps.reserve(order_only_deps.size());
    swift_order_only_deps.Append(order_only_deps.begin(),
                                 order_only_deps.end());

    for (const Target* swiftmodule :
         resolved().GetSwiftModuleDependencies(target_))
      swift_order_only_deps.push_back(swiftmodule->dependency_output_file());

    WriteCompilerBuildLine(target_->sources(), input_deps,
                           swift_order_only_deps.vector(), tool->name(),
                           {swiftmodule_output_file}, false);

    if (!additional_outputs.empty()) {
      out_ << std::endl;
      WriteCompilerBuildLine(
          {swiftmodule_output_file.AsSourceFile(settings_->build_settings())},
          input_deps, swift_order_only_deps.vector(),
          GeneralTool::kGeneralToolStamp, additional_outputs, false);
    }
  }

  out_ << std::endl;
}

void NinjaCBinaryTargetWriter::WriteLinkerStuff(
    const std::vector<OutputFile>& object_files,
    const std::vector<SourceFile>& other_files,
    const std::vector<OutputFile>& input_deps) {
  std::vector<OutputFile> output_files;
  SubstitutionWriter::ApplyListToLinkerAsOutputFile(
      target_, tool_, tool_->outputs(), &output_files);

  out_ << "build";
  path_output_.WriteFiles(out_, output_files);

  out_ << ": " << rule_prefix_
       << Tool::GetToolTypeForTargetFinalOutput(target_);

  ClassifiedDeps classified_deps = GetClassifiedDeps();

  // Object files.
  path_output_.WriteFiles(out_, object_files);
  path_output_.WriteFiles(out_, classified_deps.extra_object_files);

  // Dependencies.
  std::vector<OutputFile> implicit_deps;
  std::vector<OutputFile> solibs;
  for (const Target* cur : classified_deps.linkable_deps) {
    // All linkable deps should have a link output file.
    DCHECK(!cur->link_output_file().value().empty())
        << "No link output file for "
        << target_->label().GetUserVisibleName(false);

    if (cur->output_type() == Target::RUST_LIBRARY ||
        cur->output_type() == Target::RUST_PROC_MACRO)
      continue;

    if (cur->dependency_output_file().value() !=
        cur->link_output_file().value()) {
      // This is a shared library with separate link and deps files. Save for
      // later.
      implicit_deps.push_back(cur->dependency_output_file());
      solibs.push_back(cur->link_output_file());
    } else {
      // Normal case, just link to this target.
      out_ << " ";
      path_output_.WriteFile(out_, cur->link_output_file());
    }
  }

  const SourceFile* optional_def_file = nullptr;
  if (!other_files.empty()) {
    for (const SourceFile& src_file : other_files) {
      if (src_file.IsDefType()) {
        optional_def_file = &src_file;
        implicit_deps.push_back(
            OutputFile(settings_->build_settings(), src_file));
        break;  // Only one def file is allowed.
      }
    }
  }

  // Libraries specified by paths.
  for (const auto& lib : resolved().GetLinkedLibraries(target_)) {
    if (lib.is_source_file()) {
      implicit_deps.push_back(
          OutputFile(settings_->build_settings(), lib.source_file()));
    }
  }

  // If any target creates a framework bundle, then treat it as an implicit
  // dependency via the .stamp file. This is a pessimisation as it is not
  // always necessary to relink the current target if one of the framework
  // is regenerated, but it ensure that if one of the framework API changes,
  // any dependent target will relink it (see crbug.com/1037607).
  for (const Target* dep : classified_deps.framework_deps) {
    implicit_deps.push_back(dep->dependency_output_file());
  }

  // The input dependency is only needed if there are no object files, as the
  // dependency is normally provided transitively by the source files.
  std::copy(input_deps.begin(), input_deps.end(),
            std::back_inserter(implicit_deps));

  // Any C++ target which depends on a Rust .rlib has to depend on its entire
  // tree of transitive rlibs found inside the linking target (which excludes
  // rlibs only depended on inside a shared library dependency).
  std::vector<OutputFile> transitive_rustlibs;
  if (target_->IsFinal()) {
    for (const auto& inherited : resolved().GetInheritedLibraries(target_)) {
      const Target* dep = inherited.target();
      if (dep->output_type() == Target::RUST_LIBRARY) {
        transitive_rustlibs.push_back(dep->dependency_output_file());
        implicit_deps.push_back(dep->dependency_output_file());
      }
    }
  }

  // Swift modules from dependencies (and possibly self).
  std::vector<OutputFile> swiftmodules;
  if (target_->IsFinal()) {
    for (const Target* dep : classified_deps.swiftmodule_deps) {
      swiftmodules.push_back(dep->swift_values().module_output_file());
      implicit_deps.push_back(dep->swift_values().module_output_file());
    }
    if (target_->builds_swift_module()) {
      swiftmodules.push_back(target_->swift_values().module_output_file());
      implicit_deps.push_back(target_->swift_values().module_output_file());
    }
  }

  // Append implicit dependencies collected above.
  if (!implicit_deps.empty()) {
    out_ << " |";
    path_output_.WriteFiles(out_, implicit_deps);
  }

  // Append data dependencies as order-only dependencies.
  //
  // This will include data dependencies and input dependencies (like when
  // this target depends on an action). Having the data dependencies in this
  // list ensures that the data is available at runtime when the user builds
  // this target.
  //
  // The action dependencies are not strictly necessary in this case. They
  // should also have been collected via the input deps stamp that each source
  // file has for an order-only dependency, and since this target depends on
  // the sources, there is already an implicit order-only dependency. However,
  // it's extra work to separate these out and there's no disadvantage to
  // listing them again.
  WriteOrderOnlyDependencies(classified_deps.non_linkable_deps);

  // End of the link "build" line.
  out_ << std::endl;

  // The remaining things go in the inner scope of the link line.
  if (target_->output_type() == Target::EXECUTABLE ||
      target_->output_type() == Target::SHARED_LIBRARY ||
      target_->output_type() == Target::LOADABLE_MODULE) {
    out_ << "  ldflags =";
    WriteLinkerFlags(out_, tool_, optional_def_file);
    out_ << std::endl;
    out_ << "  libs =";
    WriteLibs(out_, tool_);
    out_ << std::endl;
    out_ << "  frameworks =";
    WriteFrameworks(out_, tool_);
    out_ << std::endl;
    out_ << "  swiftmodules =";
    WriteSwiftModules(out_, tool_, swiftmodules);
    out_ << std::endl;
  } else if (target_->output_type() == Target::STATIC_LIBRARY) {
    out_ << "  arflags =";
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::arflags,
                                         GetFlagOptions(), out_);
    out_ << std::endl;
  }
  WriteOutputSubstitutions();
  WriteLibsList("solibs", solibs);
  WriteLibsList("rlibs", transitive_rustlibs);
  WritePool(out_);
}

void NinjaCBinaryTargetWriter::WriteOutputSubstitutions() {
  out_ << "  output_extension = "
       << SubstitutionWriter::GetLinkerSubstitution(
              target_, tool_, &SubstitutionOutputExtension);
  out_ << std::endl;
  out_ << "  output_dir = "
       << SubstitutionWriter::GetLinkerSubstitution(target_, tool_,
                                                    &SubstitutionOutputDir);
  out_ << std::endl;
}

void NinjaCBinaryTargetWriter::WriteLibsList(
    const std::string& label,
    const std::vector<OutputFile>& libs) {
  if (libs.empty())
    return;

  out_ << "  " << label << " =";
  PathOutput output(path_output_.current_dir(),
                    settings_->build_settings()->root_path_utf8(),
                    ESCAPE_NINJA_COMMAND);
  output.WriteFiles(out_, libs);
  out_ << std::endl;
}

void NinjaCBinaryTargetWriter::WriteOrderOnlyDependencies(
    const UniqueVector<const Target*>& non_linkable_deps) {
  if (!non_linkable_deps.empty()) {
    out_ << " ||";

    // Non-linkable targets.
    for (auto* non_linkable_dep : non_linkable_deps) {
      out_ << " ";
      path_output_.WriteFile(out_, non_linkable_dep->dependency_output_file());
    }
  }
}

bool NinjaCBinaryTargetWriter::CheckForDuplicateObjectFiles(
    const std::vector<OutputFile>& files) const {
  std::set<std::string> set;
  for (const auto& file : files) {
    if (!set.insert(file.value()).second) {
      Err err(
          target_->defined_from(), "Duplicate object file",
          "The target " + target_->label().GetUserVisibleName(false) +
              "\ngenerates two object files with the same name:\n  " +
              file.value() +
              "\n"
              "\n"
              "It could be you accidentally have a file listed twice in the\n"
              "sources. Or, depending on how your toolchain maps sources to\n"
              "object files, two source files with the same name in different\n"
              "directories could map to the same object file.\n"
              "\n"
              "In the latter case, either rename one of the files or move one "
              "of\n"
              "the sources to a separate source_set to avoid them both being "
              "in\n"
              "the same target.");
      g_scheduler->FailWithError(err);
      return false;
    }
  }
  return true;
}
