// 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();
}

// python_exe_name and python_bat_name can be empty but cannot be absolute
// paths. They should be "python.exe" or "", etc., and "python.bat" or "", etc.
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.
  if (!python_exe_name.empty()) {
    CHECK(python_exe_name.FinalExtension() == u".exe");
    CHECK_EQ(python_exe_name.IsAbsolute(), false);
    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)) {
    if (!python_exe_name.empty()) {
      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.
    if (!python_bat_name.empty()) {
      CHECK(python_bat_name.FinalExtension() == u".bat");
      CHECK_EQ(python_bat_name.IsAbsolute(), false);
      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.
  auto extension = script_executable.FinalExtension();
  if (script_executable.IsAbsolute()) {
    // Do translation from .bat to .exe but otherwise just pass through.
    if (extension == u".bat")
      script_executable = PythonBatToExe(script_executable);
  } else {
    if (extension == u"") {
      // If no extension is specified then search the path for .exe and .bat
      // variants.
      script_executable =
          FindWindowsPython(script_executable.ReplaceExtension(u".exe"),
                            script_executable.ReplaceExtension(u".bat"));
    } else if (extension == u".bat") {
      // Search the path just for the specified .bat.
      script_executable =
          FindWindowsPython(base::FilePath(), script_executable);
    } else if (extension == u".exe") {
      // Search the path just for the specified .exe.
      script_executable =
          FindWindowsPython(script_executable, base::FilePath());
    }
  }
  script_executable = script_executable.NormalizePathSeparatorsTo('/');
#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);
    build_settings_.set_python_path(ProcessFileExtensions(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)
    base::FilePath python_path =
        ProcessFileExtensions(base::FilePath(u"python"));
    if (!python_path.IsAbsolute()) {
      scheduler_.Log("WARNING",
                     "Could not find python on path, using "
                     "just \"python.exe\"");
      python_path = base::FilePath(u"python.exe");
    }
    build_settings_.set_python_path(python_path);
#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;
}
