# 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, and a # static library that compiles the .cc files. # # Parameters # # source (required) # Path to .grd file. # # source_is_generated (optional, defaults to false) # Declares that the input (or one of its dependencies) is generated so # that grit_info is not run on the file when # compute_inputs_for_analyze is set (because the file will not # exist at analyze time). For "analyze" to be correct in this case, the # inputs to the grit file must either be listed in the inputs variable # or are listed as inputs to dependencies of this target. # # 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 # 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. # # depfile_dir (optional) # If set, used to store the depfile and corresponding stamp file. # Defaults to output_dir # # configs (optional) # List of additional configs to be applied to the generated target. # deps (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/android/config.gni") import("//build/config/chrome_build.gni") import("//build/config/compute_inputs_for_analyze.gni") import("//build/config/crypto.gni") import("//build/config/features.gni") import("//build/config/ui.gni") import("//third_party/closure_compiler/closure_args.gni") assert(!enable_resource_whitelist_generation || is_android, "resource whitelist generation only works on android") grit_defines = [] # Mac and iOS want Title Case strings. use_titlecase_in_grd_files = is_mac || is_ios 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", "-D", "scale_factors=2x", ] } 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", ] } if (is_mac || is_ios) { grit_defines += [ "-D", "scale_factors=2x", ] } # 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) { grit_defines += [ "-t", "linux2", ] } if (is_mac) { grit_defines += [ "-t", "darwin", ] } if (is_win) { grit_defines += [ "-t", "win32", ] } } # TODO(aberent): Enable for other platforms once the build machines have # Java on them (and hence can run the closure compiler). _strip_resource_files = is_android _js_minifier = "//third_party/closure_compiler/js_minify.py" grit_resource_id_file = "//tools/gritsettings/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") { assert(defined(invoker.source), "\"source\" must be defined for the grit template $target_name") if (defined(invoker.resource_ids)) { resource_ids = invoker.resource_ids } else { resource_ids = grit_resource_id_file } if (defined(invoker.output_dir)) { output_dir = invoker.output_dir } else { output_dir = target_gen_dir } if (defined(invoker.output_name)) { grit_output_name = invoker.output_name } else { grit_output_name = target_name } if (defined(invoker.depfile_dir)) { depfile_dir = invoker.depfile_dir } else { depfile_dir = output_dir } # These are all passed as arguments to the script so have to be relative to # the build directory. rebased_output_dir = rebase_path(output_dir, root_build_dir) source_path = rebase_path(invoker.source, root_build_dir) # Compute flags. grit_flags = [] if (defined(invoker.grit_flags)) { grit_flags += invoker.grit_flags } if (resource_ids != "") { grit_flags += [ "-f", rebase_path(resource_ids, root_build_dir), ] } if (grit_predetermined_resource_ids_file != "") { grit_flags += [ "-p", rebase_path(grit_predetermined_resource_ids_file, root_build_dir), ] } if (defined(invoker.source_is_generated)) { source_is_generated = invoker.source_is_generated } else { source_is_generated = false } assert_files_flags = [] # 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)) assert_files_flags += [ "--assert-file-list=" + rebase_path(asserted_list_file, root_build_dir) ] grit_outputs = get_path_info(rebase_path(invoker.outputs, ".", output_dir), "abspath") # Add .info output for all pak files set_sources_assignment_filter([ "*.pak" ]) sources = grit_outputs pak_grit_outputs = grit_outputs - sources sources = [] pak_info_outputs = [] foreach(output, pak_grit_outputs) { pak_info_outputs += [ "${output}.info" ] } # The config and the action below get this visibility son only the generated # source set can depend on them. The variable "target_name" will get # overwritten inside the inner classes so we need to compute it here. target_visibility = [ ":$target_name" ] # This config sets up flags needed for enable_resource_whitelist_generation. grit_config = target_name + "_grit_config" config(grit_config) { if ((is_linux || is_android) && enable_resource_whitelist_generation) { cflags = [ "-Wunknown-pragmas", "-Wno-error=unknown-pragmas", ] } visibility = target_visibility } grit_custom_target = target_name + "_grit" action(grit_custom_target) { script = "//tools/grit/grit.py" inputs = [ invoker.source, ] if (resource_ids != "") { # The script depends on the ID file. Only add this dependency if the ID # file is specified. inputs += [ resource_ids ] } depfile = "$depfile_dir/${grit_output_name}_stamp.d" outputs = [ "${depfile}.stamp" ] + grit_outputs + pak_info_outputs args = [ "-i", source_path, "build", "-o", rebased_output_dir, "--depdir", ".", "--depfile", rebase_path(depfile, root_build_dir), "--write-only-new=1", "--depend-on-stamp", ] + grit_defines # Add extra defines with -D flags. define_args = [] if (defined(invoker.defines)) { foreach(i, invoker.defines) { define_args += [ "-D", i, ] } } args += define_args + grit_flags + assert_files_flags if (enable_resource_whitelist_generation) { args += [ "-h" ] if (is_win) { args += [ "#define {textual_id} __pragma(message(\"whitelisted_resource_{numeric_id}\")) {numeric_id}" ] } else { args += [ "#define {textual_id} _Pragma(\"whitelisted_resource_{numeric_id}\") {numeric_id}" ] } } if (_strip_resource_files) { js_minifier_command = rebase_path(_js_minifier) js_minifier_command = "$js_minifier_command --closure_args" foreach(closure_arg, common_closure_args + minifying_closure_args + default_disabled_closure_args) { js_minifier_command = "$js_minifier_command $closure_arg" } args += [ "--js-minifier", js_minifier_command, ] inputs += [ _js_minifier, "//third_party/closure_compiler/compiler/compiler.jar", ] } # Must be after the args are computed since they are re-used. # See the comments for the two variables used in this condition for # why this works this way. if (compute_inputs_for_analyze && !source_is_generated) { grit_info_script = "//tools/grit/grit_info.py" grit_info_args = [ "--inputs", source_path, ] + grit_flags + grit_defines + define_args # Only call exec_script when the user has explicitly opted into greater # precision at the expense of performance. rel_inputs = exec_script(grit_info_script, grit_info_args, "list lines", [ grit_info_script ]) inputs += rebase_path(rel_inputs, ".", root_build_dir) } else { assert(source_is_generated || !source_is_generated) # Prevent error. } 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 = target_visibility + invoker.visibility } deps = [ "//tools/grit:grit_sources", ] 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) { # Since we generate a file, we need to be run before the targets that # depend on us. sources = grit_outputs # 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", ] public_configs = [ ":$grit_config" ] 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 } }