// Copyright 2015 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/runtime_deps.h"

#include <optional>
#include <sstream>
#include <unordered_map>

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "gn/build_settings.h"
#include "gn/builder.h"
#include "gn/deps_iterator.h"
#include "gn/filesystem_utils.h"
#include "gn/loader.h"
#include "gn/output_file.h"
#include "gn/scheduler.h"
#include "gn/settings.h"
#include "gn/string_output_buffer.h"
#include "gn/switches.h"
#include "gn/target.h"
#include "gn/trace.h"

namespace {

using RuntimeDepsVector = std::vector<std::pair<OutputFile, const Target*>>;

// Returns an OutputFile given a string that looks like a source.
std::string SourceAsOutputFile(const std::string& str, const Target* source) {
  return RebasePath(str, source->settings()->build_settings()->build_dir(),
                    source->settings()->build_settings()->root_path_utf8());
}

// Runs `on_file` for each output file and target. To avoid duplicate traversals
// of targets, the set of targets that have been found so far is passed. The
// "value" of the seen_targets map is a boolean indicating if the seen dep was a
// data dep (true = data_dep). data deps add more stuff, so we will want to
// revisit a target if it's a data dependency and we've previously only seen it
// as a regular dep. `on_file` may be called more than once for the same output
// file.
template <typename F>
void RecursiveCollectRuntimeDeps(
    const Target* target,
    bool is_target_data_dep,
    F&& on_file,
    std::unordered_map<const Target*, bool>* seen_targets) {
  auto [found_seen_target, inserted] =
      seen_targets->try_emplace(target, is_target_data_dep);
  if (!inserted) {
    // Already visited.
    if (found_seen_target->second || !is_target_data_dep) {
      // Already visited as a data dep, or the current dep is not a data
      // dep so visiting again will be a no-op.
      return;
    }
    // In the else case, the previously seen target was a regular dependency
    // and we'll now process it as a data dependency.
    found_seen_target->second = is_target_data_dep;
  }

  // Add the main output file for executables, shared libraries, and
  // loadable modules.
  if (target->output_type() == Target::EXECUTABLE ||
      target->output_type() == Target::LOADABLE_MODULE ||
      target->output_type() == Target::SHARED_LIBRARY) {
    for (const auto& runtime_output : target->runtime_outputs())
      on_file(runtime_output.value(), target);
  }

  // Add all data files.
  for (const auto& file : target->data())
    on_file(SourceAsOutputFile(file, target), target);

  // Actions/copy have all outputs considered when the're a data dep.
  if (is_target_data_dep && (target->output_type() == Target::ACTION ||
                             target->output_type() == Target::ACTION_FOREACH ||
                             target->output_type() == Target::COPY_FILES)) {
    std::vector<SourceFile> outputs;
    target->action_values().GetOutputsAsSourceFiles(target, &outputs);
    for (const auto& output_file : outputs)
      on_file(SourceAsOutputFile(output_file.value(), target), target);
  }

  // Data dependencies.
  for (const auto& dep_pair : target->data_deps()) {
    RecursiveCollectRuntimeDeps(dep_pair.ptr, true, on_file, seen_targets);
  }

  // Do not recurse into bundle targets. A bundle's dependencies should be
  // copied into the bundle itself for run-time access.
  if (target->output_type() == Target::CREATE_BUNDLE) {
    SourceDir bundle_root_dir =
        target->bundle_data().GetBundleRootDirOutputAsDir(target->settings());
    on_file(SourceAsOutputFile(bundle_root_dir.value(), target), target);
    return;
  }

  // Non-data dependencies (both public and private).
  for (const auto& dep_pair : target->GetDeps(Target::DEPS_LINKED)) {
    if (dep_pair.ptr->output_type() == Target::EXECUTABLE)
      continue;  // Skip executables that aren't data deps.
    if (dep_pair.ptr->output_type() == Target::SHARED_LIBRARY &&
        (target->output_type() == Target::ACTION ||
         target->output_type() == Target::ACTION_FOREACH)) {
      // Skip shared libraries that action depends on,
      // unless it were listed in data deps.
      continue;
    }
    RecursiveCollectRuntimeDeps(dep_pair.ptr, false, on_file, seen_targets);
  }
}

// Streams the output file for all runtime deps of `target` to `out`.
void StreamRuntimeDeps(const Target* target, std::ostream& out) {
  std::unordered_map<const Target*, bool> seen_targets;

  // The initial target is not considered a data dependency so that actions's
  // outputs (if the current target is an action) are not automatically
  // considered data deps.
  auto on_file = [&out](std::string_view output_file,
                        const Target* target) -> void {
    out << output_file << std::endl;
  };
  RecursiveCollectRuntimeDeps(target, false, on_file, &seen_targets);
}

bool CollectRuntimeDepsFromFlag(const BuildSettings* build_settings,
                                const Builder& builder,
                                RuntimeDepsVector* files_to_write,
                                Err* err) {
  std::string deps_target_list_file =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueString(
          switches::kRuntimeDepsListFile);

  if (deps_target_list_file.empty())
    return true;

  std::string list_contents;
  ScopedTrace load_trace(TraceItem::TRACE_FILE_LOAD, deps_target_list_file);
  if (!base::ReadFileToString(UTF8ToFilePath(deps_target_list_file),
                              &list_contents)) {
    *err = Err(Location(),
               std::string("File for --") + switches::kRuntimeDepsListFile +
                   " doesn't exist.",
               "The file given was \"" + deps_target_list_file + "\"");
    return false;
  }
  load_trace.Done();

  SourceDir root_dir("//");
  Label default_toolchain_label = builder.loader()->GetDefaultToolchain();
  for (const auto& line : base::SplitString(
           list_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
    if (line.empty())
      continue;
    Label label =
        Label::Resolve(root_dir, build_settings->root_path_utf8(),
                       default_toolchain_label, Value(nullptr, line), err);
    if (err->has_error())
      return false;

    const Item* item = builder.GetItem(label);
    const Target* target = item ? item->AsTarget() : nullptr;
    if (!target) {
      *err =
          Err(Location(),
              "The label \"" + label.GetUserVisibleName(true) +
                  "\" isn't a target.",
              "When reading the line:\n  " + line +
                  "\n"
                  "from the --" +
                  switches::kRuntimeDepsListFile + "=" + deps_target_list_file);
      return false;
    }

    std::optional<OutputFile> output_file;
    const char extension[] = ".runtime_deps";
    if (target->output_type() == Target::SHARED_LIBRARY ||
        target->output_type() == Target::LOADABLE_MODULE) {
      // Force the first output for shared-library-type linker outputs since
      // the dependency output files might not be the main output.
      CHECK(!target->computed_outputs().empty());
      std::string path(target->computed_outputs()[0].value());
      path.append(extension);
      output_file = OutputFile(std::move(path));
    } else if (target->has_dependency_output_file()) {
      std::string path(target->dependency_output_file().value());
      path.append(extension);
      output_file = OutputFile(std::move(path));
    } else {
      // If there is no dependency_output_file, this target's dependency output
      // is either a phony alias or was elided entirely (due to lack of real
      // inputs). In either case, there is no file to add an additional
      // extension to, so we should compute our own name in the OBJ BuildDir.
      output_file = GetOutputFile(*target, BuildDirType::OBJ,
                                  target->GetComputedOutputName(), extension);
    }
    if (output_file)
      files_to_write->emplace_back(*output_file, target);
  }
  return true;
}

bool WriteRuntimeDepsFile(const OutputFile& output_file,
                          const Target* target,
                          Err* err) {
  SourceFile output_as_source =
      output_file.AsSourceFile(target->settings()->build_settings());
  base::FilePath data_deps_file =
      target->settings()->build_settings()->GetFullPath(output_as_source);

  StringOutputBuffer storage;
  std::ostream contents(&storage);
  StreamRuntimeDeps(target, contents);

  ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, output_as_source.value());
  return storage.WriteToFileIfChanged(data_deps_file, err);
}

}  // namespace

const char kRuntimeDeps_Help[] =
    R"(Runtime dependencies

  Runtime dependencies of a target are exposed via the "runtime_deps" category
  of "gn desc" (see "gn help desc") or they can be written at build generation
  time via write_runtime_deps(), or --runtime-deps-list-file (see "gn help
  --runtime-deps-list-file").

  To a first approximation, the runtime dependencies of a target are the set of
  "data" files, data directories, and the shared libraries from all transitive
  dependencies. Executables, shared libraries, and loadable modules are
  considered runtime dependencies of themselves.

Executables

  Executable targets and those executable targets' transitive dependencies are
  not considered unless that executable is listed in "data_deps". Otherwise, GN
  assumes that the executable (and everything it requires) is a build-time
  dependency only.

Actions and copies

  Action and copy targets that are listed as "data_deps" will have all of their
  outputs and data files considered as runtime dependencies. Action and copy
  targets that are "deps" or "public_deps" will have only their data files
  considered as runtime dependencies. These targets can list an output file in
  both the "outputs" and "data" lists to force an output file as a runtime
  dependency in all cases.

  The different rules for deps and data_deps are to express build-time (deps)
  vs. run-time (data_deps) outputs. If GN counted all build-time copy steps as
  data dependencies, there would be a lot of extra stuff, and if GN counted all
  run-time dependencies as regular deps, the build's parallelism would be
  unnecessarily constrained.

  This rule can sometimes lead to unintuitive results. For example, given the
  three targets:
    A  --[data_deps]-->  B  --[deps]-->  ACTION
  GN would say that A does not have runtime deps on the result of the ACTION,
  which is often correct. But the purpose of the B target might be to collect
  many actions into one logic unit, and the "data"-ness of A's dependency is
  lost. Solutions:

   - List the outputs of the action in its data section (if the results of
     that action are always runtime files).
   - Have B list the action in data_deps (if the outputs of the actions are
     always runtime files).
   - Have B list the action in both deps and data deps (if the outputs might be
     used in both contexts and you don't care about unnecessary entries in the
     list of files required at runtime).
   - Split B into run-time and build-time versions with the appropriate "deps"
     for each.

Static libraries and source sets

  The results of static_library or source_set targets are not considered
  runtime dependencies since these are assumed to be intermediate targets only.
  If you need to list a static library as a runtime dependency, you can
  manually compute the .a/.lib file name for the current platform and list it
  in the "data" list of a target (possibly on the static library target
  itself).

Multiple outputs

  Linker tools can specify which of their outputs should be considered when
  computing the runtime deps by setting runtime_outputs. If this is unset on
  the tool, the default will be the first output only.
)";

RuntimeDepsVector ComputeRuntimeDeps(const Target* target) {
  RuntimeDepsVector result;
  std::unordered_map<const Target*, bool> seen_targets;

  auto on_file = [&result](std::string_view output_file, const Target* target) {
    result.emplace_back(OutputFile(output_file), target);
  };
  // The initial target is not considered a data dependency so that actions's
  // outputs (if the current target is an action) are not automatically
  // considered data deps.
  RecursiveCollectRuntimeDeps(target, false, on_file, &seen_targets);
  return result;
}

bool WriteRuntimeDepsFilesIfNecessary(const BuildSettings* build_settings,
                                      const Builder& builder) {
  RuntimeDepsVector files_to_write;
  Err err;
  if (!CollectRuntimeDepsFromFlag(build_settings, builder, &files_to_write,
                                  &err)) {
    err.PrintToStdout();
    return false;
  }
  for (auto& entry : files_to_write) {
    g_scheduler->ScheduleWork(
        [output_file = std::move(entry.first), target = entry.second]() {
          Err err;
          if (!WriteRuntimeDepsFile(output_file, target, &err)) {
            g_scheduler->FailWithError(err);
          }
        });
  }

  // Files scheduled by write_runtime_deps.
  for (const Target* target : g_scheduler->GetWriteRuntimeDepsTargets()) {
    g_scheduler->ScheduleWork(
        [output_file = target->write_runtime_deps_output(), target]() {
          Err err;
          if (!WriteRuntimeDepsFile(output_file, target, &err)) {
            g_scheduler->FailWithError(err);
          }
        });
  }

  return g_scheduler->Run();
}
