1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Helper script to repack paks for a list of locales.
7
8Gyp doesn't have any built-in looping capability, so this just provides a way to
9loop over a list of locales when repacking pak files, thus avoiding a
10proliferation of mostly duplicate, cut-n-paste gyp actions.
11"""
12
13import optparse
14import os
15import sys
16
17sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..',
18                             'tools', 'grit'))
19from grit.format import data_pack
20
21# The gyp "branding" variable.
22BRANDING = None
23
24# Some build paths defined by gyp.
25GRIT_DIR = None
26SHARE_INT_DIR = None
27INT_DIR = None
28
29# The target platform. If it is not defined, sys.platform will be used.
30OS = None
31
32# Note that OS is normally set to 'linux' when building for chromeos.
33CHROMEOS = False
34
35USE_ASH = False
36USE_ATHENA = False
37ENABLE_AUTOFILL_DIALOG = False
38ENABLE_EXTENSIONS = False
39
40WHITELIST = None
41
42# Extra input files.
43EXTRA_INPUT_FILES = []
44
45class Usage(Exception):
46  def __init__(self, msg):
47    self.msg = msg
48
49
50def calc_output(locale):
51  """Determine the file that will be generated for the given locale."""
52  #e.g. '<(INTERMEDIATE_DIR)/repack/da.pak',
53  # For Fake Bidi, generate it at a fixed path so that tests can safely
54  # reference it.
55  if locale == 'fake-bidi':
56    return '%s/%s.pak' % (INT_DIR, locale)
57  if OS == 'mac' or OS == 'ios':
58    # For Cocoa to find the locale at runtime, it needs to use '_' instead
59    # of '-' (http://crbug.com/20441).  Also, 'en-US' should be represented
60    # simply as 'en' (http://crbug.com/19165, http://crbug.com/25578).
61    if locale == 'en-US':
62      locale = 'en'
63    return '%s/repack/%s.lproj/locale.pak' % (INT_DIR, locale.replace('-', '_'))
64  else:
65    return os.path.join(INT_DIR, 'repack', locale + '.pak')
66
67
68def calc_inputs(locale):
69  """Determine the files that need processing for the given locale."""
70  inputs = []
71
72  #e.g. '<(grit_out_dir)/generated_resources_da.pak'
73  inputs.append(os.path.join(GRIT_DIR, 'generated_resources_%s.pak' % locale))
74
75  #e.g. '<(grit_out_dir)/locale_settings_da.pak'
76  inputs.append(os.path.join(GRIT_DIR, 'locale_settings_%s.pak' % locale))
77
78  #e.g. '<(grit_out_dir)/platform_locale_settings_da.pak'
79  inputs.append(os.path.join(GRIT_DIR,
80                'platform_locale_settings_%s.pak' % locale))
81
82  #e.g. '<(SHARED_INTERMEDIATE_DIR)/components/strings/
83  # components_strings_da.pak',
84  inputs.append(os.path.join(SHARE_INT_DIR, 'components', 'strings',
85                'components_strings_%s.pak' % locale))
86
87  if USE_ASH:
88    #e.g. '<(SHARED_INTERMEDIATE_DIR)/ash/strings/ash_strings_da.pak',
89    inputs.append(os.path.join(SHARE_INT_DIR, 'ash', 'strings',
90                  'ash_strings_%s.pak' % locale))
91
92  if USE_ATHENA:
93    #e.g. '<(SHARED_INTERMEDIATE_DIR)/athena/strings/athena_strings_da.pak',
94    inputs.append(os.path.join(SHARE_INT_DIR, 'athena', 'strings',
95                  'athena_strings_%s.pak' % locale))
96
97  if CHROMEOS:
98    inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'chromeos', 'strings',
99                  'ui_chromeos_strings_%s.pak' % locale))
100
101  if OS != 'ios':
102    #e.g.
103    # '<(SHARED_INTERMEDIATE_DIR)/content/app/strings/content_strings_da.pak'
104    inputs.append(os.path.join(SHARE_INT_DIR, 'content', 'app', 'strings',
105                  'content_strings_%s.pak' % locale))
106
107    #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/strings/ui_strings_da.pak',
108    inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'strings',
109                  'ui_strings_%s.pak' % locale))
110
111    #e.g. '<(SHARED_INTERMEDIATE_DIR)/ui/strings/app_locale_settings_da.pak',
112    inputs.append(os.path.join(SHARE_INT_DIR, 'ui', 'strings',
113                  'app_locale_settings_%s.pak' % locale))
114
115  if ENABLE_AUTOFILL_DIALOG and OS != 'ios' and OS != 'android':
116    #e.g. '<(SHARED_INTERMEDIATE_DIR)/third_party/libaddressinput/
117    # address_input_strings_da.pak',
118    inputs.append(os.path.join(SHARE_INT_DIR, 'third_party', 'libaddressinput',
119                               'address_input_strings_%s.pak' % locale))
120
121  if ENABLE_EXTENSIONS:
122    #e.g. '<(SHARED_INTERMEDIATE_DIR)/device/bluetooth/strings/
123    # device_bluetooth_strings_da.pak',
124    inputs.append(os.path.join(SHARE_INT_DIR, 'device', 'bluetooth', 'strings',
125                  'device_bluetooth_strings_%s.pak' % locale))
126
127    # For example:
128    # '<(SHARED_INTERMEDIATE_DIR)/extensions/strings/extensions_strings_da.pak
129    # TODO(jamescook): When Android stops building extensions code move this
130    # to the OS != 'ios' and OS != 'android' section below.
131    inputs.append(os.path.join(SHARE_INT_DIR, 'extensions', 'strings',
132                  'extensions_strings_%s.pak' % locale))
133
134  #e.g. '<(grit_out_dir)/google_chrome_strings_da.pak'
135  #     or
136  #     '<(grit_out_dir)/chromium_strings_da.pak'
137  inputs.append(os.path.join(
138      GRIT_DIR, '%s_strings_%s.pak' % (BRANDING, locale)))
139
140  # Add any extra input files.
141  for extra_file in EXTRA_INPUT_FILES:
142    inputs.append('%s_%s.pak' % (extra_file, locale))
143
144  return inputs
145
146
147def list_outputs(locales):
148  """Returns the names of files that will be generated for the given locales.
149
150  This is to provide gyp the list of output files, so build targets can
151  properly track what needs to be built.
152  """
153  outputs = []
154  for locale in locales:
155    outputs.append(calc_output(locale))
156  # Quote each element so filename spaces don't mess up gyp's attempt to parse
157  # it into a list.
158  return " ".join(['"%s"' % x for x in outputs])
159
160
161def list_inputs(locales):
162  """Returns the names of files that will be processed for the given locales.
163
164  This is to provide gyp the list of input files, so build targets can properly
165  track their prerequisites.
166  """
167  inputs = []
168  for locale in locales:
169    inputs += calc_inputs(locale)
170  # Quote each element so filename spaces don't mess up gyp's attempt to parse
171  # it into a list.
172  return " ".join(['"%s"' % x for x in inputs])
173
174
175def repack_locales(locales):
176  """ Loop over and repack the given locales."""
177  for locale in locales:
178    inputs = []
179    inputs += calc_inputs(locale)
180    output = calc_output(locale)
181    data_pack.DataPack.RePack(output, inputs, whitelist_file=WHITELIST)
182
183
184def DoMain(argv):
185  global BRANDING
186  global GRIT_DIR
187  global SHARE_INT_DIR
188  global INT_DIR
189  global OS
190  global CHROMEOS
191  global USE_ASH
192  global USE_ATHENA
193  global WHITELIST
194  global ENABLE_AUTOFILL_DIALOG
195  global ENABLE_EXTENSIONS
196  global EXTRA_INPUT_FILES
197
198  parser = optparse.OptionParser("usage: %prog [options] locales")
199  parser.add_option("-i", action="store_true", dest="inputs", default=False,
200                    help="Print the expected input file list, then exit.")
201  parser.add_option("-o", action="store_true", dest="outputs", default=False,
202                    help="Print the expected output file list, then exit.")
203  parser.add_option("-g", action="store", dest="grit_dir",
204                    help="GRIT build files output directory.")
205  parser.add_option("-x", action="store", dest="int_dir",
206                    help="Intermediate build files output directory.")
207  parser.add_option("-s", action="store", dest="share_int_dir",
208                    help="Shared intermediate build files output directory.")
209  parser.add_option("-b", action="store", dest="branding",
210                    help="Branding type of this build.")
211  parser.add_option("-e", action="append", dest="extra_input", default=[],
212                    help="Full path to an extra input pak file without the\
213                         locale suffix and \".pak\" extension.")
214  parser.add_option("-p", action="store", dest="os",
215                    help="The target OS. (e.g. mac, linux, win, etc.)")
216  parser.add_option("--use-ash", action="store", dest="use_ash",
217                    help="Whether to include ash strings")
218  parser.add_option("--use-athena", action="store", dest="use_athena",
219                    help="Whether to include athena strings")
220  parser.add_option("--chromeos", action="store",
221                    help="Whether building for Chrome OS")
222  parser.add_option("--whitelist", action="store", help="Full path to the "
223                    "whitelist used to filter output pak file resource IDs")
224  parser.add_option("--enable-autofill-dialog", action="store",
225                    dest="enable_autofill_dialog",
226                    help="Whether to include strings for autofill dialog")
227  parser.add_option("--enable-extensions", action="store",
228                    dest="enable_extensions",
229                    help="Whether to include strings for extensions")
230  options, locales = parser.parse_args(argv)
231
232  if not locales:
233    parser.error('Please specificy at least one locale to process.\n')
234
235  print_inputs = options.inputs
236  print_outputs = options.outputs
237  GRIT_DIR = options.grit_dir
238  INT_DIR = options.int_dir
239  SHARE_INT_DIR = options.share_int_dir
240  BRANDING = options.branding
241  EXTRA_INPUT_FILES = options.extra_input
242  OS = options.os
243  CHROMEOS = options.chromeos == '1'
244  USE_ASH = options.use_ash == '1'
245  USE_ATHENA = options.use_athena == '1'
246  WHITELIST = options.whitelist
247  ENABLE_AUTOFILL_DIALOG = options.enable_autofill_dialog == '1'
248  ENABLE_EXTENSIONS = options.enable_extensions == '1'
249
250  if not OS:
251    if sys.platform == 'darwin':
252      OS = 'mac'
253    elif sys.platform.startswith('linux'):
254      OS = 'linux'
255    elif sys.platform in ('cygwin', 'win32'):
256      OS = 'win'
257    else:
258      OS = sys.platform
259
260  if not (GRIT_DIR and INT_DIR and SHARE_INT_DIR):
261    parser.error('Please specify all of "-g" and "-x" and "-s".\n')
262  if print_inputs and print_outputs:
263    parser.error('Please specify only one of "-i" or "-o".\n')
264  # Need to know the branding, unless we're just listing the outputs.
265  if not print_outputs and not BRANDING:
266    parser.error('Please specify "-b" to determine the input files.\n')
267
268  if print_inputs:
269    return list_inputs(locales)
270
271  if print_outputs:
272    return list_outputs(locales)
273
274  return repack_locales(locales)
275
276if __name__ == '__main__':
277  results = DoMain(sys.argv[1:])
278  if results:
279    print results
280