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

#include <stdlib.h>

#include <algorithm>
#include <memory>
#include <sstream>
#include <utility>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "gn/command_format.h"
#include "gn/commands.h"
#include "gn/exec_process.h"
#include "gn/filesystem_utils.h"
#include "gn/input_file.h"
#include "gn/parse_tree.h"
#include "gn/parser.h"
#include "gn/source_dir.h"
#include "gn/source_file.h"
#include "gn/standard_out.h"
#include "gn/switches.h"
#include "gn/tokenizer.h"
#include "gn/trace.h"
#include "gn/value.h"
#include "gn/value_extractors.h"
#include "util/build_config.h"

#if defined(OS_WIN)
#include <windows.h>

#include "base/win/scoped_process_information.h"
#include "base/win/win_util.h"
#endif

const char kDotfile_Help[] =
    R"(.gn file

  When gn starts, it will search the current directory and parent directories
  for a file called ".gn". This indicates the source root. You can override
  this detection by using the --root command-line argument

  The .gn file in the source root will be executed. The syntax is the same as a
  buildfile, but with very limited build setup-specific meaning.

  If you specify --root, by default GN will look for the file .gn in that
  directory. If you want to specify a different file, you can additionally pass
  --dotfile:

    gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn

Variables

  arg_file_template [optional]
      Path to a file containing the text that should be used as the default
      args.gn content when you run `gn args`.

  buildconfig [required]
      Path to the build config file. This file will be used to set up the
      build file execution environment for each toolchain.

  check_targets [optional]
      A list of labels and label patterns that should be checked when running
      "gn check" or "gn gen --check". If neither check_targets or
      no_check_targets (see below) is specified, all targets will be checked.
      It is an error to specify both check_targets and no_check_targets. If it
      is the empty list, no targets will be checked. To bypass this list,
      request an explicit check of targets, like "//*".

      The format of this list is identical to that of "visibility" so see "gn
      help visibility" for examples.

  no_check_targets [optional]
      A list of labels and label patterns that should *not* be checked when
      running "gn check" or "gn gen --check". All other targets will be checked.
      If neither check_targets (see above) or no_check_targets is specified, all
      targets will be checked. It is an error to specify both check_targets and
      no_check_targets.

      The format of this list is identical to that of "visibility" so see "gn
      help visibility" for examples.

  check_system_includes [optional]
      Boolean to control whether system style includes are checked by default
      when running "gn check" or "gn gen --check".  System style includes are
      includes that use angle brackets <> instead of double quotes "". If this
      setting is omitted or set to false, these includes will be ignored by
      default. They can be checked explicitly by running
      "gn check --check-system" or "gn gen --check=system"

  exec_script_whitelist [optional]
      A list of .gn/.gni files (not labels) that have permission to call the
      exec_script function. If this list is defined, calls to exec_script will
      be checked against this list and GN will fail if the current file isn't
      in the list.

      This is to allow the use of exec_script to be restricted since is easy to
      use inappropriately. Wildcards are not supported. Files in the
      secondary_source tree (if defined) should be referenced by ignoring the
      secondary tree and naming them as if they are in the main tree.

      If unspecified, the ability to call exec_script is unrestricted.

      Example:
        exec_script_whitelist = [
          "//base/BUILD.gn",
          "//build/my_config.gni",
        ]

  root [optional]
      Label of the root build target. The GN build will start by loading the
      build file containing this target name. This defaults to "//:" which will
      cause the file //BUILD.gn to be loaded. Note that build_file_extension
      applies to the default case as well.

      The command-line switch --root-target will override this value (see "gn
      help --root-target").

  script_executable [optional]
      Path to specific Python executable or other interpreter to use in
      action targets and exec_script calls. By default GN searches the
      PATH for Python to execute these scripts.

      If set to the empty string, the path specified in action targets
      and exec_script calls will be executed directly.

  secondary_source [optional]
      Label of an alternate directory tree to find input files. When searching
      for a BUILD.gn file (or the build config file discussed above), the file
      will first be looked for in the source root. If it's not found, the
      secondary source root will be checked (which would contain a parallel
      directory hierarchy).

      This behavior is intended to be used when BUILD.gn files can't be checked
      in to certain source directories for whatever reason.

      The secondary source root must be inside the main source tree.

  default_args [optional]
      Scope containing the default overrides for declared arguments. These
      overrides take precedence over the default values specified in the
      declare_args() block, but can be overriden using --args or the
      args.gn file.

      This is intended to be used when subprojects declare arguments with
      default values that need to be changed for whatever reason.

  build_file_extension [optional]
      If set to a non-empty string, this is added to the name of all build files
      to load.
      GN will look for build files named "BUILD.$build_file_extension.gn".
      This is intended to be used during migrations or other situations where
      there are two independent GN builds in the same directories.

  ninja_required_version [optional]
      When set specifies the minimum required version of Ninja. The default
      required version is 1.7.2. Specifying a higher version might enable the
      use of some of newer features that can make the build more efficient.

Example .gn file contents

  buildconfig = "//build/config/BUILDCONFIG.gn"

  check_targets = [
    "//doom_melon/*",  # Check everything in this subtree.
    "//tools:mind_controlling_ant",  # Check this specific target.
  ]

  root = "//:root"

  secondary_source = "//build/config/temporary_buildfiles/"

  default_args = {
    # Default to release builds for this project.
    is_debug = false
    is_component_build = false
  }
)";

namespace {

const base::FilePath::CharType kGnFile[] = FILE_PATH_LITERAL(".gn");
const char kDefaultArgsGn[] =
    "# Set build arguments here. See `gn help buildargs`.";

base::FilePath FindDotFile(const base::FilePath& current_dir) {
  base::FilePath try_this_file = current_dir.Append(kGnFile);
  if (base::PathExists(try_this_file))
    return try_this_file;

  base::FilePath with_no_slash = current_dir.StripTrailingSeparators();
  base::FilePath up_one_dir = with_no_slash.DirName();
  if (up_one_dir == current_dir)
    return base::FilePath();  // Got to the top.

  return FindDotFile(up_one_dir);
}

// Called on any thread. Post the item to the builder on the main thread.
void ItemDefinedCallback(MsgLoop* task_runner,
                         Builder* builder_call_on_main_thread_only,
                         std::unique_ptr<Item> item) {
  DCHECK(item);

  // Increment the work count for the duration of defining the item with the
  // builder. Otherwise finishing this callback will race finishing loading
  // files. If there is no other pending work at any point in the middle of
  // this call completing on the main thread, the 'Complete' function will
  // be signaled and we'll stop running with an incomplete build.
  g_scheduler->IncrementWorkCount();

  // Work around issue binding a unique_ptr with std::function by moving into a
  // shared_ptr.
  auto item_shared = std::make_shared<std::unique_ptr<Item>>(std::move(item));
  task_runner->PostTask(
      [builder_call_on_main_thread_only, item_shared]() mutable {
        builder_call_on_main_thread_only->ItemDefined(std::move(*item_shared));
        g_scheduler->DecrementWorkCount();
      });
}

void DecrementWorkCount() {
  g_scheduler->DecrementWorkCount();
}

#if defined(OS_WIN)

std::u16string SysMultiByteTo16(std::string_view mb) {
  if (mb.empty())
    return std::u16string();

  int mb_length = static_cast<int>(mb.length());
  // Compute the length of the buffer.
  int charcount = MultiByteToWideChar(CP_ACP, 0, mb.data(), mb_length, NULL, 0);
  if (charcount == 0)
    return std::u16string();

  std::u16string wide;
  wide.resize(charcount);
  MultiByteToWideChar(CP_ACP, 0, mb.data(), mb_length, base::ToWCharT(&wide[0]),
                      charcount);

  return wide;
}

// Given the path to a batch file that runs Python, extracts the name of the
// executable actually implementing Python. Generally people write a batch file
// to put something named "python" on the path, which then just redirects to
// a python.exe somewhere else. This step decodes that setup. On failure,
// returns empty path.
base::FilePath PythonBatToExe(const base::FilePath& bat_path) {
  // Note exciting double-quoting to allow spaces. The /c switch seems to check
  // for quotes around the whole thing and then deletes them. If you want to
  // quote the first argument in addition (to allow for spaces in the Python
  // path, you need *another* set of quotes around that, likewise, we need
  // two quotes at the end.
  std::u16string command = u"cmd.exe /c \"\"";
  command.append(bat_path.value());
  command.append(u"\" -c \"import sys; print(sys.executable)\"\"");

  std::string python_path;
  std::string std_err;
  int exit_code;
  base::FilePath cwd;
  GetCurrentDirectory(&cwd);
  if (internal::ExecProcess(command, cwd, &python_path, &std_err, &exit_code) &&
      exit_code == 0 && std_err.empty()) {
    base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path);

    // Python uses the system multibyte code page for sys.executable.
    base::FilePath exe_path(SysMultiByteTo16(python_path));

    // Check for reasonable output, cmd may have output an error message.
    if (base::PathExists(exe_path))
      return exe_path;
  }
  return base::FilePath();
}

base::FilePath FindWindowsPython(const base::FilePath& python_exe_name,
                                 const base::FilePath& python_bat_name) {
  char16_t current_directory[MAX_PATH];
  ::GetCurrentDirectory(MAX_PATH, reinterpret_cast<LPWSTR>(current_directory));

  // First search for python.exe in the current directory.
  base::FilePath cur_dir_candidate_exe =
      base::FilePath(current_directory).Append(python_exe_name);
  if (base::PathExists(cur_dir_candidate_exe))
    return cur_dir_candidate_exe;

  // Get the path.
  const char16_t kPathEnvVarName[] = u"Path";
  DWORD path_length = ::GetEnvironmentVariable(
      reinterpret_cast<LPCWSTR>(kPathEnvVarName), nullptr, 0);
  if (path_length == 0)
    return base::FilePath();
  std::unique_ptr<char16_t[]> full_path(new char16_t[path_length]);
  DWORD actual_path_length = ::GetEnvironmentVariable(
      reinterpret_cast<LPCWSTR>(kPathEnvVarName),
      reinterpret_cast<LPWSTR>(full_path.get()), path_length);
  CHECK_EQ(path_length, actual_path_length + 1);

  // Search for python.exe in the path.
  for (const auto& component : base::SplitStringPiece(
           std::u16string_view(full_path.get(), path_length), u";",
           base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    base::FilePath candidate_exe =
        base::FilePath(component).Append(python_exe_name);
    if (base::PathExists(candidate_exe))
      return candidate_exe;

    // Also allow python.bat, but convert into the .exe.
    base::FilePath candidate_bat =
        base::FilePath(component).Append(python_bat_name);
    if (base::PathExists(candidate_bat)) {
      base::FilePath python_exe = PythonBatToExe(candidate_bat);
      if (!python_exe.empty())
        return python_exe;
    }
  }
  return base::FilePath();
}
#endif

}  // namespace

const char Setup::kBuildArgFileName[] = "args.gn";

Setup::Setup()
    : build_settings_(),
      loader_(new LoaderImpl(&build_settings_)),
      builder_(loader_.get()),
      dotfile_settings_(&build_settings_, std::string()),
      dotfile_scope_(&dotfile_settings_) {
  dotfile_settings_.set_toolchain_label(Label());

  build_settings_.set_item_defined_callback(
      [task_runner = scheduler_.task_runner(),
       builder = &builder_](std::unique_ptr<Item> item) {
        ItemDefinedCallback(task_runner, builder, std::move(item));
      });

  loader_->set_complete_callback(&DecrementWorkCount);
  // The scheduler's task runner wasn't created when the Loader was created, so
  // we need to set it now.
  loader_->set_task_runner(scheduler_.task_runner());
}

bool Setup::DoSetup(const std::string& build_dir, bool force_create) {
  return DoSetup(build_dir, force_create,
                 *base::CommandLine::ForCurrentProcess());
}

bool Setup::DoSetup(const std::string& build_dir,
                    bool force_create,
                    const base::CommandLine& cmdline) {
  Err err;
  if (!DoSetupWithErr(build_dir, force_create, cmdline, &err)) {
    err.PrintToStdout();
    return false;
  }
  DCHECK(!err.has_error());
  return true;
}

bool Setup::DoSetupWithErr(const std::string& build_dir,
                           bool force_create,
                           const base::CommandLine& cmdline,
                           Err* err) {
  scheduler_.set_verbose_logging(cmdline.HasSwitch(switches::kVerbose));
  if (cmdline.HasSwitch(switches::kTime) ||
      cmdline.HasSwitch(switches::kTracelog))
    EnableTracing();

  ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "DoSetup");

  if (!FillSourceDir(cmdline, err))
    return false;
  if (!RunConfigFile(err))
    return false;
  if (!FillOtherConfig(cmdline, err))
    return false;

  // Must be after FillSourceDir to resolve.
  if (!FillBuildDir(build_dir, !force_create, err))
    return false;

  // Apply project-specific default (if specified).
  // Must happen before FillArguments().
  if (default_args_) {
    Scope::KeyValueMap overrides;
    default_args_->GetCurrentScopeValues(&overrides);
    build_settings_.build_args().AddDefaultArgOverrides(overrides);
  }

  if (fill_arguments_) {
    if (!FillArguments(cmdline, err))
      return false;
  }
  if (!FillPythonPath(cmdline, err))
    return false;

  // Check for unused variables in the .gn file.
  if (!dotfile_scope_.CheckForUnusedVars(err)) {
    return false;
  }

  return true;
}

bool Setup::Run() {
  return Run(*base::CommandLine::ForCurrentProcess());
}

bool Setup::Run(const base::CommandLine& cmdline) {
  RunPreMessageLoop();
  if (!scheduler_.Run())
    return false;
  return RunPostMessageLoop(cmdline);
}

SourceFile Setup::GetBuildArgFile() const {
  return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName);
}

void Setup::RunPreMessageLoop() {
  // Will be decremented with the loader is drained.
  g_scheduler->IncrementWorkCount();

  // Load the root build file.
  loader_->Load(root_build_file_, LocationRange(), Label());
}

bool Setup::RunPostMessageLoop(const base::CommandLine& cmdline) {
  Err err;
  if (!builder_.CheckForBadItems(&err)) {
    err.PrintToStdout();
    return false;
  }

  if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) {
    if (cmdline.HasSwitch(switches::kFailOnUnusedArgs)) {
      err.PrintToStdout();
      return false;
    }
    err.PrintNonfatalToStdout();
    OutputString(
        "\nThe build continued as if that argument was "
        "unspecified.\n\n");
    // Nonfatal error.
  }

  if (check_public_headers_) {
    std::vector<const Target*> all_targets = builder_.GetAllResolvedTargets();
    std::vector<const Target*> to_check;
    if (check_patterns()) {
      commands::FilterTargetsByPatterns(all_targets, *check_patterns(),
                                        &to_check);
    } else if (no_check_patterns()) {
      commands::FilterOutTargetsByPatterns(all_targets, *no_check_patterns(),
                                           &to_check);
    } else {
      to_check = all_targets;
    }

    if (!commands::CheckPublicHeaders(&build_settings_, all_targets, to_check,
                                      false, false, check_system_includes_)) {
      return false;
    }
  }

  // Write out tracing and timing if requested.
  if (cmdline.HasSwitch(switches::kTime))
    PrintLongHelp(SummarizeTraces());
  if (cmdline.HasSwitch(switches::kTracelog))
    SaveTraces(cmdline.GetSwitchValuePath(switches::kTracelog));

  return true;
}

bool Setup::FillArguments(const base::CommandLine& cmdline, Err* err) {
  // Use the args on the command line if specified, and save them. Do this even
  // if the list is empty (this means clear any defaults).
  // If --args is not set, args.gn file does not exist and gen_empty_args
  // is set, generate an empty args.gn file with default comments.

  base::FilePath build_arg_file =
      build_settings_.GetFullPath(GetBuildArgFile());
  auto switch_value = cmdline.GetSwitchValueASCII(switches::kArgs);
  if (cmdline.HasSwitch(switches::kArgs) ||
      (gen_empty_args_ && !PathExists(build_arg_file))) {
    if (!FillArgsFromCommandLine(
            switch_value.empty() ? kDefaultArgsGn : switch_value, err)) {
      return false;
    }
    SaveArgsToFile();
    return true;
  }

  // No command line args given, use the arguments from the build dir (if any).
  return FillArgsFromFile(err);
}

bool Setup::FillArgsFromCommandLine(const std::string& args, Err* err) {
  args_input_file_ = std::make_unique<InputFile>(SourceFile());
  args_input_file_->SetContents(args);
  args_input_file_->set_friendly_name("the command-line \"--args\"");
  return FillArgsFromArgsInputFile(err);
}

bool Setup::FillArgsFromFile(Err* err) {
  ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Load args file");

  SourceFile build_arg_source_file = GetBuildArgFile();
  base::FilePath build_arg_file =
      build_settings_.GetFullPath(build_arg_source_file);

  std::string contents;
  if (!base::ReadFileToString(build_arg_file, &contents))
    return true;  // File doesn't exist, continue with default args.

  // Add a dependency on the build arguments file. If this changes, we want
  // to re-generate the build.
  g_scheduler->AddGenDependency(build_arg_file);

  if (contents.empty())
    return true;  // Empty file, do nothing.

  args_input_file_ = std::make_unique<InputFile>(build_arg_source_file);
  args_input_file_->SetContents(contents);
  args_input_file_->set_friendly_name(
      "build arg file (use \"gn args <out_dir>\" to edit)");

  setup_trace.Done();  // Only want to count the load as part of the trace.
  return FillArgsFromArgsInputFile(err);
}

bool Setup::FillArgsFromArgsInputFile(Err* err) {
  ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Parse args");

  args_tokens_ = Tokenizer::Tokenize(args_input_file_.get(), err);
  if (err->has_error()) {
    return false;
  }

  args_root_ = Parser::Parse(args_tokens_, err);
  if (err->has_error()) {
    return false;
  }

  Scope arg_scope(&dotfile_settings_);
  // Set soure dir so relative imports in args work.
  SourceDir root_source_dir =
      SourceDirForCurrentDirectory(build_settings_.root_path());
  arg_scope.set_source_dir(root_source_dir);
  args_root_->Execute(&arg_scope, err);
  if (err->has_error()) {
    return false;
  }

  // Save the result of the command args.
  Scope::KeyValueMap overrides;
  arg_scope.GetCurrentScopeValues(&overrides);
  build_settings_.build_args().AddArgOverrides(overrides);
  build_settings_.build_args().set_build_args_dependency_files(
      arg_scope.build_dependency_files());
  return true;
}

bool Setup::SaveArgsToFile() {
  ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Save args file");

  // For the first run, the build output dir might not be created yet, so do
  // that so we can write a file into it. Ignore errors, we'll catch the error
  // when we try to write a file to it below.
  base::FilePath build_arg_file =
      build_settings_.GetFullPath(GetBuildArgFile());
  base::CreateDirectory(build_arg_file.DirName());

  std::string contents = args_input_file_->contents();
  commands::FormatStringToString(contents, commands::TreeDumpMode::kInactive,
                                 &contents, nullptr);
#if defined(OS_WIN)
  // Use Windows lineendings for this file since it will often open in
  // Notepad which can't handle Unix ones.
  base::ReplaceSubstringsAfterOffset(&contents, 0, "\n", "\r\n");
#endif
  if (base::WriteFile(build_arg_file, contents.c_str(),
                      static_cast<int>(contents.size())) == -1) {
    Err(Location(), "Args file could not be written.",
        "The file is \"" + FilePathToUTF8(build_arg_file) + "\"")
        .PrintToStdout();
    return false;
  }

  // Add a dependency on the build arguments file. If this changes, we want
  // to re-generate the build.
  g_scheduler->AddGenDependency(build_arg_file);

  return true;
}

bool Setup::FillSourceDir(const base::CommandLine& cmdline, Err* err) {
  // Find the .gn file.
  base::FilePath root_path;

  // Prefer the command line args to the config file.
  base::FilePath relative_root_path =
      cmdline.GetSwitchValuePath(switches::kRoot);
  if (!relative_root_path.empty()) {
    root_path = base::MakeAbsoluteFilePath(relative_root_path);
    if (root_path.empty()) {
      *err = Err(Location(), "Root source path not found.",
                 "The path \"" + FilePathToUTF8(relative_root_path) +
                     "\" doesn't exist.");
      return false;
    }

    // When --root is specified, an alternate --dotfile can also be set.
    // --dotfile should be a real file path and not a "//foo" source-relative
    // path.
    base::FilePath dotfile_path =
        cmdline.GetSwitchValuePath(switches::kDotfile);
    if (dotfile_path.empty()) {
      dotfile_name_ = root_path.Append(kGnFile);
    } else {
      dotfile_name_ = base::MakeAbsoluteFilePath(dotfile_path);
      if (dotfile_name_.empty()) {
        *err = Err(Location(), "Could not load dotfile.",
                   "The file \"" + FilePathToUTF8(dotfile_path) +
                       "\" couldn't be loaded.");
        return false;
      }
      // Only set dotfile_name if it was passed explicitly.
      build_settings_.set_dotfile_name(dotfile_name_);
    }
  } else {
    // In the default case, look for a dotfile and that also tells us where the
    // source root is.
    base::FilePath cur_dir;
    base::GetCurrentDirectory(&cur_dir);
    dotfile_name_ = FindDotFile(cur_dir);
    if (dotfile_name_.empty()) {
      *err = Err(
          Location(), "Can't find source root.",
          "I could not find a \".gn\" file in the current directory or any "
          "parent,\nand the --root command-line argument was not specified.");
      return false;
    }
    root_path = dotfile_name_.DirName();
  }

  base::FilePath root_realpath = base::MakeAbsoluteFilePath(root_path);
  if (root_realpath.empty()) {
    *err = Err(Location(), "Can't get the real root path.",
               "I could not get the real path of \"" +
                   FilePathToUTF8(root_path) + "\".");
    return false;
  }
  if (scheduler_.verbose_logging())
    scheduler_.Log("Using source root", FilePathToUTF8(root_realpath));
  build_settings_.SetRootPath(root_realpath);

  return true;
}

bool Setup::FillBuildDir(const std::string& build_dir,
                         bool require_exists,
                         Err* err) {
  SourceDir resolved =
      SourceDirForCurrentDirectory(build_settings_.root_path())
          .ResolveRelativeDir(Value(nullptr, build_dir), err,
                              build_settings_.root_path_utf8());
  if (err->has_error()) {
    return false;
  }

  base::FilePath build_dir_path = build_settings_.GetFullPath(resolved);
  if (!base::CreateDirectory(build_dir_path)) {
    *err = Err(Location(), "Can't create the build dir.",
               "I could not create the build dir \"" +
                   FilePathToUTF8(build_dir_path) + "\".");
    return false;
  }
  base::FilePath build_dir_realpath =
      base::MakeAbsoluteFilePath(build_dir_path);
  if (build_dir_realpath.empty()) {
    *err = Err(Location(), "Can't get the real build dir path.",
               "I could not get the real path of \"" +
                   FilePathToUTF8(build_dir_path) + "\".");
    return false;
  }
  resolved = SourceDirForPath(build_settings_.root_path(), build_dir_realpath);

  if (scheduler_.verbose_logging())
    scheduler_.Log("Using build dir", resolved.value());

  if (require_exists) {
    if (!base::PathExists(
            build_dir_path.Append(FILE_PATH_LITERAL("build.ninja")))) {
      *err = Err(
          Location(), "Not a build directory.",
          "This command requires an existing build directory. I interpreted "
          "your input\n\"" +
              build_dir + "\" as:\n  " + FilePathToUTF8(build_dir_path) +
              "\nwhich doesn't seem to contain a previously-generated build.");
      return false;
    }
  }

  build_settings_.SetBuildDir(resolved);
  return true;
}

// On Chromium repositories on Windows the Python executable can be specified as
// python, python.bat, or python.exe (ditto for python3, and with or without a
// full path specification). This handles all of these cases and returns a fully
// specified path to a .exe file.
// This is currently a NOP on other platforms.
base::FilePath ProcessFileExtensions(base::FilePath script_executable) {
#if defined(OS_WIN)
  // If we have a relative path with no extension such as "python" or
  // "python3" then do a path search on the name with .exe and .bat appended.
  if (!script_executable.IsAbsolute() &&
      script_executable.FinalExtension() == u"") {
    script_executable =
        FindWindowsPython(script_executable.ReplaceExtension(u".exe"),
                          script_executable.ReplaceExtension(u".bat"));
  } else {
    if (script_executable.FinalExtension() == u".bat")
      script_executable = PythonBatToExe(script_executable);
  }
#endif
  return script_executable;
}

bool Setup::FillPythonPath(const base::CommandLine& cmdline, Err* err) {
  // Trace this since it tends to be a bit slow on Windows.
  ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path");
  const Value* value = dotfile_scope_.GetValue("script_executable", true);
  if (cmdline.HasSwitch(switches::kScriptExecutable)) {
    auto script_executable =
        cmdline.GetSwitchValuePath(switches::kScriptExecutable);
    script_executable = ProcessFileExtensions(script_executable);
    build_settings_.set_python_path(script_executable);
  } else if (value) {
    if (!value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }
    build_settings_.set_python_path(
        ProcessFileExtensions(UTF8ToFilePath(value->string_value())));
  } else {
#if defined(OS_WIN)
    const base::FilePath python_exe_name(u"python.exe");
    const base::FilePath python_bat_name(u"python.bat");
    base::FilePath python_path =
        FindWindowsPython(python_exe_name, python_bat_name);
    if (python_path.empty()) {
      scheduler_.Log("WARNING",
                     "Could not find python on path, using "
                     "just \"python.exe\"");
      python_path = python_exe_name;
    }
    build_settings_.set_python_path(python_path.NormalizePathSeparatorsTo('/'));
#else
    build_settings_.set_python_path(base::FilePath("python"));
#endif
  }
  return true;
}

bool Setup::RunConfigFile(Err* err) {
  if (scheduler_.verbose_logging())
    scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_));

  dotfile_input_file_ = std::make_unique<InputFile>(SourceFile("//.gn"));
  if (!dotfile_input_file_->Load(dotfile_name_)) {
    *err = Err(Location(), "Could not load dotfile.",
               "The file \"" + FilePathToUTF8(dotfile_name_) +
                   "\" couldn't be loaded");
    return false;
  }

  dotfile_tokens_ = Tokenizer::Tokenize(dotfile_input_file_.get(), err);
  if (err->has_error()) {
    return false;
  }

  dotfile_root_ = Parser::Parse(dotfile_tokens_, err);
  if (err->has_error()) {
    return false;
  }

  // Add a dependency on the build arguments file. If this changes, we want
  // to re-generate the build. This causes the dotfile to make it into
  // build.ninja.d.
  g_scheduler->AddGenDependency(dotfile_name_);

  // Also add a build dependency to the scope, which is used by `gn analyze`.
  dotfile_scope_.AddBuildDependencyFile(SourceFile("//.gn"));
  dotfile_root_->Execute(&dotfile_scope_, err);
  if (err->has_error()) {
    return false;
  }

  return true;
}

bool Setup::FillOtherConfig(const base::CommandLine& cmdline, Err* err) {
  SourceDir current_dir("//");
  Label root_target_label(current_dir, "");

  // Secondary source path, read from the config file if present.
  // Read from the config file if present.
  const Value* secondary_value =
      dotfile_scope_.GetValue("secondary_source", true);
  if (secondary_value) {
    if (!secondary_value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }
    build_settings_.SetSecondarySourcePath(
        SourceDir(secondary_value->string_value()));
  }

  // Build file names.
  const Value* build_file_extension_value =
      dotfile_scope_.GetValue("build_file_extension", true);
  if (build_file_extension_value) {
    if (!build_file_extension_value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }

    std::string extension = build_file_extension_value->string_value();
    auto normalized_extension = UTF8ToFilePath(extension).value();
    if (normalized_extension.find_first_of(base::FilePath::kSeparators) !=
        base::FilePath::StringType::npos) {
      *err = Err(Location(), "Build file extension '" + extension +
                                 "' cannot " + "contain a path separator");
      return false;
    }
    loader_->set_build_file_extension(extension);
  }

  // Ninja required version.
  const Value* ninja_required_version_value =
      dotfile_scope_.GetValue("ninja_required_version", true);
  if (ninja_required_version_value) {
    if (!ninja_required_version_value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }
    std::optional<Version> version =
        Version::FromString(ninja_required_version_value->string_value());
    if (!version) {
      Err(Location(), "Invalid Ninja version '" +
                          ninja_required_version_value->string_value() + "'")
          .PrintToStdout();
      return false;
    }
    build_settings_.set_ninja_required_version(*version);
  }

  // Root build file.
  if (cmdline.HasSwitch(switches::kRootTarget)) {
    auto switch_value = cmdline.GetSwitchValueASCII(switches::kRootTarget);
    Value root_value(nullptr, switch_value);
    root_target_label = Label::Resolve(current_dir, std::string_view(), Label(),
                                       root_value, err);
    if (err->has_error()) {
      return false;
    }
    if (dotfile_scope_.GetValue("root", true)) {
      // The "kRootTarget" switch overwrites the "root" variable in ".gn".
      dotfile_scope_.MarkUsed("root");
    }
  } else {
    const Value* root_value = dotfile_scope_.GetValue("root", true);
    if (root_value) {
      if (!root_value->VerifyTypeIs(Value::STRING, err)) {
        return false;
      }

      root_target_label = Label::Resolve(current_dir, std::string_view(),
                                         Label(), *root_value, err);
      if (err->has_error()) {
        return false;
      }
    }
  }
  // Set the root build file here in order to take into account the values of
  // "build_file_extension" and "root".
  root_build_file_ = loader_->BuildFileForLabel(root_target_label);
  build_settings_.SetRootTargetLabel(root_target_label);

  // Build config file.
  const Value* build_config_value =
      dotfile_scope_.GetValue("buildconfig", true);
  if (!build_config_value) {
    Err(Location(), "No build config file.",
        "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) +
            "\")\n"
            "didn't specify a \"buildconfig\" value.")
        .PrintToStdout();
    return false;
  } else if (!build_config_value->VerifyTypeIs(Value::STRING, err)) {
    return false;
  }
  build_settings_.set_build_config_file(
      SourceFile(build_config_value->string_value()));

  // Targets to check.
  const Value* check_targets_value =
      dotfile_scope_.GetValue("check_targets", true);
  if (check_targets_value) {
    check_patterns_ = std::make_unique<std::vector<LabelPattern>>();
    ExtractListOfLabelPatterns(&build_settings_, *check_targets_value,
                               current_dir, check_patterns_.get(), err);
    if (err->has_error()) {
      return false;
    }
  }

  // Targets not to check.
  const Value* no_check_targets_value =
      dotfile_scope_.GetValue("no_check_targets", true);
  if (no_check_targets_value) {
    if (check_targets_value) {
      Err(Location(), "Conflicting check settings.",
          "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) +
              "\")\n"
              "specified both check_targets and no_check_targets and at most "
              "one is allowed.")
          .PrintToStdout();
      return false;
    }
    no_check_patterns_ = std::make_unique<std::vector<LabelPattern>>();
    ExtractListOfLabelPatterns(&build_settings_, *no_check_targets_value,
                               current_dir, no_check_patterns_.get(), err);
    if (err->has_error()) {
      return false;
    }
  }

  const Value* check_system_includes_value =
      dotfile_scope_.GetValue("check_system_includes", true);
  if (check_system_includes_value) {
    if (!check_system_includes_value->VerifyTypeIs(Value::BOOLEAN, err)) {
      return false;
    }
    check_system_includes_ = check_system_includes_value->boolean_value();
  }

  // Fill exec_script_whitelist.
  const Value* exec_script_whitelist_value =
      dotfile_scope_.GetValue("exec_script_whitelist", true);
  if (exec_script_whitelist_value) {
    // Fill the list of targets to check.
    if (!exec_script_whitelist_value->VerifyTypeIs(Value::LIST, err)) {
      return false;
    }
    std::unique_ptr<SourceFileSet> whitelist =
        std::make_unique<SourceFileSet>();
    for (const auto& item : exec_script_whitelist_value->list_value()) {
      if (!item.VerifyTypeIs(Value::STRING, err)) {
        return false;
      }
      whitelist->insert(current_dir.ResolveRelativeFile(item, err));
      if (err->has_error()) {
        return false;
      }
    }
    build_settings_.set_exec_script_whitelist(std::move(whitelist));
  }

  // Fill optional default_args.
  const Value* default_args_value =
      dotfile_scope_.GetValue("default_args", true);
  if (default_args_value) {
    if (!default_args_value->VerifyTypeIs(Value::SCOPE, err)) {
      return false;
    }

    default_args_ = default_args_value->scope_value();
  }

  const Value* arg_file_template_value =
      dotfile_scope_.GetValue("arg_file_template", true);
  if (arg_file_template_value) {
    if (!arg_file_template_value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }
    SourceFile path(arg_file_template_value->string_value());
    build_settings_.set_arg_file_template_path(path);
  }

  return true;
}
