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

#include "gn/settings.h"
#include "gn/source_file.h"
#include "gn/string_utils.h"
#include "gn/variables.h"
#include "util/build_config.h"
#include "util/sys_info.h"

const char kBuildArgs_Help[] =
    R"(Build Arguments Overview

  Build arguments are variables passed in from outside of the build that build
  files can query to determine how the build works.

How build arguments are set

  First, system default arguments are set based on the current system. The
  built-in arguments are:
   - gn_version
   - host_cpu
   - host_os
   - current_cpu
   - current_os
   - target_cpu
   - target_os

  Next, project-specific overrides are applied. These are specified inside
  the default_args variable of //.gn. See "gn help dotfile" for more. Note
  that during processing of the dotfile itself, only `gn_version` is defined.

  If specified, arguments from the --args command line flag are used. If that
  flag is not specified, args from previous builds in the build directory will
  be used (this is in the file args.gn in the build directory).

  Last, for targets being compiled with a non-default toolchain, the toolchain
  overrides are applied. These are specified in the toolchain_args section of a
  toolchain definition. The use-case for this is that a toolchain may be
  building code for a different platform, and that it may want to always
  specify Posix, for example. See "gn help toolchain" for more.

  If you specify an override for a build argument that never appears in a
  "declare_args" call, a nonfatal error will be displayed.

Examples

  gn args out/FooBar
      Create the directory out/FooBar and open an editor. You would type
      something like this into that file:
          enable_doom_melon=false
          os="android"

  gn gen out/FooBar --args="enable_doom_melon=true os=\"android\""
      This will overwrite the build directory with the given arguments. (Note
      that the quotes inside the args command will usually need to be escaped
      for your shell to pass through strings values.)

How build arguments are used

  If you want to use an argument, you use declare_args() and specify default
  values. These default values will apply if none of the steps listed in the
  "How build arguments are set" section above apply to the given argument, but
  the defaults will not override any of these.

  Often, the root build config file will declare global arguments that will be
  passed to all buildfiles. Individual build files can also specify arguments
  that apply only to those files. It is also useful to specify build args in an
  "import"-ed file if you want such arguments to apply to multiple buildfiles.
)";

namespace {

// Removes all entries in |overrides| that are in |declared_overrides|.
void RemoveDeclaredOverrides(const Scope::KeyValueMap& declared_arguments,
                             Scope::KeyValueMap* overrides) {
  for (Scope::KeyValueMap::iterator override = overrides->begin();
       override != overrides->end();) {
    if (declared_arguments.find(override->first) == declared_arguments.end())
      ++override;
    else
      overrides->erase(override++);
  }
}

}  // namespace

Args::ValueWithOverride::ValueWithOverride()
    : default_value(), has_override(false), override_value() {}

Args::ValueWithOverride::ValueWithOverride(const Value& def_val)
    : default_value(def_val), has_override(false), override_value() {}

Args::ValueWithOverride::~ValueWithOverride() = default;

Args::Args() = default;

Args::Args(const Args& other)
    : overrides_(other.overrides_),
      all_overrides_(other.all_overrides_),
      declared_arguments_per_toolchain_(
          other.declared_arguments_per_toolchain_),
      toolchain_overrides_(other.toolchain_overrides_) {}

Args::~Args() = default;

void Args::AddArgOverride(const char* name, const Value& value) {
  std::lock_guard<std::mutex> lock(lock_);

  overrides_[std::string_view(name)] = value;
  all_overrides_[std::string_view(name)] = value;
}

void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
  std::lock_guard<std::mutex> lock(lock_);

  for (const auto& cur_override : overrides) {
    overrides_[cur_override.first] = cur_override.second;
    all_overrides_[cur_override.first] = cur_override.second;
  }
}

void Args::AddDefaultArgOverrides(const Scope::KeyValueMap& overrides) {
  std::lock_guard<std::mutex> lock(lock_);
  for (const auto& cur_override : overrides)
    overrides_[cur_override.first] = cur_override.second;
}

const Value* Args::GetArgOverride(const char* name) const {
  std::lock_guard<std::mutex> lock(lock_);

  Scope::KeyValueMap::const_iterator found =
      all_overrides_.find(std::string_view(name));
  if (found == all_overrides_.end())
    return nullptr;
  return &found->second;
}

std::vector<const Settings*> Args::GetSortedToolchainsLocked() const {
  std::vector<const Settings*> toolchains;
  toolchains.reserve(declared_arguments_per_toolchain_.size());
  for (const auto& map_pair : declared_arguments_per_toolchain_) {
    toolchains.push_back(map_pair.first);
  }
  std::sort(toolchains.begin(), toolchains.end(),
            [](const Settings* a, const Settings* b) -> bool {
              // NOTE: There can be multiple default toolchains in the map!
              // which happens when declare_args() blocks are found in args.gn
              // or some of its imports. This uses a Settings instance with
              // an empty label, where `is_default()` returns true.
              if (a->is_default() != b->is_default())
                return a->is_default();
              return a->toolchain_label() < b->toolchain_label();
            });
  return toolchains;
}

std::optional<Value> Args::GetArgFromAllArguments(const char* name) const {
  // First, look into overrides defined in .gn
  const Value* override = GetArgOverride(name);
  if (override)
    return std::make_optional(*override);

  // Second, look into each toolchain definition, the default one
  // always appear first here.
  std::lock_guard<std::mutex> lock(lock_);

  for (const Settings* toolchain : GetSortedToolchainsLocked()) {
    const auto& value_map = declared_arguments_per_toolchain_[toolchain];
    auto it = value_map.find(name);
    if (it != value_map.end())
      return std::make_optional(it->second);
  }

  // No match
  return std::nullopt;
}

void Args::SetupRootScope(Scope* dest,
                          const Scope::KeyValueMap& toolchain_overrides) const {
  std::lock_guard<std::mutex> lock(lock_);

  SetSystemVarsLocked(dest);

  // Apply overrides for already declared args.
  // (i.e. the system vars we set above)
  ApplyOverridesLocked(overrides_, dest);
  ApplyOverridesLocked(toolchain_overrides, dest);

  OverridesForToolchainLocked(dest) = toolchain_overrides;

  SaveOverrideRecordLocked(toolchain_overrides);
}

bool Args::DeclareArgs(const Scope::KeyValueMap& args,
                       Scope* scope_to_set,
                       Err* err) const {
  std::lock_guard<std::mutex> lock(lock_);

  Scope::KeyValueMap& declared_arguments(
      DeclaredArgumentsForToolchainLocked(scope_to_set));

  const Scope::KeyValueMap& toolchain_overrides(
      OverridesForToolchainLocked(scope_to_set));

  for (const auto& arg : args) {
    // Verify that the value hasn't already been declared. We want each value
    // to be declared only once.
    //
    // The tricky part is that a buildfile can be interpreted multiple times
    // when used from different toolchains, so we can't just check that we've
    // seen it before. Instead, we check that the location matches.
    Scope::KeyValueMap::iterator previously_declared =
        declared_arguments.find(arg.first);
    if (previously_declared != declared_arguments.end()) {
      if (previously_declared->second.origin() != arg.second.origin()) {
        // Declaration location mismatch.
        *err = Err(
            arg.second.origin(), "Duplicate build argument declaration.",
            "Here you're declaring an argument that was already declared "
            "elsewhere.\nYou can only declare each argument once in the entire "
            "build so there is one\ncanonical place for documentation and the "
            "default value. Either move this\nargument to the build config "
            "file (for visibility everywhere) or to a .gni file\nthat you "
            "\"import\" from the files where you need it (preferred).");
        err->AppendSubErr(Err(previously_declared->second.origin(),
                              "Previous declaration.",
                              "See also \"gn help buildargs\" for more on how "
                              "build arguments work."));
        return false;
      }
    } else {
      declared_arguments.insert(arg);
    }

    // In all the cases below, mark the variable used. If a variable is set
    // that's only used in one toolchain, we don't want to report unused
    // variable errors in other toolchains. Also, in some cases it's reasonable
    // for the build file to overwrite the value with a different value based
    // on some other condition without dereferencing the value first.

    // Check whether this argument has been overridden on the toolchain level
    // and use the override instead.
    Scope::KeyValueMap::const_iterator toolchain_override =
        toolchain_overrides.find(arg.first);
    if (toolchain_override != toolchain_overrides.end()) {
      scope_to_set->SetValue(toolchain_override->first,
                             toolchain_override->second,
                             toolchain_override->second.origin());
      scope_to_set->MarkUsed(arg.first);
      continue;
    }

    // Check whether this argument has been overridden and use the override
    // instead.
    Scope::KeyValueMap::const_iterator override = overrides_.find(arg.first);
    if (override != overrides_.end()) {
      scope_to_set->SetValue(override->first, override->second,
                             override->second.origin());
      scope_to_set->MarkUsed(override->first);
      continue;
    }

    scope_to_set->SetValue(arg.first, arg.second, arg.second.origin());
    scope_to_set->MarkUsed(arg.first);
  }

  return true;
}

bool Args::VerifyAllOverridesUsed(Err* err) const {
  std::lock_guard<std::mutex> lock(lock_);
  Scope::KeyValueMap unused_overrides(all_overrides_);
  for (const auto& map_pair : declared_arguments_per_toolchain_)
    RemoveDeclaredOverrides(map_pair.second, &unused_overrides);

  if (unused_overrides.empty())
    return true;

  // Some assignments in args.gn had no effect.  Show an error for the first
  // unused assignment.
  std::string_view name = unused_overrides.begin()->first;
  const Value& value = unused_overrides.begin()->second;

  std::string err_help(
      "The variable \"" + name +
      "\" was set as a build argument\n"
      "but never appeared in a declare_args() block in any buildfile.\n\n"
      "To view all possible args, run \"gn args --list <out_dir>\"");

  // Use all declare_args for a spelling suggestion.
  std::vector<std::string_view> candidates;
  for (const auto& map_pair : declared_arguments_per_toolchain_) {
    for (const auto& declared_arg : map_pair.second)
      candidates.push_back(declared_arg.first);
  }
  std::string_view suggestion = SpellcheckString(name, candidates);
  if (!suggestion.empty())
    err_help = "Did you mean \"" + suggestion + "\"?\n\n" + err_help;

  *err = Err(value.origin(), "Build argument has no effect.", err_help);
  return false;
}

Args::ValueWithOverrideMap Args::GetAllArguments() const {
  ValueWithOverrideMap result;

  std::lock_guard<std::mutex> lock(lock_);

  // Sort the toolchains from declared_arguments_per_toolchain_ so
  // the return value will be deterministic. Always prioritize
  // the default toolchain.
  std::vector<const Settings*> toolchains = GetSortedToolchainsLocked();

  // Default values.
  for (const auto& toolchain : toolchains) {
    const auto& value_map = declared_arguments_per_toolchain_[toolchain];
    for (const auto& arg : value_map) {
      result.insert(std::make_pair(arg.first, ValueWithOverride(arg.second)));
    }
  }

  // Merge in overrides.
  for (const auto& over : overrides_) {
    auto found = result.find(over.first);
    if (found != result.end()) {
      found->second.has_override = true;
      found->second.override_value = over.second;
    }
  }

  return result;
}

void Args::SetSystemVarsLocked(Scope* dest) const {
  // Host OS.
  const char* os = nullptr;
#if defined(OS_WIN) || defined(OS_MSYS)
  os = "win";
#elif defined(OS_MACOSX)
  os = "mac";
#elif defined(OS_LINUX)
  os = "linux";
#elif defined(OS_FREEBSD)
  os = "freebsd";
#elif defined(OS_AIX)
  os = "aix";
#elif defined(OS_OPENBSD)
  os = "openbsd";
#elif defined(OS_HAIKU)
  os = "haiku";
#elif defined(OS_SOLARIS)
  os = "solaris";
#elif defined(OS_NETBSD)
  os = "netbsd";
#elif defined(OS_ZOS)
  os = "zos";
#elif defined(OS_SERENITY)
  os = "serenity";
#else
#error Unknown OS type.
#endif

  // Host architecture.
  static const char kX86[] = "x86";
  static const char kX64[] = "x64";
  static const char kArm[] = "arm";
  static const char kArm64[] = "arm64";
  static const char kMips[] = "mipsel";
  static const char kMips64[] = "mips64el";
  static const char kS390X[] = "s390x";
  static const char kPPC64[] = "ppc64";
  static const char kRISCV32[] = "riscv32";
  static const char kRISCV64[] = "riscv64";
  static const char kE2K[] = "e2k";
  static const char kLOONG64[] = "loong64";
  const char* arch = nullptr;

  // Set the host CPU architecture based on the underlying OS, not
  // whatever the current bit-tedness of the GN binary is.
  std::string os_arch = OperatingSystemArchitecture();
  if (os_arch == "x86" || os_arch == "BePC")
    arch = kX86;
  else if (os_arch == "x86_64")
    arch = kX64;
  else if (os_arch == "aarch64" || os_arch == "arm64")
    arch = kArm64;
  else if (os_arch.substr(0, 3) == "arm")
    arch = kArm;
  else if (os_arch == "mips")
    arch = kMips;
  else if (os_arch == "mips64")
    arch = kMips64;
  else if (os_arch == "s390x")
    arch = kS390X;
  else if (os_arch == "ppc64" || os_arch == "ppc64le")
    // We handle the endianness inside //build/config/host_byteorder.gni.
    // This allows us to use the same toolchain as ppc64 BE
    // and specific flags are included using the host_byteorder logic.
    arch = kPPC64;
  else if (os_arch == "riscv32")
    arch = kRISCV32;
  else if (os_arch == "riscv64")
    arch = kRISCV64;
  else if (os_arch == "e2k")
    arch = kE2K;
  else if (os_arch == "loongarch64")
    arch = kLOONG64;
  else
    CHECK(false) << "OS architecture not handled. (" << os_arch << ")";

  // Save the OS and architecture as build arguments that are implicitly
  // declared. This is so they can be overridden in a toolchain build args
  // override, and so that they will appear in the "gn args" output.
  Value empty_string(nullptr, std::string());

  Value os_val(nullptr, std::string(os));
  dest->SetValue(variables::kHostOs, os_val, nullptr);
  dest->SetValue(variables::kTargetOs, empty_string, nullptr);
  dest->SetValue(variables::kCurrentOs, empty_string, nullptr);

  Value arch_val(nullptr, std::string(arch));
  dest->SetValue(variables::kHostCpu, arch_val, nullptr);
  dest->SetValue(variables::kTargetCpu, empty_string, nullptr);
  dest->SetValue(variables::kCurrentCpu, empty_string, nullptr);

  Scope::KeyValueMap& declared_arguments(
      DeclaredArgumentsForToolchainLocked(dest));
  declared_arguments[variables::kHostOs] = os_val;
  declared_arguments[variables::kCurrentOs] = empty_string;
  declared_arguments[variables::kTargetOs] = empty_string;
  declared_arguments[variables::kHostCpu] = arch_val;
  declared_arguments[variables::kCurrentCpu] = empty_string;
  declared_arguments[variables::kTargetCpu] = empty_string;

  // Mark these variables used so the build config file can override them
  // without getting a warning about overwriting an unused variable.
  dest->MarkUsed(variables::kHostCpu);
  dest->MarkUsed(variables::kCurrentCpu);
  dest->MarkUsed(variables::kTargetCpu);
  dest->MarkUsed(variables::kHostOs);
  dest->MarkUsed(variables::kCurrentOs);
  dest->MarkUsed(variables::kTargetOs);
}

void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values,
                                Scope* scope) const {
  const Scope::KeyValueMap& declared_arguments(
      DeclaredArgumentsForToolchainLocked(scope));

  // Only set a value if it has been declared.
  for (const auto& val : values) {
    Scope::KeyValueMap::const_iterator declared =
        declared_arguments.find(val.first);

    if (declared == declared_arguments.end())
      continue;

    scope->SetValue(val.first, val.second, val.second.origin());
  }
}

void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const {
  for (const auto& val : values)
    all_overrides_[val.first] = val.second;
}

Scope::KeyValueMap& Args::DeclaredArgumentsForToolchainLocked(
    Scope* scope) const {
  return declared_arguments_per_toolchain_[scope->settings()];
}

Scope::KeyValueMap& Args::OverridesForToolchainLocked(Scope* scope) const {
  return toolchain_overrides_[scope->settings()];
}
