#!/usr/bin/env python
#
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Generates XML file which can be imported into an Eclipse CDT project.

The XML file contains the include directories and defines that all applications
which use the clang compiler inherit. Should be used in conjunction with the
XML file generated by "gn gen out/Release --ide=eclipse"
"""


from xml.sax.saxutils import escape
import os
import subprocess
import sys

def GetClangIncludeDirectories(compiler_path):
  """Gets the system include directories as determined by the clang compiler.

  Returns:
    The list of include directories.
  """

  includes_set = set()

  command = [compiler_path, '-E', '-xc++', '-v', '-']
  proc = subprocess.Popen(args=command, stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  output = proc.communicate()[1]
  # Extract the list of include dirs from the output, which has this format:
  #   ...
  #   #include "..." search starts here:
  #   #include <...> search starts here:
  #    /usr/include/c++/4.6
  #    /usr/local/include
  #   End of search list.
  #   ...
  in_includes_list = False
  for line in output.splitlines():
    if line.startswith('#include'):
      in_includes_list = True
      continue
    if line.startswith('End of search list.'):
      break
    if in_includes_list:
      includes_set.add(line.strip())

  return sorted(includes_set)


def GetClangDefines(compiler_path):
  """Gets the system defines as determined by the clang compiler.

  Returns:
    The dict of defines.
  """

  all_defines = {}
  command = [compiler_path, '-E', '-dM', '-']
  proc = subprocess.Popen(args=command, stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE)

  # Extract the list of defines from the output, which has this format:
  # #define __SIZEOF_INT__ 4
  # ...
  # #define unix 1
  output = proc.communicate()[0]
  for line in output.splitlines():
    if not line.strip():
      continue
    line_parts = line.split(' ', 2)
    key = line_parts[1]
    if len(line_parts) >= 3:
      val = line_parts[2]
    else:
      val = '1'
    all_defines[key] = val

  return all_defines


def WriteIncludePaths(out, eclipse_langs, include_dirs):
  """Write the includes section of a CDT settings export file."""

  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
            'settingswizards.IncludePaths">\n')
  out.write('    <language name="holder for library settings"></language>\n')
  for lang in eclipse_langs:
    out.write('    <language name="%s">\n' % lang)
    for include_dir in include_dirs:
      out.write('      <includepath workspace_path="false">%s</includepath>\n' %
                include_dir)
    out.write('    </language>\n')
  out.write('  </section>\n')


def WriteMacros(out, eclipse_langs, defines):
  """Write the macros section of a CDT settings export file."""

  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
            'settingswizards.Macros">\n')
  out.write('    <language name="holder for library settings"></language>\n')
  for lang in eclipse_langs:
    out.write('    <language name="%s">\n' % lang)
    for key in sorted(defines.iterkeys()):
      out.write('      <macro><name>%s</name><value>%s</value></macro>\n' %
                (escape(key), escape(defines[key])))
    out.write('    </language>\n')
  out.write('  </section>\n')


def main(argv):
  if len(argv) != 2:
    print("Usage: generate_cdt_clang_settings.py destination_file")
    return

  compiler_path = os.path.abspath(
      'third_party/llvm-build/Release+Asserts/bin/clang')
  if not os.path.exists(compiler_path):
    print('Please run this script from the Chromium src/ directory.')
    return

  include_dirs = GetClangIncludeDirectories(compiler_path)
  if not include_dirs:
    print('ERROR: Could not extract include dirs from %s.' % compiler_path)
    return

  defines = GetClangDefines(compiler_path)
  if not defines:
    print('ERROR: Could not extract defines from %s.' % compiler_path)

  destination_file = os.path.abspath(argv[1])
  destination_dir = os.path.dirname(destination_file)
  if not os.path.exists(destination_dir):
    os.makedirs(destination_dir)

  with open(destination_file, 'w') as out:
    eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File',
                     'GNU C++', 'GNU C', 'Assembly']

    out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
    out.write('<cdtprojectproperties>\n')
    WriteIncludePaths(out, eclipse_langs, include_dirs)
    WriteMacros(out, eclipse_langs, defines)
    out.write('</cdtprojectproperties>\n')

if __name__ == '__main__':
  sys.exit(main(sys.argv))
