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

#include "tools/gn/source_file.h"
#include "tools/gn/string_utils.h"
#include "tools/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:
   - 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.

  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_[base::StringPiece(name)] = value;
  all_overrides_[base::StringPiece(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(base::StringPiece(name));
  if (found == all_overrides_.end())
    return nullptr;
  return &found->second;
}

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.
  base::StringPiece 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<base::StringPiece> candidates;
  for (const auto& map_pair : declared_arguments_per_toolchain_) {
    for (const auto& declared_arg : map_pair.second)
      candidates.push_back(declared_arg.first);
  }
  base::StringPiece 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_);

  // Default values.
  for (const auto& map_pair : declared_arguments_per_toolchain_) {
    for (const auto& arg : map_pair.second)
      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)
  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";
#else
#error Unknown OS type.
#endif
  // NOTE: Adding a new port? Please follow
  // https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md

  // 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";
  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")
    arch = kX86;
  else if (os_arch == "x86_64")
    arch = kX64;
  else if (os_arch.substr(0, 3) == "arm")
    arch = kArm;
  else if (os_arch == "aarch64")
    arch = kArm64;
  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
    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 geting 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()];
}
