~ubuntu-branches/ubuntu/oneiric/mozc/oneiric

« back to all changes in this revision

Viewing changes to third_party/gyp/pylib/gyp/__init__.py

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2010-07-14 03:26:47 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100714032647-13qjisj6m8cm8jdx
Tags: 0.12.410.102-1
* New upstream release (Closes: #588971).
  - Add mozc-server, mozc-utils-gui and scim-mozc packages.
* Update debian/rules.
  Add --gypdir option to build_mozc.py.
* Update debian/control.
  - Bumped standards-version to 3.9.0.
  - Update description.
* Add mozc icon (Closes: #588972).
* Add patch which revises issue 18.
  ibus_mozc_issue18.patch
* kFreeBSD build support.
  support_kfreebsd.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# Copyright (c) 2009 Google Inc. All rights reserved.
 
4
# Use of this source code is governed by a BSD-style license that can be
 
5
# found in the LICENSE file.
 
6
 
 
7
import copy
 
8
import gyp.input
 
9
import optparse
 
10
import os.path
 
11
import re
 
12
import shlex
 
13
import sys
 
14
 
 
15
# Default debug modes for GYP
 
16
debug = {}
 
17
 
 
18
# List of "official" debug modes, but you can use anything you like.
 
19
DEBUG_GENERAL = 'general'
 
20
DEBUG_VARIABLES = 'variables'
 
21
DEBUG_INCLUDES = 'includes'
 
22
 
 
23
def DebugOutput(mode, message):
 
24
  if mode in gyp.debug.keys():
 
25
    print "%s: %s" % (mode.upper(), message)
 
26
 
 
27
def FindBuildFiles():
 
28
  extension = '.gyp'
 
29
  files = os.listdir(os.getcwd())
 
30
  build_files = []
 
31
  for file in files:
 
32
    if file[-len(extension):] == extension:
 
33
      build_files.append(file)
 
34
  return build_files
 
35
 
 
36
 
 
37
def Load(build_files, format, default_variables={},
 
38
         includes=[], depth='.', params={}, check=False, circular_check=True):
 
39
  """
 
40
  Loads one or more specified build files.
 
41
  default_variables and includes will be copied before use.
 
42
  Returns the generator for the specified format and the
 
43
  data returned by loading the specified build files.
 
44
  """
 
45
  default_variables = copy.copy(default_variables)
 
46
 
 
47
  # Default variables provided by this program and its modules should be
 
48
  # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
 
49
  # avoiding collisions with user and automatic variables.
 
50
  default_variables['GENERATOR'] = format
 
51
 
 
52
  generator_name = 'gyp.generator.' + format
 
53
  # These parameters are passed in order (as opposed to by key)
 
54
  # because ActivePython cannot handle key parameters to __import__.
 
55
  generator = __import__(generator_name, globals(), locals(), generator_name)
 
56
  for (key, val) in generator.generator_default_variables.items():
 
57
    default_variables.setdefault(key, val)
 
58
 
 
59
  # Give the generator the opportunity to set additional variables based on
 
60
  # the params it will receive in the output phase.
 
61
  if getattr(generator, 'CalculateVariables', None):
 
62
    generator.CalculateVariables(default_variables, params)
 
63
 
 
64
  # Fetch the generator specific info that gets fed to input, we use getattr
 
65
  # so we can default things and the generators only have to provide what
 
66
  # they need.
 
67
  generator_input_info = {
 
68
    'generator_wants_absolute_build_file_paths':
 
69
        getattr(generator, 'generator_wants_absolute_build_file_paths', False),
 
70
    'generator_handles_variants':
 
71
        getattr(generator, 'generator_handles_variants', False),
 
72
    'non_configuration_keys':
 
73
        getattr(generator, 'generator_additional_non_configuration_keys', []),
 
74
    'path_sections':
 
75
        getattr(generator, 'generator_additional_path_sections', []),
 
76
    'extra_sources_for_rules':
 
77
        getattr(generator, 'generator_extra_sources_for_rules', []),
 
78
    'generator_supports_multiple_toolsets':
 
79
        getattr(generator, 'generator_supports_multiple_toolsets', False),
 
80
  }
 
81
 
 
82
  # Process the input specific to this generator.
 
83
  result = gyp.input.Load(build_files, default_variables, includes[:],
 
84
                          depth, generator_input_info, check, circular_check)
 
85
  return [generator] + result
 
86
 
 
87
def NameValueListToDict(name_value_list):
 
88
  """
 
89
  Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
 
90
  of the pairs.  If a string is simply NAME, then the value in the dictionary
 
91
  is set to True.  If VALUE can be converted to an integer, it is.
 
92
  """
 
93
  result = { }
 
94
  for item in name_value_list:
 
95
    tokens = item.split('=', 1)
 
96
    if len(tokens) == 2:
 
97
      # If we can make it an int, use that, otherwise, use the string.
 
98
      try:
 
99
        token_value = int(tokens[1])
 
100
      except ValueError:
 
101
        token_value = tokens[1]
 
102
      # Set the variable to the supplied value.
 
103
      result[tokens[0]] = token_value
 
104
    else:
 
105
      # No value supplied, treat it as a boolean and set it.
 
106
      result[tokens[0]] = True
 
107
  return result
 
108
 
 
109
def ShlexEnv(env_name):
 
110
  flags = os.environ.get(env_name, [])
 
111
  if flags:
 
112
    flags = shlex.split(flags)
 
113
  return flags
 
114
 
 
115
def FormatOpt(opt, value):
 
116
  if opt.startswith('--'):
 
117
    return '%s=%s' % (opt, value)
 
118
  return opt + value
 
119
 
 
120
def RegenerateAppendFlag(flag, values, predicate, env_name, options):
 
121
  """Regenerate a list of command line flags, for an option of action='append'.
 
122
 
 
123
  The |env_name|, if given, is checked in the environment and used to generate
 
124
  an initial list of options, then the options that were specified on the
 
125
  command line (given in |values|) are appended.  This matches the handling of
 
126
  environment variables and command line flags where command line flags override
 
127
  the environment, while not requiring the environment to be set when the flags
 
128
  are used again.
 
129
  """
 
130
  flags = []
 
131
  if options.use_environment and env_name:
 
132
    for flag_value in ShlexEnv(env_name):
 
133
      flags.append(FormatOpt(flag, predicate(flag_value)))
 
134
  if values:
 
135
    for flag_value in values:
 
136
      flags.append(FormatOpt(flag, predicate(flag_value)))
 
137
  return flags
 
138
 
 
139
def RegenerateFlags(options):
 
140
  """Given a parsed options object, and taking the environment variables into
 
141
  account, returns a list of flags that should regenerate an equivalent options
 
142
  object (even in the absence of the environment variables.)
 
143
 
 
144
  Any path options will be normalized relative to depth.
 
145
 
 
146
  The format flag is not included, as it is assumed the calling generator will
 
147
  set that as appropriate.
 
148
  """
 
149
  def FixPath(path):
 
150
    path = gyp.common.FixIfRelativePath(path, options.depth)
 
151
    if not path:
 
152
      return os.path.curdir
 
153
    return path
 
154
 
 
155
  def Noop(value):
 
156
    return value
 
157
 
 
158
  # We always want to ignore the environment when regenerating, to avoid
 
159
  # duplicate or changed flags in the environment at the time of regeneration.
 
160
  flags = ['--ignore-environment']
 
161
  for name, metadata in options._regeneration_metadata.iteritems():
 
162
    opt = metadata['opt']
 
163
    value = getattr(options, name)
 
164
    value_predicate = metadata['type'] == 'path' and FixPath or Noop
 
165
    action = metadata['action']
 
166
    env_name = metadata['env_name']
 
167
    if action == 'append':
 
168
      flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
 
169
                                        env_name, options))
 
170
    elif action in ('store', None):  # None is a synonym for 'store'.
 
171
      if value:
 
172
        flags.append(FormatOpt(opt, value_predicate(value)))
 
173
      elif options.use_environment and env_name and os.environ.get(env_name):
 
174
        flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
 
175
    elif action in ('store_true', 'store_false'):
 
176
      if ((action == 'store_true' and value) or
 
177
          (action == 'store_false' and not value)):
 
178
        flags.append(opt)
 
179
      elif options.use_environment and env_name:
 
180
        print >>sys.stderr, ('Warning: environment regeneration unimplemented '
 
181
                             'for %s flag %r env_name %r' % (action, opt,
 
182
                                                             env_name))
 
183
    else:
 
184
      print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
 
185
                           'flag %r' % (action, opt))
 
186
 
 
187
  return flags
 
188
 
 
189
class RegeneratableOptionParser(optparse.OptionParser):
 
190
  def __init__(self):
 
191
    self.__regeneratable_options = {}
 
192
    optparse.OptionParser.__init__(self)
 
193
 
 
194
  def add_option(self, *args, **kw):
 
195
    """Add an option to the parser.
 
196
 
 
197
    This accepts the same arguments as OptionParser.add_option, plus the
 
198
    following:
 
199
      regenerate: can be set to False to prevent this option from being included
 
200
                  in regeneration.
 
201
      env_name: name of environment variable that additional values for this
 
202
                option come from.
 
203
      type: adds type='path', to tell the regenerator that the values of
 
204
            this option need to be made relative to options.depth
 
205
    """
 
206
    env_name = kw.pop('env_name', None)
 
207
    if 'dest' in kw and kw.pop('regenerate', True):
 
208
      dest = kw['dest']
 
209
 
 
210
      # The path type is needed for regenerating, for optparse we can just treat
 
211
      # it as a string.
 
212
      type = kw.get('type')
 
213
      if type == 'path':
 
214
        kw['type'] = 'string'
 
215
 
 
216
      self.__regeneratable_options[dest] = {
 
217
          'action': kw.get('action'),
 
218
          'type': type,
 
219
          'env_name': env_name,
 
220
          'opt': args[0],
 
221
        }
 
222
 
 
223
    optparse.OptionParser.add_option(self, *args, **kw)
 
224
 
 
225
  def parse_args(self, *args):
 
226
    values, args = optparse.OptionParser.parse_args(self, *args)
 
227
    values._regeneration_metadata = self.__regeneratable_options
 
228
    return values, args
 
229
 
 
230
def main(args):
 
231
  my_name = os.path.basename(sys.argv[0])
 
232
 
 
233
  parser = RegeneratableOptionParser()
 
234
  usage = 'usage: %s [options ...] [build_file ...]'
 
235
  parser.set_usage(usage.replace('%s', '%prog'))
 
236
  parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
 
237
                    env_name='GYP_DEFINES',
 
238
                    help='sets variable VAR to value VAL')
 
239
  parser.add_option('-f', '--format', dest='formats', action='append',
 
240
                    env_name='GYP_GENERATORS', regenerate=False,
 
241
                    help='output formats to generate')
 
242
  parser.add_option('--msvs-version', dest='msvs_version',
 
243
                    regenerate=False,
 
244
                    help='Deprecated; use -G msvs_version=MSVS_VERSION instead')
 
245
  parser.add_option('-I', '--include', dest='includes', action='append',
 
246
                    metavar='INCLUDE', type='path',
 
247
                    help='files to include in all loaded .gyp files')
 
248
  parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
 
249
                    help='set DEPTH gyp variable to a relative path to PATH')
 
250
  parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
 
251
                    action='append', default=[], help='turn on a debugging '
 
252
                    'mode for debugging GYP.  Supported modes are "variables" '
 
253
                    'and "general"')
 
254
  parser.add_option('-S', '--suffix', dest='suffix', default='',
 
255
                    help='suffix to add to generated files')
 
256
  parser.add_option('-G', dest='generator_flags', action='append', default=[],
 
257
                    metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
 
258
                    help='sets generator flag FLAG to VAL')
 
259
  parser.add_option('--generator-output', dest='generator_output',
 
260
                    action='store', default=None, metavar='DIR', type='path',
 
261
                    env_name='GYP_GENERATOR_OUTPUT',
 
262
                    help='puts generated build files under DIR')
 
263
  parser.add_option('--ignore-environment', dest='use_environment',
 
264
                    action='store_false', default=True, regenerate=False,
 
265
                    help='do not read options from environment variables')
 
266
  parser.add_option('--check', dest='check', action='store_true',
 
267
                    help='check format of gyp files')
 
268
  parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
 
269
                    default=None, metavar='DIR', type='path',
 
270
                    help='directory to use as the root of the source tree')
 
271
  # --no-circular-check disables the check for circular relationships between
 
272
  # .gyp files.  These relationships should not exist, but they've only been
 
273
  # observed to be harmful with the Xcode generator.  Chromium's .gyp files
 
274
  # currently have some circular relationships on non-Mac platforms, so this
 
275
  # option allows the strict behavior to be used on Macs and the lenient
 
276
  # behavior to be used elsewhere.
 
277
  # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
 
278
  parser.add_option('--no-circular-check', dest='circular_check',
 
279
                    action='store_false', default=True, regenerate=False,
 
280
                    help="don't check for circular relationships between files")
 
281
 
 
282
  # We read a few things from ~/.gyp, so set up a var for that.
 
283
  home_vars = ['HOME']
 
284
  if sys.platform in ('cygwin', 'win32'):
 
285
    home_vars.append('USERPROFILE')
 
286
  home = None
 
287
  home_dot_gyp = None
 
288
  for home_var in home_vars:
 
289
    home = os.getenv(home_var)
 
290
    if home != None:
 
291
      home_dot_gyp = os.path.join(home, '.gyp')
 
292
      if not os.path.exists(home_dot_gyp):
 
293
        home_dot_gyp = None
 
294
      else:
 
295
        break
 
296
 
 
297
  # TODO(thomasvl): add support for ~/.gyp/defaults
 
298
 
 
299
  options, build_files_arg = parser.parse_args(args)
 
300
  build_files = build_files_arg
 
301
 
 
302
  if not options.formats:
 
303
    # If no format was given on the command line, then check the env variable.
 
304
    generate_formats = []
 
305
    if options.use_environment:
 
306
      generate_formats = os.environ.get('GYP_GENERATORS', [])
 
307
    if generate_formats:
 
308
      generate_formats = re.split('[\s,]', generate_formats)
 
309
    if generate_formats:
 
310
      options.formats = generate_formats
 
311
    else:
 
312
      # Nothing in the variable, default based on platform.
 
313
      options.formats = [ {'darwin':   'xcode',
 
314
                           'win32':    'msvs',
 
315
                           'cygwin':   'msvs',
 
316
                           'freebsd7': 'make',
 
317
                           'freebsd8': 'make',
 
318
                           'linux2':   'make',
 
319
                           'openbsd4': 'make',
 
320
                           'sunos5':   'make',}[sys.platform] ]
 
321
 
 
322
  if not options.generator_output and options.use_environment:
 
323
    g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
 
324
    if g_o:
 
325
      options.generator_output = g_o
 
326
 
 
327
  for mode in options.debug:
 
328
    gyp.debug[mode] = 1
 
329
 
 
330
  # Do an extra check to avoid work when we're not debugging.
 
331
  if DEBUG_GENERAL in gyp.debug.keys():
 
332
    DebugOutput(DEBUG_GENERAL, 'running with these options:')
 
333
    for option, value in sorted(options.__dict__.items()):
 
334
      if option[0] == '_':
 
335
        continue
 
336
      if isinstance(value, basestring):
 
337
        DebugOutput(DEBUG_GENERAL, "  %s: '%s'" % (option, value))
 
338
      else:
 
339
        DebugOutput(DEBUG_GENERAL, "  %s: %s" % (option, str(value)))
 
340
 
 
341
  if not build_files:
 
342
    build_files = FindBuildFiles()
 
343
  if not build_files:
 
344
    print >>sys.stderr, (usage + '\n\n%s: error: no build_file') % \
 
345
                        (my_name, my_name)
 
346
    return 1
 
347
 
 
348
  # TODO(mark): Chromium-specific hack!
 
349
  # For Chromium, the gyp "depth" variable should always be a relative path
 
350
  # to Chromium's top-level "src" directory.  If no depth variable was set
 
351
  # on the command line, try to find a "src" directory by looking at the
 
352
  # absolute path to each build file's directory.  The first "src" component
 
353
  # found will be treated as though it were the path used for --depth.
 
354
  if not options.depth:
 
355
    for build_file in build_files:
 
356
      build_file_dir = os.path.abspath(os.path.dirname(build_file))
 
357
      build_file_dir_components = build_file_dir.split(os.path.sep)
 
358
      components_len = len(build_file_dir_components)
 
359
      for index in xrange(components_len - 1, -1, -1):
 
360
        if build_file_dir_components[index] == 'src':
 
361
          options.depth = os.path.sep.join(build_file_dir_components)
 
362
          break
 
363
        del build_file_dir_components[index]
 
364
 
 
365
      # If the inner loop found something, break without advancing to another
 
366
      # build file.
 
367
      if options.depth:
 
368
        break
 
369
 
 
370
    if not options.depth:
 
371
      raise Exception, \
 
372
            'Could not automatically locate src directory.  This is a ' + \
 
373
            'temporary Chromium feature that will be removed.  Use ' + \
 
374
            '--depth as a workaround.'
 
375
 
 
376
  # If toplevel-dir is not set, we assume that depth is the root of our source
 
377
  # tree.
 
378
  if not options.toplevel_dir:
 
379
    options.toplevel_dir = options.depth
 
380
 
 
381
  # -D on the command line sets variable defaults - D isn't just for define,
 
382
  # it's for default.  Perhaps there should be a way to force (-F?) a
 
383
  # variable's value so that it can't be overridden by anything else.
 
384
  cmdline_default_variables = {}
 
385
  defines = []
 
386
  if options.use_environment:
 
387
    defines += ShlexEnv('GYP_DEFINES')
 
388
  if options.defines:
 
389
    defines += options.defines
 
390
  cmdline_default_variables = NameValueListToDict(defines)
 
391
  if DEBUG_GENERAL in gyp.debug.keys():
 
392
    DebugOutput(DEBUG_GENERAL,
 
393
                "cmdline_default_variables: %s" % cmdline_default_variables)
 
394
 
 
395
  # Set up includes.
 
396
  includes = []
 
397
 
 
398
  # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
 
399
  # .gyp file that's loaded, before anything else is included.
 
400
  if home_dot_gyp != None:
 
401
    default_include = os.path.join(home_dot_gyp, 'include.gypi')
 
402
    if os.path.exists(default_include):
 
403
      includes.append(default_include)
 
404
 
 
405
  # Command-line --include files come after the default include.
 
406
  if options.includes:
 
407
    includes.extend(options.includes)
 
408
 
 
409
  # Generator flags should be prefixed with the target generator since they
 
410
  # are global across all generator runs.
 
411
  gen_flags = []
 
412
  if options.use_environment:
 
413
    gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
 
414
  if options.generator_flags:
 
415
    gen_flags += options.generator_flags
 
416
  generator_flags = NameValueListToDict(gen_flags)
 
417
  if DEBUG_GENERAL in gyp.debug.keys():
 
418
    DebugOutput(DEBUG_GENERAL, "generator_flags: %s" % generator_flags)
 
419
 
 
420
  # TODO: Remove this and the option after we've gotten folks to move to the
 
421
  # generator flag.
 
422
  if options.msvs_version:
 
423
    print >>sys.stderr, \
 
424
      'DEPRECATED: Use generator flag (-G msvs_version=' + \
 
425
      options.msvs_version + ') instead of --msvs-version=' + \
 
426
      options.msvs_version
 
427
    generator_flags['msvs_version'] = options.msvs_version
 
428
 
 
429
  # Generate all requested formats (use a set in case we got one format request
 
430
  # twice)
 
431
  for format in set(options.formats):
 
432
    params = {'options': options,
 
433
              'build_files': build_files,
 
434
              'generator_flags': generator_flags,
 
435
              'cwd': os.getcwd(),
 
436
              'build_files_arg': build_files_arg,
 
437
              'gyp_binary': sys.argv[0],
 
438
              'home_dot_gyp': home_dot_gyp}
 
439
 
 
440
    # Start with the default variables from the command line.
 
441
    [generator, flat_list, targets, data] = Load(build_files, format,
 
442
                                                 cmdline_default_variables,
 
443
                                                 includes, options.depth,
 
444
                                                 params, options.check,
 
445
                                                 options.circular_check)
 
446
 
 
447
    # TODO(mark): Pass |data| for now because the generator needs a list of
 
448
    # build files that came in.  In the future, maybe it should just accept
 
449
    # a list, and not the whole data dict.
 
450
    # NOTE: flat_list is the flattened dependency graph specifying the order
 
451
    # that targets may be built.  Build systems that operate serially or that
 
452
    # need to have dependencies defined before dependents reference them should
 
453
    # generate targets in the order specified in flat_list.
 
454
    generator.GenerateOutput(flat_list, targets, data, params)
 
455
 
 
456
  # Done
 
457
  return 0
 
458
 
 
459
 
 
460
if __name__ == '__main__':
 
461
  sys.exit(main(sys.argv[1:]))