// Copyright (c) 2013 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_binary_target_writer.h"

#include <sstream>

#include "base/strings/string_util.h"
#include "gn/config_values_extractors.h"
#include "gn/deps_iterator.h"
#include "gn/filesystem_utils.h"
#include "gn/general_tool.h"
#include "gn/ninja_c_binary_target_writer.h"
#include "gn/ninja_rust_binary_target_writer.h"
#include "gn/ninja_target_command_util.h"
#include "gn/ninja_utils.h"
#include "gn/pool.h"
#include "gn/settings.h"
#include "gn/string_utils.h"
#include "gn/substitution_writer.h"
#include "gn/target.h"
#include "gn/variables.h"

namespace {

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

}  // namespace

NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
                                                 std::ostream& out)
    : NinjaTargetWriter(target, out),
      rule_prefix_(GetNinjaRulePrefixForToolchain(settings_)) {}

NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() = default;

void NinjaBinaryTargetWriter::Run() {
  if (target_->source_types_used().RustSourceUsed()) {
    NinjaRustBinaryTargetWriter writer(target_, out_);
    writer.SetResolvedTargetData(GetResolvedTargetData());
    writer.SetNinjaOutputs(ninja_outputs_);
    writer.Run();
    return;
  }

  NinjaCBinaryTargetWriter writer(target_, out_);
  writer.SetResolvedTargetData(GetResolvedTargetData());
  writer.SetNinjaOutputs(ninja_outputs_);
  writer.Run();
}

std::vector<OutputFile> NinjaBinaryTargetWriter::WriteInputsStampAndGetDep(
    size_t num_stamp_uses) const {
  CHECK(target_->toolchain()) << "Toolchain not set on target "
                              << target_->label().GetUserVisibleName(true);

  UniqueVector<const SourceFile*> inputs;
  for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
    for (const auto& input : iter.cur().inputs()) {
      inputs.push_back(&input);
    }
  }

  if (inputs.size() == 0)
    return std::vector<OutputFile>();  // No inputs

  // If we only have one input, return it directly instead of writing a stamp
  // file for it.
  if (inputs.size() == 1) {
    return std::vector<OutputFile>{
        OutputFile(settings_->build_settings(), *inputs[0])};
  }

  std::vector<OutputFile> outs;
  for (const SourceFile* source : inputs)
    outs.push_back(OutputFile(settings_->build_settings(), *source));

  // If there are multiple inputs, but the stamp file would be referenced only
  // once, don't write it but depend on the inputs directly.
  if (num_stamp_uses == 1u)
    return outs;

  // Make a stamp file.
  OutputFile stamp_file =
      GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
  stamp_file.value().append(target_->label().name());
  stamp_file.value().append(".inputs.stamp");

  out_ << "build ";
  WriteOutput(stamp_file);

  out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
       << GeneralTool::kGeneralToolStamp;

  // File inputs.
  for (const auto* input : inputs) {
    out_ << " ";
    path_output_.WriteFile(out_, *input);
  }

  out_ << std::endl;
  return {stamp_file};
}

NinjaBinaryTargetWriter::ClassifiedDeps
NinjaBinaryTargetWriter::GetClassifiedDeps() const {
  ClassifiedDeps classified_deps;

  const auto& target_deps = resolved().GetTargetDeps(target_);

  // Normal public/private deps.
  for (const Target* dep : target_deps.linked_deps()) {
    ClassifyDependency(dep, &classified_deps);
  }

  // Inherited libraries.
  for (const auto& inherited : resolved().GetInheritedLibraries(target_)) {
    ClassifyDependency(inherited.target(), &classified_deps);
  }

  // Data deps.
  for (const Target* data_dep : target_deps.data_deps())
    classified_deps.non_linkable_deps.push_back(data_dep);

  return classified_deps;
}

void NinjaBinaryTargetWriter::ClassifyDependency(
    const Target* dep,
    ClassifiedDeps* classified_deps) const {
  // Only the following types of outputs have libraries linked into them:
  //  EXECUTABLE
  //  SHARED_LIBRARY
  //  _complete_ STATIC_LIBRARY
  //
  // Child deps of intermediate static libraries get pushed up the
  // dependency tree until one of these is reached, and source sets
  // don't link at all.
  bool can_link_libs = target_->IsFinal();

  if (can_link_libs && dep->builds_swift_module())
    classified_deps->swiftmodule_deps.push_back(dep);

  if (target_->source_types_used().RustSourceUsed() &&
      (target_->output_type() == Target::RUST_LIBRARY ||
       target_->output_type() == Target::STATIC_LIBRARY) &&
      dep->IsLinkable()) {
    // Rust libraries and static libraries aren't final, but need to have the
    // link lines of all transitive deps specified.
    classified_deps->linkable_deps.push_back(dep);
  } else if (dep->output_type() == Target::SOURCE_SET ||
             // If a complete static library depends on an incomplete static
             // library, manually link in the object files of the dependent
             // library as if it were a source set. This avoids problems with
             // braindead tools such as ar which don't properly link dependent
             // static libraries.
             (target_->complete_static_lib() &&
              (dep->output_type() == Target::STATIC_LIBRARY &&
               !dep->complete_static_lib()))) {
    // Source sets have their object files linked into final targets
    // (shared libraries, executables, loadable modules, and complete static
    // libraries). Intermediate static libraries and other source sets
    // just forward the dependency, otherwise the files in the source
    // set can easily get linked more than once which will cause
    // multiple definition errors.
    if (can_link_libs)
      AddSourceSetFiles(dep, &classified_deps->extra_object_files);

    // Add the source set itself as a non-linkable dependency on the current
    // target. This will make sure that anything the source set's stamp file
    // depends on (like data deps) are also built before the current target
    // can be complete. Otherwise, these will be skipped since this target
    // will depend only on the source set's object files.
    classified_deps->non_linkable_deps.push_back(dep);
  } else if (target_->complete_static_lib() && dep->IsFinal()) {
    classified_deps->non_linkable_deps.push_back(dep);
  } else if (can_link_libs && dep->IsLinkable()) {
    classified_deps->linkable_deps.push_back(dep);
  } else if (dep->output_type() == Target::CREATE_BUNDLE &&
             dep->bundle_data().is_framework()) {
    classified_deps->framework_deps.push_back(dep);
  } else {
    classified_deps->non_linkable_deps.push_back(dep);
  }
}

void NinjaBinaryTargetWriter::AddSourceSetFiles(
    const Target* source_set,
    UniqueVector<OutputFile>* obj_files) const {
  std::vector<OutputFile> tool_outputs;  // Prevent allocation in loop.

  // Compute object files for all sources. Only link the first output from
  // the tool if there are more than one.
  for (const auto& source : source_set->sources()) {
    const char* tool_name = Tool::kToolNone;
    if (source_set->GetOutputFilesForSource(source, &tool_name, &tool_outputs))
      obj_files->push_back(tool_outputs[0]);
  }

  // Swift files may generate one object file per module or one per source file
  // depending on how the compiler is invoked (whole module optimization).
  if (source_set->source_types_used().SwiftSourceUsed()) {
    std::vector<OutputFile> outputs;
    source_set->swift_values().GetOutputs(source_set, &outputs);

    for (const OutputFile& output : outputs) {
      SourceFile output_as_source =
          output.AsSourceFile(source_set->settings()->build_settings());
      if (output_as_source.IsObjectType()) {
        obj_files->push_back(output);
      }
    }
  }

  // Add MSVC precompiled header object files. GCC .gch files are not object
  // files so they are omitted.
  if (source_set->config_values().has_precompiled_headers()) {
    if (source_set->source_types_used().Get(SourceFile::SOURCE_C)) {
      const CTool* tool = source_set->toolchain()->GetToolAsC(CTool::kCToolCc);
      if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
        GetPCHOutputFiles(source_set, CTool::kCToolCc, &tool_outputs);
        obj_files->Append(tool_outputs.begin(), tool_outputs.end());
      }
    }
    if (source_set->source_types_used().Get(SourceFile::SOURCE_CPP)) {
      const CTool* tool = source_set->toolchain()->GetToolAsC(CTool::kCToolCxx);
      if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
        GetPCHOutputFiles(source_set, CTool::kCToolCxx, &tool_outputs);
        obj_files->Append(tool_outputs.begin(), tool_outputs.end());
      }
    }
    if (source_set->source_types_used().Get(SourceFile::SOURCE_M)) {
      const CTool* tool =
          source_set->toolchain()->GetToolAsC(CTool::kCToolObjC);
      if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
        GetPCHOutputFiles(source_set, CTool::kCToolObjC, &tool_outputs);
        obj_files->Append(tool_outputs.begin(), tool_outputs.end());
      }
    }
    if (source_set->source_types_used().Get(SourceFile::SOURCE_MM)) {
      const CTool* tool =
          source_set->toolchain()->GetToolAsC(CTool::kCToolObjCxx);
      if (tool && tool->precompiled_header_type() == CTool::PCH_MSVC) {
        GetPCHOutputFiles(source_set, CTool::kCToolObjCxx, &tool_outputs);
        obj_files->Append(tool_outputs.begin(), tool_outputs.end());
      }
    }
  }
}

void NinjaBinaryTargetWriter::WriteCompilerBuildLine(
    const std::vector<SourceFile>& sources,
    const std::vector<OutputFile>& extra_deps,
    const std::vector<OutputFile>& order_only_deps,
    const char* tool_name,
    const std::vector<OutputFile>& outputs,
    bool can_write_source_info,
    bool restat_output_allowed) {
  out_ << "build";
  WriteOutputs(outputs);

  out_ << ": " << rule_prefix_ << tool_name;
  path_output_.WriteFiles(out_, sources);

  if (!extra_deps.empty()) {
    out_ << " |";
    path_output_.WriteFiles(out_, extra_deps);
  }

  if (!order_only_deps.empty()) {
    out_ << " ||";
    path_output_.WriteFiles(out_, order_only_deps);
  }
  out_ << std::endl;

  if (!sources.empty() && can_write_source_info) {
    out_ << "  " << "source_file_part = " << sources[0].GetName();
    out_ << std::endl;
    out_ << "  " << "source_name_part = "
         << FindFilenameNoExtension(&sources[0].value());
    out_ << std::endl;
  }

  if (restat_output_allowed) {
    out_ << "  restat = 1" << std::endl;
  }
}

void NinjaBinaryTargetWriter::WriteCustomLinkerFlags(std::ostream& out,
                                                     const Tool* tool) {
  if (tool->AsC() || (tool->AsRust() && tool->AsRust()->MayLink())) {
    // First the ldflags from the target and its config.
    RecursiveTargetConfigStringsToStream(kRecursiveWriterKeepDuplicates,
                                         target_, &ConfigValues::ldflags,
                                         GetFlagOptions(), out);
  }
}

void NinjaBinaryTargetWriter::WriteLibrarySearchPath(std::ostream& out,
                                                     const Tool* tool) {
  // Write library search paths that have been recursively pushed
  // through the dependency tree.
  const auto& all_lib_dirs = resolved().GetLinkedLibraryDirs(target_);
  if (!all_lib_dirs.empty()) {
    // Since we're passing these on the command line to the linker and not
    // to Ninja, we need to do shell escaping.
    PathOutput lib_path_output(path_output_.current_dir(),
                               settings_->build_settings()->root_path_utf8(),
                               ESCAPE_NINJA_COMMAND);
    for (size_t i = 0; i < all_lib_dirs.size(); i++) {
      out << " " << tool->lib_dir_switch();
      lib_path_output.WriteDir(out, all_lib_dirs[i],
                               PathOutput::DIR_NO_LAST_SLASH);
    }
  }

  const auto& all_framework_dirs = resolved().GetLinkedFrameworkDirs(target_);
  if (!all_framework_dirs.empty()) {
    // Since we're passing these on the command line to the linker and not
    // to Ninja, we need to do shell escaping.
    PathOutput framework_path_output(
        path_output_.current_dir(),
        settings_->build_settings()->root_path_utf8(), ESCAPE_NINJA_COMMAND);
    for (size_t i = 0; i < all_framework_dirs.size(); i++) {
      out << " " << tool->framework_dir_switch();
      framework_path_output.WriteDir(out, all_framework_dirs[i],
                                     PathOutput::DIR_NO_LAST_SLASH);
    }
  }
}

void NinjaBinaryTargetWriter::WriteLinkerFlags(
    std::ostream& out,
    const Tool* tool,
    const SourceFile* optional_def_file) {
  // First any ldflags
  WriteCustomLinkerFlags(out, tool);
  // Then the library search path
  WriteLibrarySearchPath(out, tool);

  if (optional_def_file) {
    out_ << " /DEF:";
    path_output_.WriteFile(out, *optional_def_file);
  }
}

void NinjaBinaryTargetWriter::WriteLibs(std::ostream& out, const Tool* tool) {
  // Libraries that have been recursively pushed through the dependency tree.
  // Since we're passing these on the command line to the linker and not
  // to Ninja, we need to do shell escaping.
  PathOutput lib_path_output(path_output_.current_dir(),
                             settings_->build_settings()->root_path_utf8(),
                             ESCAPE_NINJA_COMMAND);
  EscapeOptions lib_escape_opts;
  lib_escape_opts.mode = ESCAPE_NINJA_COMMAND;
  const auto& all_libs = resolved().GetLinkedLibraries(target_);
  for (size_t i = 0; i < all_libs.size(); i++) {
    const LibFile& lib_file = all_libs[i];
    const std::string& lib_value = lib_file.value();
    if (lib_file.is_source_file()) {
      out << " " << tool->linker_arg();
      lib_path_output.WriteFile(out, lib_file.source_file());
    } else {
      out << " " << tool->lib_switch();
      EscapeStringToStream(out, lib_value, lib_escape_opts);
    }
  }
}

void NinjaBinaryTargetWriter::WriteFrameworks(std::ostream& out,
                                              const Tool* tool) {
  // Frameworks that have been recursively pushed through the dependency tree.
  FrameworksWriter writer(tool->framework_switch());
  const auto& all_frameworks = resolved().GetLinkedFrameworks(target_);
  for (size_t i = 0; i < all_frameworks.size(); i++) {
    writer(all_frameworks[i], out);
  }

  FrameworksWriter weak_writer(tool->weak_framework_switch());
  const auto& all_weak_frameworks = resolved().GetLinkedWeakFrameworks(target_);
  for (size_t i = 0; i < all_weak_frameworks.size(); i++) {
    weak_writer(all_weak_frameworks[i], out);
  }
}

void NinjaBinaryTargetWriter::WriteSwiftModules(
    std::ostream& out,
    const Tool* tool,
    const std::vector<OutputFile>& swiftmodules) {
  // Since we're passing these on the command line to the linker and not
  // to Ninja, we need to do shell escaping.
  PathOutput swiftmodule_path_output(
      path_output_.current_dir(), settings_->build_settings()->root_path_utf8(),
      ESCAPE_NINJA_COMMAND);

  for (const OutputFile& swiftmodule : swiftmodules) {
    out << " " << tool->swiftmodule_switch();
    swiftmodule_path_output.WriteFile(out, swiftmodule);
  }
}

void NinjaBinaryTargetWriter::WritePool(std::ostream& out) {
  if (target_->pool().ptr) {
    out << "  pool = ";
    out << target_->pool().ptr->GetNinjaName(
        settings_->default_toolchain_label());
    out << std::endl;
  }
}
