// 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_number_conversions.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/label_pattern.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

  The system variables `gn_version`, `host_cpu`, and `host_os` are available
  in the dotfile, but none of the other variables are, because the dotfile is
  processed before args.gn or anything else is processed.

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_allowlist [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_allowlist = [
          "//base/BUILD.gn",
          "//build/my_config.gni",
        ]

  exec_script_whitelist [optional]
      A synonym for "exec_script_allowlist" that exists for backwards
      compatibility. New code should use "exec_script_allowlist" instead.
      If both values are set, only the value in "exec_script_allowlist" will
      have any effect (so don't set both!).

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

      The use of expand_directory is restricted because it encourages
      monolithic build targets with redundant inputs, which can slow down
      the build.

      Example:
        expand_directory_allowlist = [
          "//base/BUILD.gn",
        ]

  export_compile_commands [optional]
      A list of label patterns for which to generate a Clang compilation
      database (see "gn help label_pattern" for the string format).

      When specified, GN will generate a compile_commands.json file in the root
      of the build directory containing information on how to compile each
      source file reachable from any label matching any pattern in the list.
      This is used for Clang-based tooling and some editor integration. See
      https://clang.llvm.org/docs/JSONCompilationDatabase.html

      The switch --add-export-compile-commands to "gn gen" (see "gn help gen")
      appends to this value which provides a per-user way to customize it.

      The deprecated switch --export-compile-commands to "gn gen" (see "gn help
      gen") adds to the export target list using a different format.

      Example:
        export_compile_commands = [
          "//base/*",
          "//tools:doom_melon",
        ]

  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").

  root_patterns [optional]
      A list of label pattern strings. When not defined or empty, the GN build
      graph will contain all targets from any BUILD.gn evaluated in the default
      toolchain context, and their transitive dependencies.

      When set to a non empty list, only the targets in the default toolchain
      matching these patterns, and their transitive dependencies, will be defined
      instead.

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

  script_executable [optional]
      By default, GN runs the scripts used in action targets and exec_script
      calls using the Python interpreter found in PATH. This value specifies the
      Python executable or other interpreter to use instead.

      If set to a path starting with "//", it will be interpreted as relative
      to the source root directory and converted to a build-directory-relative
      path in the generated Ninja files.

      If set to the empty string, the scripts will be executed directly.

      The command-line switch --script-executable will override this value (see
      "gn help --script-executable")

  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 overridden 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.

  no_stamp_files [optional]
      A boolean flag that can be set to generate Ninja files that use phony
      rules instead of stamp files whenever possible. This results in smaller
      Ninja build plans, but requires at least Ninja 1.11.

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

std::unique_ptr<SourceFileSet> FillAllowlist(const Value* value,
                                             const SourceDir& current_dir,
                                             Err* err) {
  if (!value)
    return nullptr;

  if (!value->VerifyTypeIs(Value::LIST, err)) {
    return nullptr;
  }
  auto allowlist = std::make_unique<SourceFileSet>();
  for (const auto& item : value->list_value()) {
    if (!item.VerifyTypeIs(Value::STRING, err)) {
      return nullptr;
    }
    allowlist->insert(current_dir.ResolveRelativeFile(item, err));
    if (err->has_error()) {
      return nullptr;
    }
  }
  return allowlist;
}

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

  dotfile_provider_ =
      std::make_unique<ScopePerFileProvider>(&dotfile_scope_, false, true);

  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::DoSetupForEditing() {
  Err err;
  if (!FillSourceDir(*base::CommandLine::ForCurrentProcess(), &err)) {
    err.PrintToStdout();
    return false;
  }
  if (!RunConfigFile(&err)) {
    err.PrintToStdout();
    return false;
  }
  if (!FillOtherConfig(*base::CommandLine::ForCurrentProcess(), &err)) {
    err.PrintToStdout();
    return false;
  }
  return true;
}

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();
    OutputLogString(
        "\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;
    }

    bool fix = cmdline.HasSwitch("fix");

    if (!commands::CheckPublicHeaders(&build_settings_, all_targets, to_check,
                                      false, false, check_system_includes_, fix,
                                      this)) {
      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.GetSwitchValueString(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 source dir so relative imports in args work.
  arg_scope.set_source_dir(args_input_file_->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.CollectBuildDependencyFiles());
  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,
                                 commands::kDefaultFormatWidth, &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);
    std::string str_val = FilePathToUTF8(script_executable);
    base::FilePath python_path;
    if (str_val.starts_with("//")) {
      SourceFile source_file(std::move(str_val));
      python_path = build_settings_.GetFullPath(source_file);
    } else {
      python_path = std::move(script_executable);
    }
    build_settings_.SetPythonPath(ProcessFileExtensions(python_path));
  } else if (value) {
    if (!value->VerifyTypeIs(Value::STRING, err)) {
      return false;
    }
    // Note that an empty string value is valid, and means that the scripts
    // invoked by actions will be run directly.
    base::FilePath python_path;
    if (!value->string_value().empty()) {
      const std::string& str_val = value->string_value();
      if (str_val.starts_with("//")) {
        SourceFile source_file(str_val);
        python_path = build_settings_.GetFullPath(source_file);
      } else {
        python_path = UTF8ToFilePath(str_val);
      }
      python_path = ProcessFileExtensions(python_path);
      if (python_path.empty()) {
        *err = Err(Location(), "Could not find \"" + value->string_value() +
                                   "\" from dotfile in PATH.");
        return false;
      }
    }
    build_settings_.SetPythonPath(std::move(python_path));
  } 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_.SetPythonPath(std::move(python_path));
#else
    build_settings_.SetPythonPath(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, "");
  std::vector<LabelPattern> root_patterns;

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

  if (cmdline.HasSwitch(switches::kRootPattern)) {
    auto& switches = cmdline.GetSwitches();
    for (auto it = switches.find(switches::kRootPattern);
         it != switches.end() && it->first == switches::kRootPattern; ++it) {
      std::string pattern = base::CommandLine::StringTypeToUTF8(it->second);
      LabelPattern pat = LabelPattern::GetPattern(
          SourceDir("//"), build_settings_.root_path_utf8(),
          Value(nullptr, pattern), err);
      if (err->has_error()) {
        err->AppendSubErr(
            Err(Location(),
                "for the command-line switch --root-pattern=" + pattern));
        return false;
      }
      if (!pat.toolchain().is_null()) {
        *err = Err(Location(),
                   "Root pattern cannot have toolchain suffix: " + pattern);
        return false;
      }
      root_patterns.push_back(std::move(pat));
    }
    // Ensure GN does not complain about the .gn root_patterns value being
    // ignored if it is set.
    (void)dotfile_scope_.GetValue("root_patterns", true);
  } else {
    const Value* root_patterns_value =
        dotfile_scope_.GetValue("root_patterns", true);
    if (root_patterns_value) {
      if (!root_patterns_value->VerifyTypeIs(Value::LIST, err)) {
        return false;
      }
      for (const auto& pattern_value : root_patterns_value->list_value()) {
        if (!pattern_value.VerifyTypeIs(Value::STRING, err))
          return false;

        LabelPattern pat = LabelPattern::GetPattern(
            SourceDir("//"), build_settings_.root_path_utf8(), pattern_value,
            err);
        if (err->has_error())
          return false;
        if (!pat.toolchain().is_null()) {
          *err =
              Err(pattern_value, "Root pattern cannot have toolchain suffix: " +
                                     pattern_value.string_value());
          return false;
        }
        root_patterns.push_back(std::move(pat));
      }
    }
  }

  // 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_settings_.SetRootPatterns(std::move(root_patterns));

  // 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_allowlist.
  const Value* exec_script_allowlist_value =
      dotfile_scope_.GetValue("exec_script_allowlist", true);
  if (!exec_script_allowlist_value) {
    // Check for this value as well, for backwards-compatibility.
    exec_script_allowlist_value =
        dotfile_scope_.GetValue("exec_script_whitelist", true);
  }
  if (exec_script_allowlist_value) {
    build_settings_.set_exec_script_allowlist(
        FillAllowlist(exec_script_allowlist_value, current_dir, err));
    if (err->has_error()) {
      return false;
    }
  }

  // Fill expand_directory_allowlist.
  const Value* expand_directory_allowlist_value =
      dotfile_scope_.GetValue("expand_directory_allowlist", true);

  if (expand_directory_allowlist_value) {
    build_settings_.set_expand_directory_allowlist(
        FillAllowlist(expand_directory_allowlist_value, current_dir, err));
    if (err->has_error()) {
      return false;
    }
  } else {
    // Treat unspecified as empty.
    build_settings_.set_expand_directory_allowlist(
        std::make_unique<SourceFileSet>());
  }

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

  // No stamp files.
  const Value* no_stamp_files_value =
      dotfile_scope_.GetValue("no_stamp_files", true);
  if (no_stamp_files_value) {
    if (!no_stamp_files_value->VerifyTypeIs(Value::BOOLEAN, err)) {
      return false;
    }
    build_settings_.set_no_stamp_files(no_stamp_files_value->boolean_value());
  }

  // Export compile commands.
  const Value* export_cc_value =
      dotfile_scope_.GetValue("export_compile_commands", true);
  if (export_cc_value) {
    if (!ExtractListOfLabelPatterns(&build_settings_, *export_cc_value,
                                    SourceDir("//"), &export_compile_commands_,
                                    err)) {
      return false;
    }
  }

  // Append any additional export compile command patterns from the cmdline.
  for (const std::string& cur :
       cmdline.GetSwitchValueStrings(switches::kAddExportCompileCommands)) {
    LabelPattern pat = LabelPattern::GetPattern(
        SourceDir("//"), build_settings_.root_path_utf8(), Value(nullptr, cur),
        err);
    if (err->has_error()) {
      err->AppendSubErr(Err(
          Location(),
          "for the command-line switch --add-export-compile-commands=" + cur));
      return false;
    }
    export_compile_commands_.push_back(std::move(pat));
  }

  return true;
}
