chromium/tools/grit/repack.gni

# 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.

import("//tools/grit/grit_rule.gni")

# This file defines a template to invoke grit repack in a consistent manner.
#
# Parameters:
#   sources  [required]
#       List of pak files that need to be combined.
#
#   output  [required]
#       File name (single string) of the output file.
#
#   copy_data_to_bundle [optional]
#       Whether to define a bundle_data() for the resulting pak.
#
#   mark_as_data
#       Whether to add the resulting pak to |data|.
#
#   bundle_output [optional]
#       Path of the file in the application bundle, defaults to
#       {{bundle_resources_dir}}/{{source_file_part}}.
#
#   compress  [optional]
#       Gzip the resulting bundle (and append .gz to the output name).
#
#   deps  [optional]
#   public_deps  [optional]
#   visibility  [optional]
#       Normal meaning.
template("repack") {
  _copy_data_to_bundle =
      defined(invoker.copy_data_to_bundle) && invoker.copy_data_to_bundle
  _repack_target_name = target_name
  if (_copy_data_to_bundle) {
    _repack_target_name = "${target_name}__repack"
  }

  _compress = defined(invoker.compress) && invoker.compress

  action(_repack_target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "public_deps",
                             "testonly",
                             "visibility",
                           ])
    if (defined(visibility) && _copy_data_to_bundle) {
      visibility += [ ":${invoker.target_name}" ]
    }
    assert(defined(invoker.sources), "Need sources for $target_name")
    assert(defined(invoker.output), "Need output for $target_name")

    script = "//tools/grit/pak_util.py"

    inputs = []
    foreach(source, invoker.sources) {
      inputs += [
        source,
        "${source}.info",
      ]
    }
    outputs = [
      invoker.output,
      "${invoker.output}.info",
    ]

    if (defined(invoker.mark_as_data) && invoker.mark_as_data) {
      data = [ invoker.output ]
    }

    args = [ "repack" ]
    if (defined(invoker.repack_allowlist)) {
      inputs += [ invoker.repack_allowlist ]
      _rebased_allowlist = rebase_path(invoker.repack_allowlist)
      args += [ "--allowlist=$_rebased_allowlist" ]
      args += [ "--suppress-removed-key-output" ]
    }
    args += [ rebase_path(invoker.output, root_build_dir) ]
    args += rebase_path(invoker.sources, root_build_dir)
    if (_compress) {
      args += [ "--compress" ]
    }
  }

  if (_copy_data_to_bundle) {
    bundle_data(target_name) {
      forward_variables_from(invoker,
                             [
                               "testonly",
                               "visibility",
                             ])

      public_deps = [ ":$_repack_target_name" ]
      sources = [ invoker.output ]
      if (defined(invoker.bundle_output)) {
        outputs = [ invoker.bundle_output ]
      } else {
        outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
      }
    }
  }
}

# Repacks a set of .pak files for each locale.
#
# Parameters:
#
#   input_locales [required]
#       List of locale names to use as inputs.
#
#   output_locales [required]
#       A list containing the corresponding output names for each of the
#       input names. Mac and iOS use different names in some cases.
#
#   source_patterns [required]
#       The pattern for pak files which need repacked. The filenames always end
#       with "${locale}.pak".
#       E.g.:
#          ${root_gen_dir}/foo_ expands to ${root_gen_dir}/foo_zh-CN.pak
#        when locale is zh-CN.
#
#   output_dir [optional]
#       Directory in which to put all pak files.
#
#   deps  [optional]
#   visibility  [optional]
#   testonly  [optional]
#   copy_data_to_bundle [optional]
#   repack_allowlist [optional]
#       Normal meaning.
template("repack_locales") {
  if (defined(invoker.output_dir)) {
    _output_dir = invoker.output_dir
  } else if (is_ios) {
    _output_dir = "$target_gen_dir"
  } else {
    _output_dir = "$target_gen_dir/$target_name"
  }

  # GN can't handle invoker.output_locales[foo] (http://crbug.com/614747).
  _output_locales = invoker.output_locales

  # Collects all targets the loop generates.
  _locale_targets = []

  # This loop iterates over the input locales and also keeps a counter so it
  # can simultaneously iterate over the output locales (using GN's very
  # limited looping capabilities).
  _current_index = 0
  foreach(_input_locale, invoker.input_locales) {
    _output_locale = _output_locales[_current_index]

    # Compute the name of the target for the current file. Save it for the deps.
    _current_name = "${target_name}_${_input_locale}"
    _locale_targets += [ ":$_current_name" ]

    repack(_current_name) {
      forward_variables_from(invoker,
                             [
                               "bundle_output",
                               "compress",
                               "copy_data_to_bundle",
                               "deps",
                               "mark_as_data",
                               "repack_allowlist",
                               "testonly",
                             ])
      visibility = [ ":${invoker.target_name}" ]
      if (is_ios) {
        output = "$_output_dir/${_output_locale}.lproj/locale.pak"
      } else {
        output = "$_output_dir/${_output_locale}.pak"
      }
      if (defined(copy_data_to_bundle) && copy_data_to_bundle) {
        bundle_output =
            "{{bundle_resources_dir}}/${_output_locale}.lproj/locale.pak"
      }
      sources = []
      foreach(_pattern, invoker.source_patterns) {
        sources += [ "${_pattern}${_input_locale}.pak" ]
      }
    }

    _current_index = _current_index + 1
  }

  # The group that external targets depend on which collects all deps.
  group(target_name) {
    forward_variables_from(invoker,
                           [
                             "visibility",
                             "testonly",
                           ])
    public_deps = _locale_targets
  }
}