# Copyright 2026 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.

"""A simple data structure for generating simple Ninja build files."""

import dataclasses
import os
import pathlib
import shlex
import sys


def escape_path_ninja(path):
  return str(path).replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')


def escape_path_command(path):
  # shlex.quote is designed for posix shells and thus won't work on windows.
  # Assume there are no double quotes in the path - seems pretty reasonable.
  return f'"{path}"'



@dataclasses.dataclass
class Action:
  rule: 'DummyRule'
  output: pathlib.Path
  inputs: list[pathlib.Path] = dataclasses.field(default_factory=list)
  implicit_inputs: list[pathlib.Path] = dataclasses.field(default_factory=list)
  variables: dict[str, str] = dataclasses.field(default_factory=dict)

  def __str__(self):
    return str(self.output)


class DummyRule:

  def __init__(self, name, ninja_file, inputs=None):
    self.name = name
    self.ninja_file = ninja_file
    self.inputs = inputs or []

  def __call__(self, output, *, inputs=None, implicit_inputs=None, **kwargs):
    action = Action(
        rule=self,
        output=pathlib.Path(output),
        inputs=inputs or [],
        implicit_inputs=self.inputs + (implicit_inputs or []),
        variables=kwargs,
    )
    self.ninja_file.actions.append(action)
    return action.output


class Rule(DummyRule):

  def __init__(
      self,
      name,
      ninja_file,
      command,
      description=None,
      inputs=None,
      depfile=None,
      deps=None,
      restat=None,
      pool=None,
  ):
    super().__init__(name, ninja_file, inputs)
    self.command = command
    self.description = description
    self.depfile = depfile
    self.deps = deps
    self.restat = restat
    self.pool = pool
    self.ninja_file.rules.append(self)


class NinjaFile:

  def __init__(self, platform, source_root, out_dir, debug=False):
    self.platform = platform
    self.debug = debug
    self.out_dir = pathlib.Path(out_dir).resolve()
    # source_root is relative to out_dir
    self.source_root = pathlib.Path(os.path.relpath(source_root, self.out_dir))

    self.regen_triggers = []
    self.rules = []
    self.actions = []

    self._gn_exe = pathlib.Path('gn' + self.platform.exe_suffix)
    build_prefix = '' if self.platform.is_windows() else './'

    def python(path, args):
      return (
          f'{escape_path_command(sys.executable)}'
          f' {escape_path_command(self.source_file(path))} {args}'
      )

    # Define standard/dummy rules (no rule block generated in build.ninja)
    self.Phony = DummyRule('phony', self)
    self.Cxx = DummyRule('cxx', self)
    self.Link = DummyRule('link', self)

    self.RunBinary = Rule(
        name='run_binary',
        ninja_file=self,
        command=self.chain(
            f'$env {build_prefix}$in $args', python('tools/touch.py', '$out')
        ),
        description='RUN BINARY $in',
    )

    # Define custom rules (rule block generated in build.ninja)
    self._run_gn = Rule(
        name='run_gn',
        ninja_file=self,
        command=self.chain(
            # For golden tests it's very important that if a ninja file is no
            # longer generated, it is actually deleted.
            python('tools/clean.py', '$path/out'),
            f'{build_prefix}{self._gn_exe} gen $path/out --quiet'
            ' --root=$path',
            python('tools/touch.py', '$out'),
        ),
        description='RUN GN $out',
        inputs=[self._gn_exe],
    )

    compare_script = self.source_file('tools/compare_goldens.py')
    self._compare_goldens = Rule(
        name='compare_goldens',
        ninja_file=self,
        command=self.chain(
            python('tools/compare_goldens.py', '$path $goldens'),
            python('tools/touch.py', '$out'),
        ),
        description='COMPARE $out',
        inputs=[compare_script],
    )

    run_cargo_rel_path = 'build/run_cargo.py'
    run_cargo_script = self.source_file(run_cargo_rel_path)
    self.Cargo = Rule(
        name='cargo',
        ninja_file=self,
        command=python(
            run_cargo_rel_path,
            '$target_type $out $cargo_out_dir $cxx "$cxxflags"'
            ' cargo build --color=always'
            ' --manifest-path=$manifest_path $cargo_target_dir $cargo_flags' + ('' if self.debug else ' --release'),
        ),
        description='CARGO build $out',
        inputs=[run_cargo_script],
        depfile='$depfile',
        deps='gcc',
        restat='1',
        pool='cargo_pool',
    )

  def chain(self, *commands):
    joined = ' && '.join(commands)
    if self.platform.is_windows():
      return f'cmd.exe /s /c "{joined}"'
    return joined

  def source_file(self, path):
    return self.source_root / path

  @property
  def rust_profile(self):
    return 'debug' if self.debug else 'release'

  def CargoLibTarget(self, name, *, crate_dir, target_dir, cargo_flags='', **kwargs):
    return self.Cargo(
        name,
        inputs=self.directory(crate_dir, ['target', 'testdata']),
        manifest_path=crate_dir / 'Cargo.toml',
        cargo_target_dir=f'--target-dir={target_dir}',
        cargo_flags=cargo_flags + ' --lib',
        target_type='lib',
        cargo_out_dir=f'{target_dir}/{self.rust_profile}',
        depfile=f'{name}.d',
        **kwargs,
    )

  def CargoTestTarget(self, name, *, crate_dir, target_dir, cargo_flags='', **kwargs):
    return self.Cargo(
        name,
        inputs=self.directory(crate_dir, ['target']),
        manifest_path=crate_dir / 'Cargo.toml',
        cargo_target_dir=f'--target-dir={target_dir}',
        cargo_flags=cargo_flags + ' --tests',
        target_type='test',
        cargo_out_dir=f'{target_dir}/{self.rust_profile}',
        depfile=f'{name}.d',
        **kwargs,
    )

  def directory(self, dir_path, exclude_dirs):
    # Join out_dir with dir_path (which is relative to out_dir) to get absolute path for filesystem walk
    full_dir_path = (self.out_dir / dir_path).resolve()
    inputs = []
    for root, dirs, files in os.walk(full_dir_path):
      for exc in exclude_dirs:
        if exc in dirs:
          dirs.remove(exc)
      root = pathlib.Path(os.path.relpath(root, self.out_dir))
      self.regen_triggers.append(root)
      inputs.append(root)
      for file in files:
        inputs.append(root / file)
    return sorted(inputs)

  # IntegrationTest is a macro more so than a rule.
  def IntegrationTest(self, name):
    path = self.source_file(f'integration_tests/{name}')
    inputs = self.directory(path, ['out', 'goldens'])
    golden_path = path / 'goldens'

    stamp = self._run_gn(name, path=path, inputs=inputs)

    return self._compare_goldens(
        name + '_integration_test',
        inputs=[stamp] + self.directory(golden_path, []),
        path=path / 'out',
        goldens=golden_path,
    )

  def write_ninja(self):
    out = []
    for rule in self.rules:
      out.append(f'rule {rule.name}')
      out.append(f'  command = {getattr(rule, "command", "")}')
      out.append(f'  description = {getattr(rule, "description", "")}')
      if rule.depfile is not None:
        out.append(f'  depfile = {rule.depfile}')
      if rule.deps is not None:
        out.append(f'  deps = {rule.deps}')
      if rule.restat is not None:
        out.append(f'  restat = {rule.restat}')
      if rule.pool is not None:
        out.append(f'  pool = {rule.pool}')
      out.append('')

    for action in self.actions:
      inputs = ' '.join([escape_path_ninja(p) for p in action.inputs])
      inputs = f' {inputs}' if inputs else ''

      implicit = ' '.join(
          [escape_path_ninja(p) for p in action.implicit_inputs]
      )
      implicit = f' | {implicit}' if implicit else ''

      out.append(f'build {action.output}: {action.rule.name}{inputs}{implicit}')
      for k, v in action.variables.items():
        out.append(f'  {k} = {v}')
      out.append('')

    return '\n'.join(out)
