#!/usr/bin/env python
#
# Copyright 2016 The Chromium Authors
# 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 __future__ import print_function

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))
