blob: cedcbb4f711666971db84b534cfd84a0842ab705 [file] [log] [blame]
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../../../scripts/build/typescript/typescript.gni")
import("./bundle.gni")
import("./copy.gni")
import("./node.gni")
import("./vars.gni")
# This defines an entrypoint for DevTools, which uses Rollup
# in release mode, but creates an unbundled JavaScript file
# in debug mode. This entrypoint should only be used if:
# 1. it defines a file that is statically imported. E.g. in
# the form of "../entrypoint/entrypoint.js".
# 2. it defines a file that is dynamically imported by the
# runtime. This uses the same notation, but uses a dynamic
# import in `core/root/Runtime.js`.
template("devtools_entrypoint") {
assert(defined(invoker.entrypoint),
"You must define the 'entrypoint' for a bundle target")
_entrypoint_target_name = "devtools_entrypoint-" + target_name
_entrypoint_output_file_name = get_path_info(invoker.entrypoint, "name")
_entrypoint_gen_file_location =
"$target_gen_dir/$_entrypoint_output_file_name.js"
_devtools_entrypoint_deps = []
# If we don't bundle, the entrypoint is kept as-is. This means we only
# need to compile with TypeScript/esbuild, which means it will fetch all
# of its files as separate network requests.
if (!devtools_bundle) {
_ts_library_target_name = _entrypoint_target_name + "-typescript"
ts_library(_ts_library_target_name) {
forward_variables_from(invoker, ["deps", "es_target", "es_libs", "inputs"])
sources = [ invoker.entrypoint ]
}
_devtools_entrypoint_deps += [ ":$_ts_library_target_name" ]
} else {
# Otherwise, we are running Rollup and thus bundle all
# files in the (sub-)folder(s) into 1 file.
#
# To make sure that the build system can handle the Rollup
# bundle, we have to use several tasks. That's because we
# can't have 2 tasks generate a file to the same location.
#
# First, we need to compile the entrypoint with TypeScript
# as usual. However, we can't put the output into the
# location of the entrypoint, as that's where we are going
# to put the Rollup bundle output. Therefore, we need to
# create a separate file called the "entrypoint.prebundle.ts"
# file.
#
# We compile the "prebundle.ts" with TypeScript, to create
# the "prebundle.js" file. We pass in the "prebundle.js"
# into Rollup, which then outputs into the normal
# "entrypoint.js" location.
#
# Since TypeScript does not support renaming of files during
# compilation, we first have a "copy" task that copies (and
# essentially renames) the file to the output directory.
#
# Additionally, we need to fix the tsconfig renaming, to patch
# up the generated tsconfig.json as part of the second ts_library
# step.
#
# Since all of these tasks depend on each other, we have to
# make sure that the GN dependency graph correctly corresponds
# to that. Therefore, the graph looks like so:
#
# copy -> ts_library -> fix-tsconfig -> bundle
#
_entrypoint_output_file_name = get_path_info(invoker.entrypoint, "name")
_output_file_name =
"$target_gen_dir/$_entrypoint_output_file_name.prebundle"
_copy_output_file_name = "$_output_file_name.ts"
_prebundle_output_file_name = "$_output_file_name.js"
_copy_target_name = _entrypoint_target_name + "-copy"
_bundle_target_name = _entrypoint_target_name + "-bundle"
_prebundle_target_name = _entrypoint_target_name + "-tsconfig"
node_action(_copy_target_name) {
script = "scripts/build/ninja/copy-file.js"
inputs = [ invoker.entrypoint ]
outputs = [ _copy_output_file_name ]
_copy_src = rebase_path(".", root_build_dir) + "/" + invoker.entrypoint
_copy_dest = rebase_path(_copy_output_file_name, root_build_dir)
args = [
_copy_src,
_copy_dest,
]
public_deps = invoker.deps
}
ts_library(_prebundle_target_name) {
forward_variables_from(invoker, ["deps", "es_target", "es_libs", "inputs"])
sources = [ _copy_output_file_name ]
rootdir = target_gen_dir
public_deps = [ ":$_copy_target_name" ]
}
bundle(_bundle_target_name) {
entrypoint = _prebundle_output_file_name
output_file_location = _entrypoint_gen_file_location
# Since bundles both the entrypoint and the files it imports,
# we have to make sure that, when you change a file it imports, we
# retrigger Rollup. Since the `invoker.deps` is a reference to the
# `ts_library` that compiles all of the files it imports, we have to
# explicitly add it here. If you don't, then the file change will
# retrigger the copy action above, but "the output of the copy action"
# is the same. So Ninja will detect that no output has changed for
# "_typescript_target_name" and bail out. This would then *also* skip
# the Rollup action.
public_deps = [ ":$_prebundle_target_name" ] + invoker.deps
}
if (!devtools_skip_typecheck) {
_generated_declaration_target_name =
_entrypoint_target_name + "-generate-declaration"
# TypeScript requires a `module.d.ts` that describes
# the public API of the `module.js` entrypoint. To do so, we copy
# the generated `prebundle.d.ts` over, as the public API for a
# rolled up bundle remains the same.
node_action(_generated_declaration_target_name) {
script = "scripts/build/ninja/generate-declaration.js"
args = [
rebase_path(target_gen_dir, root_build_dir),
invoker.entrypoint,
]
public_deps = [
":$_bundle_target_name",
":$_prebundle_target_name",
]
outputs = [ "$target_gen_dir/$_entrypoint_output_file_name.d.ts" ]
}
_devtools_entrypoint_deps += [ ":$_generated_declaration_target_name" ]
} else {
_devtools_entrypoint_deps += [
":$_bundle_target_name",
":$_prebundle_target_name",
]
}
}
# Because we change the filename before rolling up the bundle,
# tsc can get upset when it uses the original `target_name` to
# reference a different `ts_library`. The `ts_library` action
# above generates a `tsconfig.json` which does not include the
# `target_name`, but instead uses `_ts_library_target_name`.
#
# For example, if the `target_name` is "module", the `ts_library`
# action above generates a
# `devtools_entrypoint-module-typescript-tsconfig.json`. However,
# if a different `ts_library` depends on this `devtools_entrypoint`,
# it depends on it as "../module:module". Therefore, the expected
# location of the `tsconfig.json` is instead `module-tsconfig.json`.
#
# Therefore, we need to generate a separate tsconfig.json which
# artificially mimics what `ts_library` would have generated.
_generated_tsconfig_location =
target_gen_dir + "/" + invoker.target_name + "-tsconfig.json"
_target_outputs = [ _entrypoint_gen_file_location ]
node_action(target_name) {
script = "scripts/build/ninja/generate-tsconfig.js"
args = [
rebase_path(_generated_tsconfig_location, root_build_dir),
rebase_path(invoker.entrypoint, root_build_dir),
] + invoker.deps
public_deps = _devtools_entrypoint_deps
outputs = [ _generated_tsconfig_location ]
data = _target_outputs
metadata = {
grd_files = _target_outputs
}
if (defined(invoker.visibility)) {
visibility = invoker.visibility
} else {
visibility = [ ":*" ]
}
}
}
set_defaults("devtools_entrypoint") {
inputs = []
}