| # Copyright 2014 The Chromium Authors |
| # 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 defines in the |
| # grit_args 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("//build/config/compiler/compiler.gni") |
| import("//build/config/compute_inputs_for_analyze.gni") |
| import("//build/config/sanitizers/sanitizers.gni") |
| import("//build/toolchain/gcc_toolchain.gni") |
| import("//tools/grit/grit_args.gni") |
| _strip_resource_files = is_android && is_official_build |
| _js_minifier = "//tools/grit/minify_js.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) { |
| script = "//tools/grit/grit.py" |
| inputs = [ invoker.source ] |
| |
| testonly = defined(invoker.testonly) && invoker.testonly |
| |
| depfile = "$target_gen_dir/$target_name.d" |
| |
| deps = [ "//tools/grit:grit_sources" ] |
| outputs = [ "${depfile}.stamp" ] + _grit_outputs + _pak_info_outputs |
| |
| _grit_flags = grit_args |
| |
| # 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_allowlist_generation) { |
| _rc_grit_outputs = [] |
| foreach(output, _grit_outputs) { |
| if (get_path_info(output, "extension") == "rc") { |
| _rc_grit_outputs += [ output ] |
| } |
| } |
| |
| if (_rc_grit_outputs != []) { |
| # Resource allowlisting cannot be used with .rc files. |
| # Make sure that there aren't any .pak outputs which would require |
| # allowlist annotations. |
| assert(_pak_info_outputs == [], "can't combine .pak and .rc outputs") |
| } else { |
| args += [ "--allowlist-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" ] |
| |
| 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 |
| } |
| } |
| |
| if (is_android) { |
| import("//build/config/android/rules.gni") |
| |
| # Declare a target that generates localized strings.xml from a .grd file. |
| # |
| # If this target is included in the deps of an android resources/library/apk, |
| # the strings.xml will be included with that target. |
| # |
| # Variables |
| # deps: Specifies the dependencies of this target. |
| # grd_file: Path to the .grd file to generate strings.xml from. |
| # outputs: Expected grit outputs (see grit rule). |
| # |
| # Example |
| # java_strings_grd("foo_strings_grd") { |
| # grd_file = "foo_strings.grd" |
| # } |
| template("java_strings_grd") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| _resources_zip = "$target_out_dir/$target_name.resources.zip" |
| _grit_target_name = "${target_name}__grit" |
| _grit_output_dir = "$target_gen_dir/${target_name}_grit_output" |
| |
| grit(_grit_target_name) { |
| forward_variables_from(invoker, |
| [ |
| "deps", |
| "defines", |
| ]) |
| grit_flags = [ |
| "-E", |
| "ANDROID_JAVA_TAGGED_ONLY=false", |
| ] |
| output_dir = _grit_output_dir |
| resource_ids = "" |
| source = invoker.grd_file |
| outputs = invoker.outputs |
| } |
| |
| _zip_target_name = "${target_name}__zip" |
| |
| zip(_zip_target_name) { |
| base_dir = _grit_output_dir |
| |
| # No need to depend on the source_set(). |
| _grit_dep = ":${_grit_target_name}_grit" |
| deps = [ _grit_dep ] |
| inputs = filter_exclude(get_target_outputs(_grit_dep), [ "*.stamp" ]) |
| output = _resources_zip |
| } |
| |
| android_generated_resources(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "resource_overlay", |
| "visibility", |
| ]) |
| generating_target = ":$_zip_target_name" |
| generated_resources_zip = _resources_zip |
| } |
| } |
| |
| # Declare a target that packages strings.xml generated from a grd file. |
| # |
| # If this target is included in the deps of an android resources/library/apk, |
| # the strings.xml will be included with that target. |
| # |
| # Variables |
| # grit_output_dir: directory containing grit-generated files. |
| # generated_files: list of android resource files to package. |
| # |
| # Example |
| # java_strings_grd_prebuilt("foo_strings_grd") { |
| # grit_output_dir = "$root_gen_dir/foo/grit" |
| # generated_files = [ |
| # "values/strings.xml" |
| # ] |
| # } |
| template("java_strings_grd_prebuilt") { |
| forward_variables_from(invoker, [ "testonly" ]) |
| |
| _resources_zip = "$target_out_dir/$target_name.resources.zip" |
| _zip_target_name = "${target_name}__zip" |
| |
| zip(_zip_target_name) { |
| base_dir = invoker.grit_output_dir |
| inputs = rebase_path(invoker.generated_files, ".", base_dir) |
| output = _resources_zip |
| if (defined(invoker.deps)) { |
| deps = [] |
| foreach(_dep, invoker.deps) { |
| deps += [ "${_dep}_grit" ] |
| } |
| } |
| } |
| |
| android_generated_resources(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "resource_overlay", |
| "visibility", |
| ]) |
| generating_target = ":$_zip_target_name" |
| generated_resources_zip = _resources_zip |
| } |
| } |
| } |