1c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org#!/usr/bin/env python
2cacb19013939eb665b7fb46068209f94be9b0b5fmark@chromium.org
3831ee126ee146d0740953d95e586a45b9bdbe26dsteveblock@chromium.org# Copyright (c) 2012 Google Inc. All rights reserved.
4df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org# Use of this source code is governed by a BSD-style license that can be
5df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org# found in the LICENSE file.
6df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org
7fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.orgimport copy
8f6d65a99233197a7b2e194d19be63ec85ff635d2mark@chromium.orgimport gyp.input
9a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.orgimport optparse
10cacb19013939eb665b7fb46068209f94be9b0b5fmark@chromium.orgimport os.path
111d6f22598b0995cbe4696d0fdc403a0ea7e538c5bradnelson@google.comimport re
120adefc99735bd48510089c07f0802ed83704b8ddsgk@chromium.orgimport shlex
13cacb19013939eb665b7fb46068209f94be9b0b5fmark@chromium.orgimport sys
1497ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.comimport traceback
15d3d94fcdfb9745d6784065cade320c2462924df9sbc@chromium.orgfrom gyp.common import GypError
16a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org
179def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.com# Default debug modes for GYP
1833d0f7ef6994003838f7d308e922616f5adad774gspencer@google.comdebug = {}
199def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.com
209def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.com# List of "official" debug modes, but you can use anything you like.
219def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.comDEBUG_GENERAL = 'general'
229def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.comDEBUG_VARIABLES = 'variables'
23217082c4e554b3f66e45729e24bbbffb5e9db305gspencer@google.comDEBUG_INCLUDES = 'includes'
249def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.com
25c1ced77af959d11dd80252ab471e89906ea70f09maruel@chromium.org
26e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.orgdef DebugOutput(mode, message, *args):
27e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org  if 'all' in gyp.debug or mode in gyp.debug:
2897ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com    ctx = ('unknown', 0, 'unknown')
2997ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com    try:
3097ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com      f = traceback.extract_stack(limit=2)
3197ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com      if f:
3297ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com        ctx = f[0][:3]
3397ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com    except:
3497ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com      pass
35e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org    if args:
36e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org      message %= args
3797ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com    print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
3897ad90ed7a275ffbfceb8424f41a0d702aa1d117bradnelson@google.com                              ctx[1], ctx[2], message)
39cacb19013939eb665b7fb46068209f94be9b0b5fmark@chromium.org
4016f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.orgdef FindBuildFiles():
4122bf54785eb1fec2a100fb79177ed34497e74292mark@chromium.org  extension = '.gyp'
4216f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  files = os.listdir(os.getcwd())
4316f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  build_files = []
4416f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  for file in files:
452fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org    if file.endswith(extension):
4616f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org      build_files.append(file)
4716f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  return build_files
4816f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org
4916f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org
5040ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.comdef Load(build_files, format, default_variables={},
519ab98f9c2e167392a6d47baaf3bc430a42dcf4c2dmazzoni@chromium.org         includes=[], depth='.', params=None, check=False,
521c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org         circular_check=True, duplicate_basename_check=True):
53fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  """
54fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  Loads one or more specified build files.
55fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  default_variables and includes will be copied before use.
56fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  Returns the generator for the specified format and the
57fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  data returned by loading the specified build files.
58fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  """
59c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  if params is None:
60c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    params = {}
61c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
62c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  flavor = None
63c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  if '-' in format:
64c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    format, params['flavor'] = format.split('-', 1)
65c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
66fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  default_variables = copy.copy(default_variables)
67817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org
68fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # Default variables provided by this program and its modules should be
69fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
70fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # avoiding collisions with user and automatic variables.
71fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  default_variables['GENERATOR'] = format
72fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org
731a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org  # Format can be a custom python file, or by default the name of a module
741a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org  # within gyp.generator.
751a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org  if format.endswith('.py'):
761a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    generator_name = os.path.splitext(format)[0]
771a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    path, generator_name = os.path.split(generator_name)
781a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org
791a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    # Make sure the path to the custom generator is in sys.path
801a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    # Don't worry about removing it once we are done.  Keeping the path
811a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    # to each generator that is used in sys.path is likely harmless and
821a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    # arguably a good idea.
831a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    path = os.path.abspath(path)
841a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    if path not in sys.path:
851a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org      sys.path.insert(0, path)
861a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org  else:
871a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org    generator_name = 'gyp.generator.' + format
881a7515121a2dc972e05cfec42a70fb98544cd8c1sbc@chromium.org
89fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # These parameters are passed in order (as opposed to by key)
90fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # because ActivePython cannot handle key parameters to __import__.
91fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  generator = __import__(generator_name, globals(), locals(), generator_name)
926fab4b7038e7a46ba7966623bb825c4652223f79mmoss@chromium.org  for (key, val) in generator.generator_default_variables.items():
936fab4b7038e7a46ba7966623bb825c4652223f79mmoss@chromium.org    default_variables.setdefault(key, val)
94817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org
9540ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com  # Give the generator the opportunity to set additional variables based on
9640ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com  # the params it will receive in the output phase.
9740ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com  if getattr(generator, 'CalculateVariables', None):
9840ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com    generator.CalculateVariables(default_variables, params)
9940ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com
100b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org  # Give the generator the opportunity to set generator_input_info based on
101b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org  # the params it will receive in the output phase.
102b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org  if getattr(generator, 'CalculateGeneratorInputInfo', None):
103b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org    generator.CalculateGeneratorInputInfo(params)
104b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org
105fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # Fetch the generator specific info that gets fed to input, we use getattr
106fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # so we can default things and the generators only have to provide what
107fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # they need.
108fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  generator_input_info = {
109fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org    'non_configuration_keys':
110fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org        getattr(generator, 'generator_additional_non_configuration_keys', []),
111fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org    'path_sections':
112fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org        getattr(generator, 'generator_additional_path_sections', []),
113fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org    'extra_sources_for_rules':
114fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org        getattr(generator, 'generator_extra_sources_for_rules', []),
115821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    'generator_supports_multiple_toolsets':
116821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com        getattr(generator, 'generator_supports_multiple_toolsets', False),
1176d8d580da0b6bcedf646b1b4fbc6e580d0254ff9evan@chromium.org    'generator_wants_static_library_dependencies_adjusted':
1186d8d580da0b6bcedf646b1b4fbc6e580d0254ff9evan@chromium.org        getattr(generator,
119b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org                'generator_wants_static_library_dependencies_adjusted', True),
120b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org    'generator_wants_sorted_dependencies':
121b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org        getattr(generator, 'generator_wants_sorted_dependencies', False),
122072660db6ec1fafc1e0997439b5015913f0b9aa5scottmg@chromium.org    'generator_filelist_paths':
123072660db6ec1fafc1e0997439b5015913f0b9aa5scottmg@chromium.org        getattr(generator, 'generator_filelist_paths', None),
124fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  }
125fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org
126fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  # Process the input specific to this generator.
127fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  result = gyp.input.Load(build_files, default_variables, includes[:],
1289ab98f9c2e167392a6d47baaf3bc430a42dcf4c2dmazzoni@chromium.org                          depth, generator_input_info, check, circular_check,
1291c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org                          duplicate_basename_check,
130beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig                          params['parallel'], params['root_targets'])
131fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org  return [generator] + result
132fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org
133413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.orgdef NameValueListToDict(name_value_list):
134413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  """
135413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
136413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  of the pairs.  If a string is simply NAME, then the value in the dictionary
137413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  is set to True.  If VALUE can be converted to an integer, it is.
138413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  """
139413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  result = { }
140413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  for item in name_value_list:
141413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org    tokens = item.split('=', 1)
142413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org    if len(tokens) == 2:
143413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      # If we can make it an int, use that, otherwise, use the string.
144413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      try:
145413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org        token_value = int(tokens[1])
146413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      except ValueError:
147413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org        token_value = tokens[1]
148413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      # Set the variable to the supplied value.
149413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      result[tokens[0]] = token_value
150413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org    else:
151413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      # No value supplied, treat it as a boolean and set it.
152413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org      result[tokens[0]] = True
153413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  return result
154fde9c3ff08e1db97b77bc639ffb6849be5fb74d8sgk@chromium.org
155c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.orgdef ShlexEnv(env_name):
156c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  flags = os.environ.get(env_name, [])
157c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if flags:
158c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    flags = shlex.split(flags)
159c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  return flags
160c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
161031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.orgdef FormatOpt(opt, value):
162031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org  if opt.startswith('--'):
163031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org    return '%s=%s' % (opt, value)
164031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org  return opt + value
165031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org
166c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.orgdef RegenerateAppendFlag(flag, values, predicate, env_name, options):
167c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  """Regenerate a list of command line flags, for an option of action='append'.
168c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
169c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  The |env_name|, if given, is checked in the environment and used to generate
170c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  an initial list of options, then the options that were specified on the
171c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  command line (given in |values|) are appended.  This matches the handling of
172c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  environment variables and command line flags where command line flags override
173c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  the environment, while not requiring the environment to be set when the flags
174c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  are used again.
175c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  """
176c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  flags = []
177c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if options.use_environment and env_name:
178c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    for flag_value in ShlexEnv(env_name):
179831ee126ee146d0740953d95e586a45b9bdbe26dsteveblock@chromium.org      value = FormatOpt(flag, predicate(flag_value))
180831ee126ee146d0740953d95e586a45b9bdbe26dsteveblock@chromium.org      if value in flags:
181831ee126ee146d0740953d95e586a45b9bdbe26dsteveblock@chromium.org        flags.remove(value)
182831ee126ee146d0740953d95e586a45b9bdbe26dsteveblock@chromium.org      flags.append(value)
183c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if values:
184c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    for flag_value in values:
185031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org      flags.append(FormatOpt(flag, predicate(flag_value)))
186c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  return flags
187c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
188c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.orgdef RegenerateFlags(options):
189c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  """Given a parsed options object, and taking the environment variables into
190c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  account, returns a list of flags that should regenerate an equivalent options
191c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  object (even in the absence of the environment variables.)
192c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
193c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  Any path options will be normalized relative to depth.
194c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
195c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  The format flag is not included, as it is assumed the calling generator will
196c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  set that as appropriate.
197c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  """
198c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  def FixPath(path):
199c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    path = gyp.common.FixIfRelativePath(path, options.depth)
200c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    if not path:
201c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      return os.path.curdir
202c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    return path
203c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
204c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  def Noop(value):
205c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    return value
206c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
207c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  # We always want to ignore the environment when regenerating, to avoid
208c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  # duplicate or changed flags in the environment at the time of regeneration.
209c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  flags = ['--ignore-environment']
210c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  for name, metadata in options._regeneration_metadata.iteritems():
211c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    opt = metadata['opt']
212c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    value = getattr(options, name)
213c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    value_predicate = metadata['type'] == 'path' and FixPath or Noop
214c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    action = metadata['action']
215c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    env_name = metadata['env_name']
216c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    if action == 'append':
217c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
218c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                                        env_name, options))
219031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org    elif action in ('store', None):  # None is a synonym for 'store'.
220c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      if value:
221031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org        flags.append(FormatOpt(opt, value_predicate(value)))
222c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      elif options.use_environment and env_name and os.environ.get(env_name):
223031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org        flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
224031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org    elif action in ('store_true', 'store_false'):
225031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org      if ((action == 'store_true' and value) or
226031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org          (action == 'store_false' and not value)):
227031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org        flags.append(opt)
228031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org      elif options.use_environment and env_name:
229031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org        print >>sys.stderr, ('Warning: environment regeneration unimplemented '
230031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org                             'for %s flag %r env_name %r' % (action, opt,
231031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org                                                             env_name))
232c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    else:
233031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org      print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
234031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org                           'flag %r' % (action, opt))
235c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
236c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  return flags
237c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
238c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.orgclass RegeneratableOptionParser(optparse.OptionParser):
239c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  def __init__(self):
240c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    self.__regeneratable_options = {}
241c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    optparse.OptionParser.__init__(self)
242c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
243c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  def add_option(self, *args, **kw):
244c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    """Add an option to the parser.
245c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
246c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    This accepts the same arguments as OptionParser.add_option, plus the
247c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    following:
248c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      regenerate: can be set to False to prevent this option from being included
249c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                  in regeneration.
250c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      env_name: name of environment variable that additional values for this
251c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                option come from.
252c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      type: adds type='path', to tell the regenerator that the values of
253c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org            this option need to be made relative to options.depth
254c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    """
255031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org    env_name = kw.pop('env_name', None)
256c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    if 'dest' in kw and kw.pop('regenerate', True):
257c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      dest = kw['dest']
258c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
259c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      # The path type is needed for regenerating, for optparse we can just treat
260c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      # it as a string.
261c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      type = kw.get('type')
262c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      if type == 'path':
263c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org        kw['type'] = 'string'
264c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
265c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      self.__regeneratable_options[dest] = {
266c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org          'action': kw.get('action'),
267c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org          'type': type,
268c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org          'env_name': env_name,
269031237710478fe5eaa8e7558d72c35f80e243190mmoss@chromium.org          'opt': args[0],
270c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org        }
271c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
272c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    optparse.OptionParser.add_option(self, *args, **kw)
273c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
274c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  def parse_args(self, *args):
275c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    values, args = optparse.OptionParser.parse_args(self, *args)
276c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    values._regeneration_metadata = self.__regeneratable_options
277c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    return values, args
278c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
2792fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.orgdef gyp_main(args):
280a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org  my_name = os.path.basename(sys.argv[0])
281a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org
282c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  parser = RegeneratableOptionParser()
283676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  usage = 'usage: %s [options ...] [build_file ...]'
28422bf54785eb1fec2a100fb79177ed34497e74292mark@chromium.org  parser.set_usage(usage.replace('%s', '%prog'))
2857e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('--build', dest='configs', action='append',
2867e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='configuration for build after project generation')
2877e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('--check', dest='check', action='store_true',
2887e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='check format of gyp files')
2897e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('--config-dir', dest='config_dir', action='store',
2907e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    env_name='GYP_CONFIG_DIR', default=None,
2917e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='The location for configuration files like '
2927e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    'include.gypi.')
2937e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
2947e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    action='append', default=[], help='turn on a debugging '
2957e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    'mode for debugging GYP.  Supported modes are "variables", '
2967e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    '"includes" and "general" or "all" for all of them.')
2971d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org  parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
298c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    env_name='GYP_DEFINES',
2991d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org                    help='sets variable VAR to value VAL')
3007e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
3017e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='set DEPTH gyp variable to a relative path to PATH')
302d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  parser.add_option('-f', '--format', dest='formats', action='append',
303c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    env_name='GYP_GENERATORS', regenerate=False,
304d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org                    help='output formats to generate')
305413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  parser.add_option('-G', dest='generator_flags', action='append', default=[],
306c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
307c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    help='sets generator flag FLAG to VAL')
3089c88b549cd9f1773ed472daa27d6cbd8bc690b41sgk@chromium.org  parser.add_option('--generator-output', dest='generator_output',
309c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    action='store', default=None, metavar='DIR', type='path',
310c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    env_name='GYP_GENERATOR_OUTPUT',
3119c88b549cd9f1773ed472daa27d6cbd8bc690b41sgk@chromium.org                    help='puts generated build files under DIR')
312c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  parser.add_option('--ignore-environment', dest='use_environment',
313c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    action='store_false', default=True, regenerate=False,
314c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org                    help='do not read options from environment variables')
3157e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('-I', '--include', dest='includes', action='append',
3167e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    metavar='INCLUDE', type='path',
3177e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='files to include in all loaded .gyp files')
318496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # --no-circular-check disables the check for circular relationships between
319496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # .gyp files.  These relationships should not exist, but they've only been
320496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # observed to be harmful with the Xcode generator.  Chromium's .gyp files
321496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # currently have some circular relationships on non-Mac platforms, so this
322496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # option allows the strict behavior to be used on Macs and the lenient
323496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # behavior to be used elsewhere.
324496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
325496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org  parser.add_option('--no-circular-check', dest='circular_check',
326496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org                    action='store_false', default=True, regenerate=False,
327496290f0d7026d1c763087bae53acdc1c6ecdd3fmark@chromium.org                    help="don't check for circular relationships between files")
3281c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # --no-duplicate-basename-check disables the check for duplicate basenames
3291c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # in a static_library/shared_library project. Visual C++ 2008 generator
3301c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # doesn't support this configuration. Libtool on Mac also generates warnings
3311c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # when duplicate basenames are passed into Make generator on Mac.
3321c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # TODO(yukawa): Remove this option when these legacy generators are
3331c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  # deprecated.
3341c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  parser.add_option('--no-duplicate-basename-check',
3351c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org                    dest='duplicate_basename_check', action='store_false',
3361c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org                    default=True, regenerate=False,
3371c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org                    help="don't check for duplicate basenames")
338072660db6ec1fafc1e0997439b5015913f0b9aa5scottmg@chromium.org  parser.add_option('--no-parallel', action='store_true', default=False,
339072660db6ec1fafc1e0997439b5015913f0b9aa5scottmg@chromium.org                    help='Disable multiprocessing')
3407e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('-S', '--suffix', dest='suffix', default='',
3417e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='suffix to add to generated files')
3427e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
3437e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    default=None, metavar='DIR', type='path',
3447e2399c80b851754358adffc821699045534cd0egspencer@chromium.org                    help='directory to use as the root of the source tree')
345beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig  parser.add_option('-R', '--root-target', dest='root_targets',
346beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig                    action='append', metavar='TARGET',
347beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig                    help='include only TARGET and its deep dependencies')
348817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org
349cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org  options, build_files_arg = parser.parse_args(args)
350c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  build_files = build_files_arg
3519def40ccb23ce0a125b35719650a16cbb4c2f22fgspencer@google.com
3527e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  # Set up the configuration directory (defaults to ~/.gyp)
3537e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  if not options.config_dir:
3547e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    home = None
3557e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    home_dot_gyp = None
3567e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    if options.use_environment:
3577e2399c80b851754358adffc821699045534cd0egspencer@chromium.org      home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
3587e2399c80b851754358adffc821699045534cd0egspencer@chromium.org      if home_dot_gyp:
3597e2399c80b851754358adffc821699045534cd0egspencer@chromium.org        home_dot_gyp = os.path.expanduser(home_dot_gyp)
3607e2399c80b851754358adffc821699045534cd0egspencer@chromium.org
3617e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    if not home_dot_gyp:
3627e2399c80b851754358adffc821699045534cd0egspencer@chromium.org      home_vars = ['HOME']
363ee8b4571e3d6c5f39ba72c6885b53e9404642985thakis@chromium.org      if sys.platform in ('cygwin', 'win32'):
3647e2399c80b851754358adffc821699045534cd0egspencer@chromium.org        home_vars.append('USERPROFILE')
3657e2399c80b851754358adffc821699045534cd0egspencer@chromium.org      for home_var in home_vars:
3667e2399c80b851754358adffc821699045534cd0egspencer@chromium.org        home = os.getenv(home_var)
3677e2399c80b851754358adffc821699045534cd0egspencer@chromium.org        if home != None:
3687e2399c80b851754358adffc821699045534cd0egspencer@chromium.org          home_dot_gyp = os.path.join(home, '.gyp')
3697e2399c80b851754358adffc821699045534cd0egspencer@chromium.org          if not os.path.exists(home_dot_gyp):
3707e2399c80b851754358adffc821699045534cd0egspencer@chromium.org            home_dot_gyp = None
3717e2399c80b851754358adffc821699045534cd0egspencer@chromium.org          else:
3727e2399c80b851754358adffc821699045534cd0egspencer@chromium.org            break
3737e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  else:
3747e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    home_dot_gyp = os.path.expanduser(options.config_dir)
3757e2399c80b851754358adffc821699045534cd0egspencer@chromium.org
3767e2399c80b851754358adffc821699045534cd0egspencer@chromium.org  if home_dot_gyp and not os.path.exists(home_dot_gyp):
3777e2399c80b851754358adffc821699045534cd0egspencer@chromium.org    home_dot_gyp = None
3787e2399c80b851754358adffc821699045534cd0egspencer@chromium.org
379d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  if not options.formats:
380817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org    # If no format was given on the command line, then check the env variable.
381c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    generate_formats = []
382c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    if options.use_environment:
383c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      generate_formats = os.environ.get('GYP_GENERATORS', [])
384817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org    if generate_formats:
3853c044d16f852be036bb8bb71e55fde45b01946cdsgk@chromium.org      generate_formats = re.split('[\s,]', generate_formats)
386817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org    if generate_formats:
387817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org      options.formats = generate_formats
388817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org    else:
389817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org      # Nothing in the variable, default based on platform.
390fa1ff074d693ee9b3b3cd4ca8e618ebb85ad8237tony@chromium.org      if sys.platform == 'darwin':
391fa1ff074d693ee9b3b3cd4ca8e618ebb85ad8237tony@chromium.org        options.formats = ['xcode']
392ee8b4571e3d6c5f39ba72c6885b53e9404642985thakis@chromium.org      elif sys.platform in ('win32', 'cygwin'):
393fa1ff074d693ee9b3b3cd4ca8e618ebb85ad8237tony@chromium.org        options.formats = ['msvs']
394fa1ff074d693ee9b3b3cd4ca8e618ebb85ad8237tony@chromium.org      else:
395fa1ff074d693ee9b3b3cd4ca8e618ebb85ad8237tony@chromium.org        options.formats = ['make']
396676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org
397c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if not options.generator_output and options.use_environment:
398c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
399c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    if g_o:
400c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      options.generator_output = g_o
401c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
402072660db6ec1fafc1e0997439b5015913f0b9aa5scottmg@chromium.org  options.parallel = not options.no_parallel
4039ab98f9c2e167392a6d47baaf3bc430a42dcf4c2dmazzoni@chromium.org
404c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  for mode in options.debug:
405c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    gyp.debug[mode] = 1
406c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
407c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  # Do an extra check to avoid work when we're not debugging.
408e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org  if DEBUG_GENERAL in gyp.debug:
409c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    DebugOutput(DEBUG_GENERAL, 'running with these options:')
410cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    for option, value in sorted(options.__dict__.items()):
411c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      if option[0] == '_':
412c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org        continue
413c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      if isinstance(value, basestring):
414e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org        DebugOutput(DEBUG_GENERAL, "  %s: '%s'", option, value)
415c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      else:
416e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org        DebugOutput(DEBUG_GENERAL, "  %s: %s", option, value)
417c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
41816f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  if not build_files:
41916f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org    build_files = FindBuildFiles()
420a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org  if not build_files:
4212fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org    raise GypError((usage + '\n\n%s: error: no build_file') %
4222fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org                   (my_name, my_name))
423a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org
424676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # TODO(mark): Chromium-specific hack!
425676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # For Chromium, the gyp "depth" variable should always be a relative path
426676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # to Chromium's top-level "src" directory.  If no depth variable was set
427676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # on the command line, try to find a "src" directory by looking at the
428676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # absolute path to each build file's directory.  The first "src" component
429676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  # found will be treated as though it were the path used for --depth.
430676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org  if not options.depth:
431676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org    for build_file in build_files:
432676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      build_file_dir = os.path.abspath(os.path.dirname(build_file))
433676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      build_file_dir_components = build_file_dir.split(os.path.sep)
434676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      components_len = len(build_file_dir_components)
435676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      for index in xrange(components_len - 1, -1, -1):
436676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org        if build_file_dir_components[index] == 'src':
437676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org          options.depth = os.path.sep.join(build_file_dir_components)
438676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org          break
439676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org        del build_file_dir_components[index]
440676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org
441676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      # If the inner loop found something, break without advancing to another
442676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      # build file.
443676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org      if options.depth:
444676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org        break
445676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org
446676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org    if not options.depth:
4472fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org      raise GypError('Could not automatically locate src directory.  This is'
4482fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org                     'a temporary Chromium feature that will be removed.  Use'
4492fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org                     '--depth as a workaround.')
450676305c32b799705b8dbe8fd00f4bafaad59a023mark@chromium.org
451cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org  # If toplevel-dir is not set, we assume that depth is the root of our source
452cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org  # tree.
453cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org  if not options.toplevel_dir:
454cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    options.toplevel_dir = options.depth
455cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org
4561d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org  # -D on the command line sets variable defaults - D isn't just for define,
4571d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org  # it's for default.  Perhaps there should be a way to force (-F?) a
4581d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org  # variable's value so that it can't be overridden by anything else.
459d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  cmdline_default_variables = {}
460c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  defines = []
461c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if options.use_environment:
462c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    defines += ShlexEnv('GYP_DEFINES')
4631d4bf03af656e8f45c6ff3edd85af569acf710aamark@chromium.org  if options.defines:
4640adefc99735bd48510089c07f0802ed83704b8ddsgk@chromium.org    defines += options.defines
465413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  cmdline_default_variables = NameValueListToDict(defines)
466e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org  if DEBUG_GENERAL in gyp.debug:
467c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    DebugOutput(DEBUG_GENERAL,
468e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org                "cmdline_default_variables: %s", cmdline_default_variables)
469475089d4d1a7ea54e6f25312d665da1e982d96d0mark@chromium.org
47079692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  # Set up includes.
47179692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  includes = []
47279692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org
47379692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
47479692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  # .gyp file that's loaded, before anything else is included.
475817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org  if home_dot_gyp != None:
476817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org    default_include = os.path.join(home_dot_gyp, 'include.gypi')
47779692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org    if os.path.exists(default_include):
4788051f4242ca0291165aef138ab4b621eb3128d92thomasvl@chromium.org      print 'Using overrides found in ' + default_include
47979692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org      includes.append(default_include)
48079692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org
48179692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  # Command-line --include files come after the default include.
48279692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org  if options.includes:
48379692c0bed2f35ddfa3bfe86fe16e678c9433f06mark@chromium.org    includes.extend(options.includes)
484817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org
485d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  # Generator flags should be prefixed with the target generator since they
486d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  # are global across all generator runs.
487c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  gen_flags = []
488c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if options.use_environment:
489c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
490413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  if options.generator_flags:
491413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org    gen_flags += options.generator_flags
492413fae9c2f955a0e4898c51a2d9c76aa1a493b83thomasvl@chromium.org  generator_flags = NameValueListToDict(gen_flags)
493c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  if DEBUG_GENERAL in gyp.debug.keys():
494e57bc16e9c9dfa3cd39b9c0fc7a1a5fa66a1903cthakis@chromium.org    DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)
495c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
496817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org  # Generate all requested formats (use a set in case we got one format request
497817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org  # twice)
498817da792b2cee3bbcc185045deae8b0fce2739cbthomasvl@chromium.org  for format in set(options.formats):
49940ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com    params = {'options': options,
50040ac74c52f7dde42b0e9310eb975c7d63a2eb437bradnelson@google.com              'build_files': build_files,
5019c88b549cd9f1773ed472daa27d6cbd8bc690b41sgk@chromium.org              'generator_flags': generator_flags,
502c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org              'cwd': os.getcwd(),
503c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org              'build_files_arg': build_files_arg,
50407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org              'gyp_binary': sys.argv[0],
5055a10131a4bf9462ebf86224278d8db66487064b5dmazzoni@chromium.org              'home_dot_gyp': home_dot_gyp,
506beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig              'parallel': options.parallel,
507beca12a56c0772fc8263ad7ca12ca022b8671c1csbaig              'root_targets': options.root_targets}
508d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org
509d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # Start with the default variables from the command line.
5101c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    [generator, flat_list, targets, data] = Load(
5111c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        build_files, format, cmdline_default_variables, includes, options.depth,
5121c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        params, options.check, options.circular_check,
5131c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        options.duplicate_basename_check)
514d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org
515d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # TODO(mark): Pass |data| for now because the generator needs a list of
516d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # build files that came in.  In the future, maybe it should just accept
517d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # a list, and not the whole data dict.
518d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # NOTE: flat_list is the flattened dependency graph specifying the order
519d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # that targets may be built.  Build systems that operate serially or that
520d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # need to have dependencies defined before dependents reference them should
521d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    # generate targets in the order specified in flat_list.
522d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org    generator.GenerateOutput(flat_list, targets, data, params)
523d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org
52408fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    if options.configs:
52508fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org      valid_configs = targets[flat_list[0]]['configurations'].keys()
52608fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org      for conf in options.configs:
52708fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org        if conf not in valid_configs:
52808fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org          raise GypError('Invalid config specified via --build: %s' % conf)
52908fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org      generator.PerformBuild(data, options.configs, params)
53008fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org
531d8c2237ec6634a9183d906a5aa7762816a80af0fthomasvl@chromium.org  # Done
53216f66331f709d9ed362d0b1c2f3781b40928b653mark@chromium.org  return 0
533a85d7de5129e37e558dc6e9c70ded4d300a71c5emark@chromium.org
534cacb19013939eb665b7fb46068209f94be9b0b5fmark@chromium.org
5352fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.orgdef main(args):
5362fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org  try:
5372fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org    return gyp_main(args)
5382fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org  except GypError, e:
5392fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org    sys.stderr.write("gyp: %s\n" % e)
5402fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org    return 1
5412fc70cd0cddfc54809a3ab21b193f778343a3a89sbc@chromium.org
542e7d6d052f9e0cbba7ca11414495c54207f4aacfesbaig# NOTE: setuptools generated console_scripts calls function with no arguments
543e7d6d052f9e0cbba7ca11414495c54207f4aacfesbaigdef script_main():
544e7d6d052f9e0cbba7ca11414495c54207f4aacfesbaig  return main(sys.argv[1:])
545e7d6d052f9e0cbba7ca11414495c54207f4aacfesbaig
54622bf54785eb1fec2a100fb79177ed34497e74292mark@chromium.orgif __name__ == '__main__':
547e7d6d052f9e0cbba7ca11414495c54207f4aacfesbaig  sys.exit(script_main())
548