Source code

Revision control

Copy as Markdown

Other Tools

# Copyright 2014 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.
# Instantiate grit. This will produce a script target to run grit (named
# ${target_name}_grit), and a static library that compiles the .cc files.
#
# In general, code should depend on the static library. However, if the
# generated files are only processed by other actions to generate other
# files, it is possible to depend on the script target directly.
#
# Parameters
#
# source (required)
# Path to .grd file.
#
# enable_input_discovery_for_gn_analyze (default=true)
# Runs grit_info.py via exec_script() when compute_inputs_for_analyze=true
# in order to discover all files that affect this target.
# Turn this off when the .grd file is generated, or an <include> with
# flattenhtml=true points to a generated file.
# For "gn analyze" to be correct with this arg disabled, all inputs
# must be listed via |inputs|.
#
# inputs (optional)
# List of additional files, required for grit to process source file.
#
# outputs (required)
# List of outputs from grit, relative to the target_gen_dir. Grit will
# verify at build time that this list is correct and will fail if there
# is a mismatch between the outputs specified by the .grd file and the
# outputs list here.
#
# To get this list, you can look in the .grd file for
# <output filename="..." and put those filename here. The base directory
# of the list in Grit and the output list specified in the GN grit target
# are the same (the target_gen_dir) so you can generally copy the names
# exactly.
#
# To get the list of outputs programatically, run:
# python tools/grit/grit_info.py --outputs . path/to/your.grd
# And strip the leading "./" from the output files.
#
# defines (optional)
# Extra defines to pass to grit (on top of the global grit_defines list).
#
# grit_flags (optional)
# List of strings containing extra command-line flags to pass to Grit.
#
# resource_ids (optional)
# Path to a grit "firstidsfile". Default is
# //tools/gritsettings/resource_ids. Set to "" to use the value specified
# in the <grit> nodes of the processed files.
#
# output_dir (optional)
# Directory for generated files. If you specify this, you will often
# want to specify output_name if the target name is not particularly
# unique, since this can cause files from multiple grit targets to
# overwrite each other.
#
# output_name (optional)
# Provide an alternate base name for the generated files, like the .d
# files. Normally these are based on the target name and go in the
# output_dir, but if multiple targets with the same name end up in
# the same output_dir, they can collide.
#
# configs (optional)
# List of additional configs to be applied to the generated target.
#
# deps (optional)
# testonly (optional)
# visibility (optional)
# Normal meaning.
#
# Example
#
# grit("my_resources") {
# # Source and outputs are required.
# source = "myfile.grd"
# outputs = [
# "foo_strings.h",
# "foo_strings.pak",
# ]
#
# grit_flags = [ "-E", "foo=bar" ] # Optional extra flags.
# # You can also put deps here if the grit source depends on generated
# # files.
# }
import("//chromium/build/config/chrome_build.gni")
import("//chromium/build/config/chromeos/ui_mode.gni")
import("//chromium/build/config/compiler/compiler.gni")
import("//chromium/build/config/compute_inputs_for_analyze.gni")
import("//chromium/build/config/crypto.gni")
import("//chromium/build/config/features.gni")
import("//chromium/build/config/sanitizers/sanitizers.gni")
import("//chromium/build/config/ui.gni")
import("//build/toolchain/gcc_toolchain.gni")
declare_args() {
enable_resource_whitelist_generation = is_android && is_official_build
}
if (enable_resource_whitelist_generation) {
assert(target_os == "android" || target_os == "win",
"unsupported platform for resource whitelist generation")
assert(
symbol_level > 0 && !strip_debug_info && !is_component_build,
"resource whitelist generation only works on non-component builds with debug info enabled.")
}
grit_defines = []
if (is_mac || is_win || is_linux || is_chromeos || is_ios) {
grit_defines += [
"-D",
"scale_factors=2x",
]
}
# Mac and iOS want Title Case strings.
use_titlecase_in_grd_files = is_apple
if (use_titlecase_in_grd_files) {
grit_defines += [
"-D",
"use_titlecase",
]
}
if (is_chrome_branded) {
grit_defines += [
"-D",
"_google_chrome",
"-E",
"CHROMIUM_BUILD=google_chrome",
]
} else {
grit_defines += [
"-D",
"_chromium",
"-E",
"CHROMIUM_BUILD=chromium",
]
}
if (is_chromeos) {
grit_defines += [
"-D",
"chromeos",
]
}
if (chromeos_is_browser_only) {
grit_defines += [
"-D",
"lacros",
]
}
if (is_desktop_linux) {
grit_defines += [
"-D",
"desktop_linux",
]
}
if (toolkit_views) {
grit_defines += [
"-D",
"toolkit_views",
]
}
if (use_aura) {
grit_defines += [
"-D",
"use_aura",
]
}
if (use_nss_certs) {
grit_defines += [
"-D",
"use_nss_certs",
]
}
if (use_ozone) {
grit_defines += [
"-D",
"use_ozone",
]
}
if (is_android) {
grit_defines += [
"-E",
"ANDROID_JAVA_TAGGED_ONLY=true",
]
}
# When cross-compiling, explicitly pass the target system to grit.
if (current_toolchain != host_toolchain) {
if (is_android) {
grit_defines += [
"-t",
"android",
]
}
if (is_ios) {
grit_defines += [
"-t",
"ios",
]
}
if (is_linux || is_chromeos) {
grit_defines += [
"-t",
"linux2",
]
}
if (is_mac) {
grit_defines += [
"-t",
"darwin",
]
}
if (is_win) {
grit_defines += [
"-t",
"win32",
]
}
}
_strip_resource_files = is_android && is_official_build
_js_minifier = "//tools/grit/minify_with_uglify.py"
_css_minifier = "//tools/grit/minimize_css.py"
grit_resource_id_target = "//tools/gritsettings:default_resource_ids"
grit_resource_id_file =
get_label_info(grit_resource_id_target, "target_gen_dir") +
"/default_resource_ids"
grit_info_script = "//tools/grit/grit_info.py"
# TODO(asvitkine): Add predetermined ids files for other platforms.
grit_predetermined_resource_ids_file = ""
if (is_mac) {
grit_predetermined_resource_ids_file =
"//tools/gritsettings/startup_resources_mac.txt"
}
if (is_win) {
grit_predetermined_resource_ids_file =
"//tools/gritsettings/startup_resources_win.txt"
}
template("grit") {
if (defined(invoker.output_dir)) {
_output_dir = invoker.output_dir
} else {
_output_dir = target_gen_dir
}
_grit_outputs =
get_path_info(rebase_path(invoker.outputs, ".", _output_dir), "abspath")
# Add .info output for all pak files
_pak_info_outputs = []
foreach(output, _grit_outputs) {
if (get_path_info(output, "extension") == "pak") {
_pak_info_outputs += [ output + ".info" ]
}
}
if (defined(invoker.output_name)) {
_grit_output_name = invoker.output_name
} else {
_grit_output_name = target_name
}
_grit_custom_target = target_name + "_grit"
action(_grit_custom_target) {
testonly = defined(invoker.testonly) && invoker.testonly
script = "//tools/grit/grit.py"
depfile = "$target_gen_dir/$target_name.d"
inputs = [ invoker.source ]
deps = [ "//tools/grit:grit_sources" ]
outputs = [ "${depfile}.stamp" ] + _grit_outputs + _pak_info_outputs
_grit_flags = grit_defines
# Add extra defines with -D flags.
if (defined(invoker.defines)) {
foreach(i, invoker.defines) {
_grit_flags += [
"-D",
i,
]
}
}
if (defined(invoker.grit_flags)) {
_grit_flags += invoker.grit_flags
}
_rebased_source_path = rebase_path(invoker.source, root_build_dir)
_enable_grit_info =
!defined(invoker.enable_input_discovery_for_gn_analyze) ||
invoker.enable_input_discovery_for_gn_analyze
if (_enable_grit_info && compute_inputs_for_analyze) {
# Only call exec_script when the user has explicitly opted into greater
# precision at the expense of performance.
_rel_inputs = exec_script("//tools/grit/grit_info.py",
[
"--inputs",
_rebased_source_path,
] + _grit_flags,
"list lines")
inputs += rebase_path(_rel_inputs, ".", root_build_dir)
}
args = [
"-i",
_rebased_source_path,
"build",
"-o",
rebase_path(_output_dir, root_build_dir),
"--depdir",
".",
"--depfile",
rebase_path(depfile, root_build_dir),
"--write-only-new=1",
"--depend-on-stamp",
] + _grit_flags
# Add brotli executable if using brotli.
if (defined(invoker.use_brotli) && invoker.use_brotli) {
_brotli_target = "//third_party/brotli:brotli($host_toolchain)"
_brotli_executable = get_label_info(_brotli_target, "root_out_dir") +
"/" + get_label_info(_brotli_target, "name")
if (host_os == "win") {
_brotli_executable += ".exe"
}
inputs += [ _brotli_executable ]
args += [
"--brotli",
rebase_path(_brotli_executable, root_build_dir),
]
}
_resource_ids = grit_resource_id_file
if (defined(invoker.resource_ids)) {
_resource_ids = invoker.resource_ids
}
if (_resource_ids != "") {
inputs += [ _resource_ids ]
args += [
"-f",
rebase_path(_resource_ids, root_build_dir),
]
if (_resource_ids == grit_resource_id_file) {
deps += [ grit_resource_id_target ]
}
}
if (grit_predetermined_resource_ids_file != "") {
inputs += [ grit_predetermined_resource_ids_file ]
args += [
"-p",
rebase_path(grit_predetermined_resource_ids_file, root_build_dir),
]
}
# We want to make sure the declared outputs actually match what Grit is
# writing. We write the list to a file (some of the output lists are long
# enough to not fit on a Windows command line) and ask Grit to verify those
# are the actual outputs at runtime.
_asserted_list_file =
"$target_out_dir/${_grit_output_name}_expected_outputs.txt"
write_file(_asserted_list_file,
rebase_path(invoker.outputs, root_build_dir, _output_dir))
inputs += [ _asserted_list_file ]
args += [
"--assert-file-list",
rebase_path(_asserted_list_file, root_build_dir),
]
if (enable_resource_whitelist_generation) {
_rc_grit_outputs = []
foreach(output, _grit_outputs) {
if (get_path_info(output, "extension") == "rc") {
_rc_grit_outputs += [ output ]
}
}
if (_rc_grit_outputs != []) {
# Resource whitelisting cannot be used with .rc files.
# Make sure that there aren't any .pak outputs which would require
# whitelist annotations.
assert(_pak_info_outputs == [], "can't combine .pak and .rc outputs")
} else {
args += [ "--whitelist-support" ]
}
}
if (_strip_resource_files) {
_js_minifier_command = rebase_path(_js_minifier, root_build_dir)
_css_minifier_command = rebase_path(_css_minifier, root_build_dir)
args += [
"--js-minifier",
_js_minifier_command,
"--css-minifier",
_css_minifier_command,
]
inputs += [
_js_minifier,
_css_minifier,
]
}
if (defined(invoker.visibility)) {
# This needs to include both what the invoker specified (since they
# probably include generated headers from this target), as well as the
# generated source set (since there's no guarantee that the visibility
# specified by the invoker includes our target).
#
# Only define visibility at all if the invoker specified it. Otherwise,
# we want to keep the public "no visibility specified" default.
visibility = [ ":${invoker.target_name}" ] + invoker.visibility
}
if (defined(invoker.use_brotli) && invoker.use_brotli) {
if (is_mac && is_asan) {
deps += [ "//tools/grit:brotli_mac_asan_workaround" ]
} else {
deps += [ "//third_party/brotli:brotli($host_toolchain)" ]
}
}
if (defined(invoker.deps)) {
deps += invoker.deps
}
if (defined(invoker.inputs)) {
inputs += invoker.inputs
}
}
# This is the thing that people actually link with, it must be named the
# same as the argument the template was invoked with.
source_set(target_name) {
testonly = defined(invoker.testonly) && invoker.testonly
# Since we generate a file, we need to be run before the targets that
# depend on us.
sources = []
foreach(_output, _grit_outputs) {
_extension = get_path_info(_output, "extension")
if (_extension != "json" && _extension != "gz" && _extension != "pak" &&
_extension != "xml") {
sources += [ _output ]
}
}
# Deps set on the template invocation will go on the action that runs
# grit above rather than this library. This target needs to depend on the
# action publicly so other scripts can take the outputs from the grit
# script as inputs.
public_deps = [ ":$_grit_custom_target" ]
deps = [ "//base" ]
if (defined(invoker.public_configs)) {
public_configs += invoker.public_configs
}
if (defined(invoker.configs)) {
configs += invoker.configs
}
if (defined(invoker.visibility)) {
visibility = invoker.visibility
}
output_name = _grit_output_name
}
}