# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/features.gni")
import(
"//tools/code_coverage/js_source_maps/create_js_source_maps/create_js_source_maps.gni")
import(
"//tools/code_coverage/js_source_maps/merge_js_source_maps/merge_js_source_maps.gni")
import("//tools/grit/grit_rule.gni")
import("//tools/grit/preprocess_if_expr.gni")
import("//tools/polymer/css_to_wrapper.gni")
import("//tools/polymer/html_to_wrapper.gni")
import("//tools/typescript/ts_library.gni")
import("//ui/webui/resources/tools/generate_grd.gni")
import("//ui/webui/resources/tools/minify_js.gni")
import("//ui/webui/resources/tools/optimize_webui.gni")
import("//ui/webui/webui_features.gni")
if (use_blink) {
import("//chrome/common/features.gni")
}
# See documentation at https://chromium.googlesource.com/chromium/src/+/HEAD/docs/webui_build_configuration.md#build_webui
template("build_webui") {
not_needed([ "target_name" ])
forward_variables_from(invoker, [ "grd_prefix" ])
preprocess_dir = "${target_gen_dir}/preprocessed"
ts_out_dir = "${target_gen_dir}/tsc"
if (defined(invoker.ts_out_dir)) {
ts_out_dir = invoker.ts_out_dir
}
optimize = optimize_webui
if (defined(invoker.optimize)) {
optimize = invoker.optimize
}
minify_and_bundle = optimize && defined(invoker.optimize_webui_in_files)
if (!minify_and_bundle) {
minify_only = optimize && !defined(invoker.optimize_webui_in_files)
}
enable_source_maps = false
if (defined(invoker.enable_source_maps)) {
assert(!invoker.enable_source_maps || !optimize)
enable_source_maps = invoker.enable_source_maps
}
# Determine whether a :build_grd or :build_grdp target should be defined.
generate_grdp = false
generate_grd_target_name = "build_grd"
if (defined(invoker.generate_grdp) && invoker.generate_grdp) {
generate_grdp = true
generate_grd_target_name = "build_grdp"
}
### Compute the lists of files that are used across multiple targets.
# At least one of `web_component_files` or 'non_web_component_files` must be
# defined.
assert(defined(invoker.web_component_files) ||
defined(invoker.non_web_component_files))
ts_files = []
if (defined(invoker.web_component_files)) {
ts_files += invoker.web_component_files
}
if (defined(invoker.non_web_component_files)) {
ts_files += invoker.non_web_component_files
}
if (defined(invoker.web_component_files) ||
defined(invoker.icons_html_files)) {
# Files that are passed as input to html_to_wrapper().
html_files = []
if (defined(invoker.web_component_files)) {
foreach(f, invoker.web_component_files) {
html_files += [ string_replace(f, ".ts", ".html") ]
}
}
if (defined(invoker.icons_html_files)) {
html_files += invoker.icons_html_files
}
# Files that are generated by html_to_wrapper().
html_wrapper_files = []
foreach(f, html_files) {
html_wrapper_files += [ f + ".ts" ]
}
}
if (defined(invoker.css_files)) {
# Files that are generated by css_to_wrapper().
css_wrapper_files = []
foreach(f, invoker.css_files) {
css_wrapper_files += [ f + ".ts" ]
}
}
# Generated Mojo JS files.
if (defined(invoker.mojo_files)) {
assert(defined(invoker.mojo_files_deps))
mojo_files = []
foreach(mojo_file, invoker.mojo_files) {
mojo_files += [ get_path_info(invoker.mojo_files, "file") ]
}
}
if (defined(invoker.static_files)) {
# Compute which static_files should be preprocessed.
non_preprocessed_files_filter = [
"*.jpg",
"*.png",
"*.svg",
]
static_non_preprocessed_files =
filter_include(invoker.static_files, non_preprocessed_files_filter)
static_preprocessed_files =
filter_exclude(invoker.static_files, non_preprocessed_files_filter)
}
### Define the various targets that are required by the build pipeline.
# Specifically the order in which these targets are executed is:
#
# 1) preprocess_if_expr()
# 2) create_js_source_maps() (only if |invoker.enable_source_maps| flag is
# true)
# 3) html_to_wrapper(), css_to_wrapper()
# 4) ts_library()
# 5) merge_js_source_maps() (only if the |invoker.enable_source_maps| flag is
# true)
# 6) optimize_webui() (only if invoker.optimize && defined(invoker.optimize_webui_in_files))
# 7) minify_js() (only if invoker.optimize && !defined(invoker.optimize_webui_in_files))
# 8) generate_grd()
# 9) grit()
if (defined(invoker.static_files)) {
preprocess_if_expr("preprocess_static_files") {
visibility = [ ":$generate_grd_target_name" ]
if (use_blink) {
defines = chrome_grit_defines
}
in_folder = "."
out_folder = preprocess_dir
in_files = static_preprocessed_files
out_manifest = "${target_gen_dir}/preprocess_static_files_manifest.json"
}
}
preprocess_if_expr("preprocess_ts_files") {
visibility = [
":build_ts",
":html_wrapper_files",
]
if (enable_source_maps) {
visibility += [ ":create_source_maps" ]
}
if (use_blink) {
defines = chrome_grit_defines
}
in_folder = "."
out_folder = preprocess_dir
if (enable_source_maps) {
out_folder = "${preprocess_dir}/_tmp"
enable_removal_comments = enable_source_maps
}
in_files = ts_files
}
if (enable_source_maps) {
create_js_source_maps("create_source_maps") {
# TODO(dpapad): Make this only visible to ":build_ts" and
# ":html_wrapper_files".
inline_sourcemaps = true
sources =
filter_include(get_target_outputs(":preprocess_ts_files"), [ "*.ts" ])
originals = []
outputs = []
foreach(in_file, sources) {
rebased_path = rebase_path(in_file, "${preprocess_dir}/_tmp")
originals += [ rebased_path ]
outputs += [ "${preprocess_dir}/" + rebased_path ]
}
deps = [ ":preprocess_ts_files" ]
}
}
if (defined(html_files) || defined(invoker.css_files)) {
preprocess_if_expr("preprocess_html_css_files") {
visibility = [
":css_wrapper_files",
":html_wrapper_files",
]
if (use_blink) {
defines = chrome_grit_defines
}
in_folder = "."
out_folder = preprocess_dir
in_files = []
if (defined(html_files)) {
in_files += html_files
}
if (defined(invoker.css_files)) {
in_files += invoker.css_files
}
}
}
if (defined(html_files)) {
html_to_wrapper("html_wrapper_files") {
visibility = [ ":build_ts" ]
deps = [ ":preprocess_html_css_files" ]
in_folder = preprocess_dir
out_folder = preprocess_dir
in_files = html_files
minify = optimize
if (defined(invoker.html_to_wrapper_scheme)) {
scheme = invoker.html_to_wrapper_scheme
}
if (defined(invoker.html_to_wrapper_template)) {
template = invoker.html_to_wrapper_template
if (invoker.html_to_wrapper_template == "detect") {
if (enable_source_maps) {
deps += [ ":create_source_maps" ]
} else {
deps += [ ":preprocess_ts_files" ]
}
}
}
}
}
if (defined(invoker.css_files)) {
css_to_wrapper("css_wrapper_files") {
visibility = [ ":build_ts" ]
deps = [ ":preprocess_html_css_files" ]
in_folder = preprocess_dir
out_folder = preprocess_dir
in_files = invoker.css_files
minify = optimize
if (defined(ohos_arkweb_extensions) && ohos_arkweb_extensions) {
arkweb_as_default_scheme = true
}
}
}
if (defined(invoker.mojo_files_deps)) {
copy("copy_mojo") {
visibility = [ ":build_ts" ]
deps = invoker.mojo_files_deps
sources = invoker.mojo_files
outputs = [ "${preprocess_dir}/{{source_file_part}}" ]
}
}
ts_library("build_ts") {
root_dir = preprocess_dir
out_dir = ts_out_dir
composite = false
if (defined(invoker.ts_composite)) {
composite = invoker.ts_composite
}
if (!composite) {
visibility = [
":$generate_grd_target_name",
":build_bundle",
":build_min_js",
]
if (enable_source_maps) {
visibility += [ ":merge_source_maps" ]
}
}
if (defined(invoker.ts_tsconfig_base)) {
tsconfig_base = invoker.ts_tsconfig_base
} else {
if ((defined(invoker.web_component_files) ||
defined(invoker.icons_html_files)) &&
(!defined(invoker.html_to_wrapper_template) ||
invoker.html_to_wrapper_template != "native")) {
# Default tsconfig is tsconfig_base_polymer.json for Polymer UIs.
# tsconfig_base is left unset (defaults to
# //tools/typescript/tsconfig_base.json) for non-Polymer UIs.
tsconfig_base = "//tools/typescript/tsconfig_base_polymer.json"
}
}
in_files = ts_files
extra_deps = []
if (enable_source_maps) {
# ts_library()'s |enable_source_maps| param inherited from the outer
# scope's enable_source_maps
extra_deps += [ ":create_source_maps" ]
} else {
extra_deps += [ ":preprocess_ts_files" ]
}
if (defined(html_files)) {
in_files += html_wrapper_files
extra_deps += [ ":html_wrapper_files" ]
}
if (defined(invoker.css_files)) {
in_files += css_wrapper_files
extra_deps += [ ":css_wrapper_files" ]
}
if (defined(invoker.ts_deps)) {
deps = invoker.ts_deps
}
if (defined(invoker.ts_definitions)) {
definitions = invoker.ts_definitions
}
if (defined(invoker.ts_path_mappings)) {
path_mappings = invoker.ts_path_mappings
}
if (defined(invoker.mojo_files_deps)) {
assert(defined(invoker.mojo_files))
target_outputs = get_target_outputs(":copy_mojo")
# Add all Mojo JS files produced by `:copy_mojo` as inputs to the TS
# compiler.
foreach(o, target_outputs) {
in_files += [ rebase_path(o, preprocess_dir) ]
}
extra_deps += [ ":copy_mojo" ]
}
if (defined(invoker.ts_extra_deps)) {
extra_deps += invoker.ts_extra_deps
}
}
if (enable_source_maps) {
merge_js_source_maps("merge_source_maps") {
deps = [ ":build_ts" ]
manifest_files =
filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
js_files = filter_include(get_target_outputs(":build_ts"), [ "*.js" ])
sources = []
outputs = []
out_dir = "$target_gen_dir/merge_source_maps"
foreach(_js_file, js_files) {
sources += [ _js_file ]
outputs += [ string_replace(_js_file, ts_out_dir, out_dir) ]
}
}
}
if (minify_and_bundle) {
bundle_manifest = "bundle_manifest.json"
optimize_webui("build_bundle") {
visibility = [ ":$generate_grd_target_name" ]
host = invoker.optimize_webui_host
input = rebase_path(ts_out_dir, root_build_dir)
js_module_in_files = invoker.optimize_webui_in_files
out_manifest = "$target_gen_dir/$bundle_manifest"
if (defined(invoker.optimize_webui_excludes)) {
excludes = invoker.optimize_webui_excludes
}
if (defined(invoker.optimize_webui_external_paths)) {
external_paths = invoker.optimize_webui_external_paths
}
deps = [ ":build_ts" ]
}
} else if (minify_only) {
minify_js("build_min_js") {
visibility = [ ":$generate_grd_target_name" ]
in_folder = ts_out_dir
out_folder = "$target_gen_dir/minified"
in_files = []
js_files = filter_include(get_target_outputs(":build_ts"), [ "*.js" ])
foreach(_js_file, js_files) {
in_files += [ string_replace(_js_file, "$ts_out_dir/", "") ]
}
deps = [ ":build_ts" ]
}
}
generate_grd(generate_grd_target_name) {
if (!generate_grdp) {
visibility = [ ":resources_grit" ]
}
grd_prefix = grd_prefix
out_grd = "$target_gen_dir/resources.grd"
if (generate_grdp) {
out_grd = "$target_gen_dir/resources.grdp"
}
deps = []
manifest_files = []
if (defined(invoker.static_files)) {
input_files = static_non_preprocessed_files
input_files_base_dir = rebase_path(".", "//")
deps += [ ":preprocess_static_files" ]
manifest_files +=
[ "${target_gen_dir}/preprocess_static_files_manifest.json" ]
}
if (minify_and_bundle) {
deps += [ ":build_bundle" ]
manifest_files += [ "$target_gen_dir/$bundle_manifest" ]
resource_path_rewrites = []
foreach(f, invoker.optimize_webui_in_files) {
name = get_path_info(f, "name")
output_file = string_replace(f, "${name}.js", "${name}.rollup.js")
resource_path_rewrites += [ "${output_file}|${f}" ]
}
} else if (minify_only) {
deps += [ ":build_min_js" ]
manifest_files += [ "$target_gen_dir/minify_js_manifest.json" ]
} else {
if (enable_source_maps) {
deps += [ ":merge_source_maps" ]
manifest_files +=
filter_include(get_target_outputs(":merge_source_maps"),
[ "*.manifest" ])
} else {
deps += [ ":build_ts" ]
manifest_files +=
filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ])
}
}
if (defined(invoker.extra_grdp_deps)) {
deps += invoker.extra_grdp_deps
grdp_files = invoker.extra_grdp_files
}
if (defined(invoker.grd_resource_path_prefix)) {
resource_path_prefix = invoker.grd_resource_path_prefix
}
}
if (!generate_grdp) {
grit("resources") {
if (use_blink) {
defines = chrome_grit_defines
}
# These arguments are needed since the grd is generated at build time.
enable_input_discovery_for_gn_analyze = false
source = "$target_gen_dir/resources.grd"
deps = [ ":$generate_grd_target_name" ]
outputs = [
"grit/${grd_prefix}_resources.h",
"grit/${grd_prefix}_resources_map.cc",
"grit/${grd_prefix}_resources_map.h",
"${grd_prefix}_resources.pak",
]
grit_output_dir = "$root_gen_dir/chrome"
if (defined(invoker.grit_output_dir)) {
grit_output_dir = invoker.grit_output_dir
}
output_dir = grit_output_dir
}
}
}