1b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org# Copyright (c) 2012 Google Inc. All rights reserved.
2b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org# Use of this source code is governed by a BSD-style license that can be
3b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org# found in the LICENSE file.
4b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
5b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org"""GYP backend that generates Eclipse CDT settings files.
6b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
7b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgThis backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML
8b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgfiles that can be imported into an Eclipse CDT project. The XML file contains a
9b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orglist of include paths and symbols (i.e. defines).
10b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
11b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgBecause a full .cproject definition is not created by this generator, it's not
12b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgpossible to properly define the include dirs and symbols for each file
13b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgindividually.  Instead, one set of includes/symbols is generated for the entire
14b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgproject.  This works fairly well (and is a vast improvement in general), but may
15b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgstill result in a few indexer issues here and there.
16b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
17b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgThis generator has no automated tests, so expect it to be broken.
18b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org"""
19b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
204051c257283eb3ca07dfdedefa34d7e2cd8c1975thakis@chromium.orgfrom xml.sax.saxutils import escape
21b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgimport os.path
22b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgimport subprocess
23b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgimport gyp
24b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgimport gyp.common
259820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.orgimport gyp.msvs_emulation
26b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgimport shlex
27b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
28b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orggenerator_wants_static_library_dependencies_adjusted = False
29b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
30b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orggenerator_default_variables = {
31b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org}
32b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
33b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgfor dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']:
34b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # Some gyp steps fail if these are empty(!).
35b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  generator_default_variables[dirname] = 'dir'
36b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
37b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgfor unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
38b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org               'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
39b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org               'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
40b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org               'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
414051c257283eb3ca07dfdedefa34d7e2cd8c1975thakis@chromium.org               'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
424051c257283eb3ca07dfdedefa34d7e2cd8c1975thakis@chromium.org               'CONFIGURATION_NAME']:
43b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  generator_default_variables[unused] = ''
44b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
45061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as
46b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org# part of the path when dealing with generated headers.  This value will be
47b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org# replaced dynamically for each configuration.
48b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orggenerator_default_variables['SHARED_INTERMEDIATE_DIR'] = \
49061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org    '$SHARED_INTERMEDIATE_DIR'
50b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
51b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
52b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef CalculateVariables(default_variables, params):
53b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  generator_flags = params.get('generator_flags', {})
54b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for key, val in generator_flags.items():
55b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    default_variables.setdefault(key, val)
569820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  flavor = gyp.common.GetFlavor(params)
579820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  default_variables.setdefault('OS', flavor)
589820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  if flavor == 'win':
599820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    # Copy additional generator configuration data from VS, which is shared
609820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    # by the Eclipse generator.
619820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    import gyp.generator.msvs as msvs_generator
629820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    generator_additional_non_configuration_keys = getattr(msvs_generator,
639820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        'generator_additional_non_configuration_keys', [])
649820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    generator_additional_path_sections = getattr(msvs_generator,
659820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        'generator_additional_path_sections', [])
669820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org
67d298d5f26cc170b170ccb42a913dddb401581e27scottmg@chromium.org    gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
68b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
69b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
70b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef CalculateGeneratorInputInfo(params):
71b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Calculate the generator specific info that gets fed to input (called by
72b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  gyp)."""
73b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  generator_flags = params.get('generator_flags', {})
74b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  if generator_flags.get('adjust_static_libraries', False):
75b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    global generator_wants_static_library_dependencies_adjusted
76b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    generator_wants_static_library_dependencies_adjusted = True
77b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
78b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
79b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef GetAllIncludeDirectories(target_list, target_dicts,
804a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                             shared_intermediate_dirs, config_name, params,
814a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                             compiler_path):
82b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Calculate the set of include directories to be used.
83b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
84b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  Returns:
85b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    A list including all the include_dir's specified for every target followed
86b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    by any include directories that were added as cflag compiler options.
87b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """
88b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
89b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  gyp_includes_set = set()
90b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  compiler_includes_list = []
91b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
924a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org  # Find compiler's default include dirs.
934a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org  if compiler_path:
944a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    command = shlex.split(compiler_path)
954a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    command.extend(['-E', '-xc++', '-v', '-'])
964a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    proc = subprocess.Popen(args=command, stdin=subprocess.PIPE,
974a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
984a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    output = proc.communicate()[1]
994a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    # Extract the list of include dirs from the output, which has this format:
1004a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #   ...
1014a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #   #include "..." search starts here:
1024a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #   #include <...> search starts here:
1034a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #    /usr/include/c++/4.6
1044a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #    /usr/local/include
1054a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #   End of search list.
1064a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    #   ...
1074a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    in_include_list = False
1084a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    for line in output.splitlines():
1094a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org      if line.startswith('#include'):
1104a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org        in_include_list = True
1114a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org        continue
1124a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org      if line.startswith('End of search list.'):
1134a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org        break
1144a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org      if in_include_list:
1154a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org        include_dir = line.strip()
1164a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org        if include_dir not in compiler_includes_list:
1174a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org          compiler_includes_list.append(include_dir)
1184a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org
1199820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  flavor = gyp.common.GetFlavor(params)
1209820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  if flavor == 'win':
1219820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    generator_flags = params.get('generator_flags', {})
122b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for target_name in target_list:
123b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    target = target_dicts[target_name]
124b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    if config_name in target['configurations']:
125b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      config = target['configurations'][config_name]
126b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
127b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      # Look for any include dirs that were explicitly added via cflags. This
128b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      # may be done in gyp files to force certain includes to come at the end.
129b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and
130b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      # remove this.
1319820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      if flavor == 'win':
1329820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags)
1339820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        cflags = msvs_settings.GetCflags(config_name)
1349820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      else:
1359820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        cflags = config['cflags']
136b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      for cflag in cflags:
137b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org        if cflag.startswith('-I'):
138b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org          include_dir = cflag[2:]
1394a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org          if include_dir not in compiler_includes_list:
1404a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org            compiler_includes_list.append(include_dir)
141b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
142b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      # Find standard gyp include dirs.
143b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      if config.has_key('include_dirs'):
144b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org        include_dirs = config['include_dirs']
145061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org        for shared_intermediate_dir in shared_intermediate_dirs:
146061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org          for include_dir in include_dirs:
147061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org            include_dir = include_dir.replace('$SHARED_INTERMEDIATE_DIR',
148061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org                                              shared_intermediate_dir)
149061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org            if not os.path.isabs(include_dir):
150061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org              base_dir = os.path.dirname(target_name)
151b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
152061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org              include_dir = base_dir + '/' + include_dir
153061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org              include_dir = os.path.abspath(include_dir)
154b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
1554a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org            gyp_includes_set.add(include_dir)
156b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
157b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # Generate a list that has all the include dirs.
158b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  all_includes_list = list(gyp_includes_set)
159b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  all_includes_list.sort()
160b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for compiler_include in compiler_includes_list:
161b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    if not compiler_include in gyp_includes_set:
162b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      all_includes_list.append(compiler_include)
163b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
164b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # All done.
165b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  return all_includes_list
166b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
167b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
168c2f33dbfd5b14c40f8c344788f2966fae3a764dathakis@chromium.orgdef GetCompilerPath(target_list, data, options):
169b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Determine a command that can be used to invoke the compiler.
170b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
171b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  Returns:
172b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    If this is a gyp project that has explicit make settings, try to determine
173b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    the compiler from that.  Otherwise, see if a compiler was specified via the
174b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    CC_target environment variable.
175b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """
176b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # First, see if the compiler is configured in make's settings.
177b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
178b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  make_global_settings_dict = data[build_file].get('make_global_settings', {})
179b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for key, value in make_global_settings_dict:
180b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    if key in ['CC', 'CXX']:
181c2f33dbfd5b14c40f8c344788f2966fae3a764dathakis@chromium.org      return os.path.join(options.toplevel_dir, value)
182b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
183b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # Check to see if the compiler was specified as an environment variable.
184b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for key in ['CC_target', 'CC', 'CXX']:
185b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    compiler = os.environ.get(key)
186b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    if compiler:
187b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      return compiler
188b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
189b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  return 'gcc'
190b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
191b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
1924a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.orgdef GetAllDefines(target_list, target_dicts, data, config_name, params,
1934a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                  compiler_path):
194b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Calculate the defines for a project.
195b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
196b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  Returns:
197b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    A dict that includes explict defines declared in gyp files along with all of
198b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    the default defines that the compiler uses.
199b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """
200b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
201b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # Get defines declared in the gyp files.
202b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  all_defines = {}
2039820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  flavor = gyp.common.GetFlavor(params)
2049820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  if flavor == 'win':
2059820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    generator_flags = params.get('generator_flags', {})
206b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for target_name in target_list:
207b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    target = target_dicts[target_name]
208b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
2099820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    if flavor == 'win':
2109820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags)
2119820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      extra_defines = msvs_settings.GetComputedDefines(config_name)
2129820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    else:
2139820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      extra_defines = []
214b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    if config_name in target['configurations']:
215b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      config = target['configurations'][config_name]
2169820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      target_defines = config['defines']
2179820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    else:
2189820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      target_defines = []
2199820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    for define in target_defines + extra_defines:
2209820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      split_define = define.split('=', 1)
2219820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      if len(split_define) == 1:
2229820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        split_define.append('1')
2239820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      if split_define[0].strip() in all_defines:
2249820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        # Already defined
2259820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org        continue
2269820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org      all_defines[split_define[0].strip()] = split_define[1].strip()
227b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # Get default compiler defines (if possible).
2289820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org  if flavor == 'win':
2299820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org    return all_defines  # Default defines already processed in the loop above.
2304a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org  if compiler_path:
2314a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org    command = shlex.split(compiler_path)
232b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    command.extend(['-E', '-dM', '-'])
233b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    cpp_proc = subprocess.Popen(args=command, cwd='.',
234b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                                stdin=subprocess.PIPE, stdout=subprocess.PIPE)
235b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    cpp_output = cpp_proc.communicate()[0]
236b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    cpp_lines = cpp_output.split('\n')
237b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    for cpp_line in cpp_lines:
238b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      if not cpp_line.strip():
239b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org        continue
240b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      cpp_line_parts = cpp_line.split(' ', 2)
241b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      key = cpp_line_parts[1]
242b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      if len(cpp_line_parts) >= 3:
243b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org        val = cpp_line_parts[2]
244b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      else:
245b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org        val = '1'
246b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      all_defines[key] = val
247b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
248b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  return all_defines
249b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
250b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
251b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef WriteIncludePaths(out, eclipse_langs, include_dirs):
252b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Write the includes section of a CDT settings export file."""
253b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
254b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
255b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org            'settingswizards.IncludePaths">\n')
256b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('    <language name="holder for library settings"></language>\n')
257b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for lang in eclipse_langs:
258b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    out.write('    <language name="%s">\n' % lang)
259b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    for include_dir in include_dirs:
260b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      out.write('      <includepath workspace_path="false">%s</includepath>\n' %
261b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                include_dir)
262b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    out.write('    </language>\n')
263b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('  </section>\n')
264b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
265b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
266b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef WriteMacros(out, eclipse_langs, defines):
267b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Write the macros section of a CDT settings export file."""
268b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
269b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
270b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org            'settingswizards.Macros">\n')
271b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('    <language name="holder for library settings"></language>\n')
272b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  for lang in eclipse_langs:
273b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    out.write('    <language name="%s">\n' % lang)
274b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    for key in sorted(defines.iterkeys()):
275b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      out.write('      <macro><name>%s</name><value>%s</value></macro>\n' %
2764051c257283eb3ca07dfdedefa34d7e2cd8c1975thakis@chromium.org                (escape(key), escape(defines[key])))
277b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    out.write('    </language>\n')
278b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('  </section>\n')
279b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
280b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
281b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef GenerateOutputForConfig(target_list, target_dicts, data, params,
282b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                            config_name):
283b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  options = params['options']
284b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  generator_flags = params.get('generator_flags', {})
285b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
286b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # build_dir: relative path from source root to our output files.
287b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  # e.g. "out/Debug"
288b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  build_dir = os.path.join(generator_flags.get('output_dir', 'out'),
289b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                           config_name)
290b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
291b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  toplevel_build = os.path.join(options.toplevel_dir, build_dir)
292061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org  # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the
293061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org  # SHARED_INTERMEDIATE_DIR. Include both possible locations.
294061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org  shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'),
295061b1ecd71abd3060d5646a84a7105e571516202thakis@chromium.org                              os.path.join(toplevel_build, 'gen')]
296b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
297b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org  out_name = os.path.join(toplevel_build, 'eclipse-cdt-settings.xml')
298b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org  gyp.common.EnsureDirExists(out_name)
299b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org  out = open(out_name, 'w')
300b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
301b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
302b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('<cdtprojectproperties>\n')
303b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
304b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File',
305b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                   'GNU C++', 'GNU C', 'Assembly']
306c2f33dbfd5b14c40f8c344788f2966fae3a764dathakis@chromium.org  compiler_path = GetCompilerPath(target_list, data, options)
307b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  include_dirs = GetAllIncludeDirectories(target_list, target_dicts,
3089820176fbe19ce21858882df0d3024bf47fc7455thakis@chromium.org                                          shared_intermediate_dirs, config_name,
3094a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                                          params, compiler_path)
310b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  WriteIncludePaths(out, eclipse_langs, include_dirs)
3114a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org  defines = GetAllDefines(target_list, target_dicts, data, config_name, params,
3124a8a15f6333b72b02ca919825a1d0881d3ed1dbbthakis@chromium.org                          compiler_path)
313b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  WriteMacros(out, eclipse_langs, defines)
314b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
315b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.write('</cdtprojectproperties>\n')
316b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  out.close()
317b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
318b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
319b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.orgdef GenerateOutput(target_list, target_dicts, data, params):
320b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  """Generate an XML settings file that can be imported into a CDT project."""
321b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
322b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  if params['options'].generator_output:
323b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    raise NotImplementedError, "--generator_output not implemented for eclipse"
324b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
325b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  user_config = params.get('generator_flags', {}).get('config', None)
326b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  if user_config:
327b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    GenerateOutputForConfig(target_list, target_dicts, data, params,
328b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                            user_config)
329b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org  else:
330b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    config_names = target_dicts[target_list[0]]['configurations'].keys()
331b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org    for config_name in config_names:
332b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org      GenerateOutputForConfig(target_list, target_dicts, data, params,
333b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org                              config_name)
334b9227b4de8268024460b3ff08a2abac964b18a8dthakis@chromium.org
335