blob: dc54747b6b80de445eca1b16ed29fa2b28f800df [file]
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("./vars.gni")
# Runs a generator that writes TypeScript sources into $target_gen_dir, where
# a ts_library() with `rootdir = target_gen_dir` compiles them. The generated
# files never live in the source tree.
#
# The generator runs under scripts/build/run_with_restat.py with the action's
# outputs as tracked files: when a run rewrites an output with identical bytes,
# the output keeps its mtime and Ninja's restat prunes everything downstream,
# most notably the tsc invocations of the consuming ts_library(). Generators
# must therefore always write their outputs and leave the write-if-changed
# logic to the wrapper.
#
# Parameters:
# script: The generator, a Python script. It runs under the interpreter that
# runs GN actions.
# outputs: The files the generator writes, all in $target_gen_dir.
# args: Arguments for the generator. Pass input and output paths rebased
# to root_build_dir, as for action().
# inputs: Files the generator reads besides `script`: its data files and the
# modules it imports. Listing them keeps incremental and remote builds
# correct.
# deps, public_deps, testonly, visibility: As for action().
#
# Example (front_end/generated/BUILD.gn):
# import("../../scripts/build/ninja/chromium_deps.gni")
# import("../../scripts/build/ninja/generated_ts.gni")
#
# generated_ts("deprecation") {
# script = "../../scripts/build/generate_deprecations.py"
# inputs = [ devtools_chromium_deps_root +
# "third_party/blink/renderer/core/frame/deprecation/deprecation.json5" ]
# outputs = [ "$target_gen_dir/Deprecation.ts" ]
# args = [
# "--input",
# rebase_path(inputs[0], root_build_dir),
# "--output",
# rebase_path(outputs[0], root_build_dir),
# ]
# }
template("generated_ts") {
assert(defined(invoker.script), "You must specify 'script' for $target_name")
assert(get_path_info(invoker.script, "extension") == "py",
"'script' of $target_name must be a Python script")
assert(defined(invoker.outputs),
"You must specify 'outputs' for $target_name")
assert(filter_exclude(invoker.outputs, [ "$target_gen_dir/*" ]) == [],
"All 'outputs' of $target_name must be in \$target_gen_dir")
action(target_name) {
forward_variables_from(invoker,
[
"deps",
"outputs",
"public_deps",
"testonly",
"visibility",
])
script = devtools_location_prepend + "scripts/build/run_with_restat.py"
inputs = [
invoker.script,
devtools_location_prepend + "scripts/build/response_file.py",
]
if (defined(invoker.inputs)) {
inputs += invoker.inputs
}
args = rebase_path(outputs, root_build_dir) + [
"--",
rebase_path(invoker.script, root_build_dir),
]
if (defined(invoker.args)) {
args += invoker.args
}
}
}