// 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_rust_binary_target_writer.h"

#include <sstream>

#include "base/strings/string_util.h"
#include "gn/deps_iterator.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/rust_substitution_type.h"
#include "gn/substitution_writer.h"
#include "gn/target.h"

namespace {

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

void WriteVar(const char* name,
              const std::string& value,
              EscapeOptions opts,
              std::ostream& out) {
  out << name << " = ";
  EscapeStringToStream(out, value, opts);
  out << std::endl;
}

void WriteCrateVars(const Target* target,
                    const Tool* tool,
                    EscapeOptions opts,
                    std::ostream& out) {
  WriteVar(kRustSubstitutionCrateName.ninja_name,
           target->rust_values().crate_name(), opts, out);

  std::string crate_type;
  switch (target->rust_values().crate_type()) {
    // Auto-select the crate type for executables, static libraries, and rlibs.
    case RustValues::CRATE_AUTO: {
      switch (target->output_type()) {
        case Target::EXECUTABLE:
          crate_type = "bin";
          break;
        case Target::STATIC_LIBRARY:
          crate_type = "staticlib";
          break;
        case Target::RUST_LIBRARY:
          crate_type = "rlib";
          break;
        case Target::RUST_PROC_MACRO:
          crate_type = "proc-macro";
          break;
        default:
          NOTREACHED();
      }
      break;
    }
    case RustValues::CRATE_BIN:
      crate_type = "bin";
      break;
    case RustValues::CRATE_CDYLIB:
      crate_type = "cdylib";
      break;
    case RustValues::CRATE_DYLIB:
      crate_type = "dylib";
      break;
    case RustValues::CRATE_PROC_MACRO:
      crate_type = "proc-macro";
      break;
    case RustValues::CRATE_RLIB:
      crate_type = "rlib";
      break;
    case RustValues::CRATE_STATICLIB:
      crate_type = "staticlib";
      break;
    default:
      NOTREACHED();
  }
  WriteVar(kRustSubstitutionCrateType.ninja_name, crate_type, opts, out);

  WriteVar(SubstitutionOutputExtension.ninja_name,
           SubstitutionWriter::GetLinkerSubstitution(
               target, tool, &SubstitutionOutputExtension),
           opts, out);
  WriteVar(SubstitutionOutputDir.ninja_name,
           SubstitutionWriter::GetLinkerSubstitution(target, tool,
                                                     &SubstitutionOutputDir),
           opts, out);
}

}  // namespace

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

NinjaRustBinaryTargetWriter::~NinjaRustBinaryTargetWriter() = default;

// TODO(juliehockett): add inherited library support? and IsLinkable support?
// for c-cross-compat
void NinjaRustBinaryTargetWriter::Run() {
  DCHECK(target_->output_type() != Target::SOURCE_SET);

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

  std::vector<OutputFile> input_deps =
      WriteInputsPhonyAndGetDep(num_output_uses);

  WriteCompilerVars();

  // Classify our dependencies.
  ClassifiedDeps classified_deps = GetClassifiedDeps();

  // 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. See
  // the comment on NinjaCBinaryTargetWriter::Run for more detailed explanation.
  std::vector<OutputFile> order_only_deps = WriteInputDepsPhonyAndGetDep(
      std::vector<const Target*>(), num_output_uses);
  std::copy(input_deps.begin(), input_deps.end(),
            std::back_inserter(order_only_deps));

  // Build lists which will go into different bits of the rustc command line.
  // Public rust_library deps go in a --extern rlibs, public non-rust deps go in
  // -Ldependency. Also assemble a list of extra (i.e. implicit) deps
  // for ninja dependency tracking.
  UniqueVector<OutputFile> implicit_deps;
  AppendSourcesAndInputsToImplicitDeps(&implicit_deps);
  implicit_deps.Append(classified_deps.extra_object_files.begin(),
                       classified_deps.extra_object_files.end());

  std::vector<OutputFile> rustdeps;
  std::vector<OutputFile> nonrustdeps;
  nonrustdeps.insert(nonrustdeps.end(),
                     classified_deps.extra_object_files.begin(),
                     classified_deps.extra_object_files.end());
  for (const auto* framework_dep : classified_deps.framework_deps) {
    CHECK(framework_dep->dependency_output_file());
    order_only_deps.push_back(*framework_dep->dependency_output_file());
  }
  for (const auto* non_linkable_dep : classified_deps.non_linkable_deps) {
    if (non_linkable_dep->dependency_output_file_or_phony()) {
      if (non_linkable_dep->source_types_used().RustSourceUsed() &&
          non_linkable_dep->output_type() != Target::SOURCE_SET) {
        rustdeps.push_back(
            *non_linkable_dep->dependency_output_file_or_phony());
      }
      order_only_deps.push_back(
          *non_linkable_dep->dependency_output_file_or_phony());
    }
  }
  for (const auto* linkable_dep : classified_deps.linkable_deps) {
    if (linkable_dep->source_types_used().RustSourceUsed()) {
      rustdeps.push_back(linkable_dep->link_output_file());
    } else {
      nonrustdeps.push_back(linkable_dep->link_output_file());
    }
    CHECK(linkable_dep->dependency_output_file());
    implicit_deps.push_back(*linkable_dep->dependency_output_file());
  }

  // Rust libraries specified by paths.
  for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
    const ConfigValues& cur = iter.cur();
    for (const auto& e : cur.externs()) {
      if (e.second.is_source_file()) {
        implicit_deps.push_back(
            OutputFile(settings_->build_settings(), e.second.source_file()));
      }
    }
  }

  // Bubble up the full list of transitive rlib dependencies.
  std::vector<OutputFile> transitive_rustlibs;
  for (const auto* dep :
       target_->rust_values().transitive_libs().GetOrdered()) {
    if (dep->source_types_used().RustSourceUsed()) {
      CHECK(dep->dependency_output_file());
      transitive_rustlibs.push_back(*dep->dependency_output_file());
    }
  }

  std::vector<OutputFile> tool_outputs;
  SubstitutionWriter::ApplyListToLinkerAsOutputFile(
      target_, tool_, tool_->outputs(), &tool_outputs);
  WriteCompilerBuildLine({target_->rust_values().crate_root()},
                         implicit_deps.vector(), order_only_deps, tool_->name(),
                         tool_outputs);

  std::vector<const Target*> extern_deps(
      classified_deps.linkable_deps.vector());
  std::copy(classified_deps.non_linkable_deps.begin(),
            classified_deps.non_linkable_deps.end(),
            std::back_inserter(extern_deps));
  WriteExterns(extern_deps);
  WriteRustdeps(transitive_rustlibs, rustdeps, nonrustdeps);
  WriteSourcesAndInputs();
}

void NinjaRustBinaryTargetWriter::WriteCompilerVars() {
  const SubstitutionBits& subst = target_->toolchain()->substitution_bits();

  EscapeOptions opts = GetFlagOptions();
  WriteCrateVars(target_, tool_, opts, out_);

  WriteOneFlag(target_, &kRustSubstitutionRustFlags, false, Tool::kToolNone,
               &ConfigValues::rustflags, opts, path_output_, out_);

  WriteOneFlag(target_, &kRustSubstitutionRustEnv, false, Tool::kToolNone,
               &ConfigValues::rustenv, opts, path_output_, out_);

  WriteSharedVars(subst);
}

void NinjaRustBinaryTargetWriter::AppendSourcesAndInputsToImplicitDeps(
    UniqueVector<OutputFile>* deps) const {
  // Only the crate_root file needs to be given to rustc as input.
  // Any other 'sources' are just implicit deps.
  // Most Rust targets won't bother specifying the "sources =" line
  // because it is handled sufficiently by crate_root and the generation
  // of depfiles by rustc. But for those which do...
  for (const auto& source : target_->sources()) {
    deps->push_back(OutputFile(settings_->build_settings(), source));
  }
  for (const auto& data : target_->config_values().inputs()) {
    deps->push_back(OutputFile(settings_->build_settings(), data));
  }
}

void NinjaRustBinaryTargetWriter::WriteSourcesAndInputs() {
  out_ << "  sources =";
  for (const auto& source : target_->sources()) {
    out_ << " ";
    path_output_.WriteFile(out_, OutputFile(settings_->build_settings(), source));
  }
  for (const auto& data : target_->config_values().inputs()) {
    out_ << " ";
    path_output_.WriteFile(out_, OutputFile(settings_->build_settings(), data));
  }
  out_ << std::endl;
}

void NinjaRustBinaryTargetWriter::WriteExterns(
    const std::vector<const Target*>& deps) {
  out_ << "  externs =";

  for (const Target* target : deps) {
    if (target->output_type() == Target::RUST_LIBRARY ||
        target->output_type() == Target::RUST_PROC_MACRO) {
      CHECK(target->dependency_output_file());
      out_ << " --extern ";
      const auto& renamed_dep =
          target_->rust_values().aliased_deps().find(target->label());
      if (renamed_dep != target_->rust_values().aliased_deps().end()) {
        out_ << renamed_dep->second << "=";
      } else {
        out_ << std::string(target->rust_values().crate_name()) << "=";
      }
      path_output_.WriteFile(out_, *target->dependency_output_file());
    }
  }

  EscapeOptions extern_escape_opts;
  extern_escape_opts.mode = ESCAPE_NINJA_COMMAND;

  for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
    const ConfigValues& cur = iter.cur();
    for (const auto& e : cur.externs()) {
      out_ << " --extern " << std::string(e.first) << "=";
      if (e.second.is_source_file()) {
        path_output_.WriteFile(out_, e.second.source_file());
      } else {
        EscapeStringToStream(out_, e.second.value(), extern_escape_opts);
      }
    }
  }

  out_ << std::endl;
}

void NinjaRustBinaryTargetWriter::WriteRustdeps(
    const std::vector<OutputFile>& transitive_rustdeps,
    const std::vector<OutputFile>& rustdeps,
    const std::vector<OutputFile>& nonrustdeps) {
  out_ << "  rustdeps =";

  // Rust dependencies.
  UniqueVector<SourceDir> transitive_rustdep_dirs;
  for (const auto& rustdep : transitive_rustdeps) {
    // TODO switch to using --extern priv: after stabilization
    transitive_rustdep_dirs.push_back(
        rustdep.AsSourceFile(settings_->build_settings()).GetDir());
  }
  for (const auto& rustdepdir : transitive_rustdep_dirs) {
    out_ << " -Ldependency=";
    path_output_.WriteDir(out_, rustdepdir, PathOutput::DIR_NO_LAST_SLASH);
  }

  EscapeOptions lib_escape_opts;
  lib_escape_opts.mode = ESCAPE_NINJA_COMMAND;
  const std::string_view lib_prefix("lib");

  // Non-Rust native dependencies.
  UniqueVector<SourceDir> nonrustdep_dirs;
  for (const auto& nonrustdep : nonrustdeps) {
    nonrustdep_dirs.push_back(
        nonrustdep.AsSourceFile(settings_->build_settings()).GetDir());
  }
  // First -Lnative to specify search directories
  for (const auto& nonrustdep_dir : nonrustdep_dirs) {
    out_ << " -Lnative=";
    path_output_.WriteDir(out_, nonrustdep_dir, PathOutput::DIR_NO_LAST_SLASH);
  }
  // Now the dependencies themselves.
  for (const auto& nonrustdep : nonrustdeps) {
    std::string_view file = FindFilenameNoExtension(&nonrustdep.value());
    if (!file.compare(0, lib_prefix.size(), lib_prefix)) {
      out_ << " -l";
      EscapeStringToStream(out_, file.substr(lib_prefix.size()),
                           lib_escape_opts);
    } else {
      out_ << " -Clink-arg=";
      path_output_.WriteFile(out_, nonrustdep);
    }
  }

  WriteLinkerFlags(out_, tool_, nullptr);
  WriteLibs(out_, tool_);
  out_ << std::endl;
}
