#!/usr/bin/env python3
# Copyright 2019 The Emscripten Authors.  All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License.  Both these licenses can be
# found in the LICENSE file.

"""Update 'symbols' files based on the contents of libraries in the cache.

The symbols files looks like the output of `nm` but only contain external
symbols and the symbols from all object in that archive are sorted and
de-duplicated.
"""

import sys
import argparse
import os
import filecmp

root_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
sys.path.insert(0, root_dir)
symbols_base_dir = os.path.join(root_dir, 'system', 'lib', 'symbols')
asmjs_symbols_dir = os.path.join(symbols_base_dir, 'asmjs')
wasm_symbols_dir = os.path.join(symbols_base_dir, 'wasm')

from tools import shared, cache
from tools.system_libs import Library

# Libraries that need .symbols file
target_libs = ['libal', 'libc', 'libc-extras', 'libcompiler_rt', 'libc-wasm',
               'libc++', 'libc++abi', 'libgl', 'libhtml5', 'libpthreads']


def get_symbols_dir():
  if shared.Settings.WASM_BACKEND:
    return wasm_symbols_dir
  else:
    return asmjs_symbols_dir


def is_symbol_file_supported(symbol_file):
  if shared.Settings.WASM_BACKEND:
    return os.path.abspath(symbol_file).startswith(wasm_symbols_dir)
  else:
    return os.path.abspath(symbol_file).startswith(asmjs_symbols_dir)


# Given a symbol file name, returns a matching library file name.
def get_lib_file(symbol_file):
  basename = os.path.splitext(os.path.basename(symbol_file))[0]
  cache_dir = cache.Cache().dirname
  lib_extension = 'a' if shared.Settings.WASM_BACKEND else 'bc'
  return os.path.join(cache_dir, basename + '.' + lib_extension)


# Given a library file name, returns a matching symbols file name.
def get_symbol_file(lib_file):
  basename = os.path.splitext(os.path.basename(lib_file))[0]
  return os.path.join(get_symbols_dir(), basename + '.symbols')


def filter_and_sort(symbols):
  lines = symbols.splitlines()
  lines = [l.rstrip() for l in lines]
  lines = [l for l in lines if l and l[-1] != ':']

  # Extract symbol type and name
  symbols = [l.split()[-2:] for l in lines]

  # Remove local symbols (lowercase type name)
  symbols = [(typ, name) for typ, name in symbols if typ.isupper()]

  symbol_map = {}
  for sym_type, sym_name in symbols:
    assert sym_type in ('W', 'T', 'D', 'C', 'U')
    existing_type = symbol_map.get(sym_name)
    if not existing_type:
      symbol_map[sym_name] = sym_type
      continue
    if existing_type == 'U' and sym_type != 'U':
      symbol_map[sym_name] = sym_type
    elif existing_type == 'W' and sym_type not in ('W', 'U'):
      symbol_map[sym_name] = sym_type
    elif sym_type not in ('W', 'U'):
      # We don't expect to see two defined version of a given symbol
      if existing_type != sym_type:
        print('Unexpected symbol types found: %s: %s vs %s' %
              (sym_name, existing_type, sym_type))
  symbols = [(typ, name) for name, typ in symbol_map.items()]

  # sort by name
  symbols.sort(key=lambda s: s[1])

  lines = ['# Auto-generated by tools/update_symbols.py.  DO NOT EDIT.']
  for typ, name in symbols:
    if typ == 'U':
      lines.append("         %s %s" % (typ, name))
    else:
      lines.append("-------- %s %s" % (typ, name))

  return '\n'.join(lines) + '\n'


def generate_symbol_file(symbol_file, lib_file):
  """Regenerate the contents of a given symbol file."""
  output = shared.run_process([shared.LLVM_NM, '-g', lib_file],
                              stdout=shared.PIPE).stdout
  new_symbols = filter_and_sort(output)
  with open(symbol_file, 'w') as f:
    f.write(new_symbols)


def main():
  parser = argparse.ArgumentParser(
      description=__doc__, usage="%(prog)s [options] [files ...]")
  parser.add_argument('files', metavar='files', type=str, nargs='*',
                      help='symbol files to regenerate (default: all)')
  args = parser.parse_args()

  if not shared.Settings.WASM:
    sys.stderr.write('This script only runs in WASM mode\n')
    sys.exit(1)

  shared.safe_ensure_dirs(get_symbols_dir())
  if args.files:
    for symbol_file in args.files:
      if not is_symbol_file_supported(symbol_file):
        print('skipping %s because it is not supported' % symbol_file)
        continue
      lib_file = get_lib_file(symbol_file)
      if not os.path.exists(lib_file):
        print('skipping %s because %s does not exist' % (symbol_file, lib_file))
        continue
      generate_symbol_file(symbol_file, lib_file)
  else:
    # Build all combinations of libraries and generate symbols files
    system_libs = Library.get_all_variations()
    for lib in system_libs.values():
      if lib.name not in target_libs:
        continue
      lib_file = lib.get_path()
      symbol_file = get_symbol_file(lib_file)
      generate_symbol_file(symbol_file, lib_file)

    # Not to generate too many symbols files with the same contents, if there
    # exists a default symbols file (that has a library name without any
    # suffices, such as -mt) and its contents are the same as another symbols
    # file with suffices, remove it.
    for lib in system_libs.values():
      if lib.name not in target_libs:
        continue
      lib_file = lib.get_path()
      symbol_file = get_symbol_file(lib_file)
      default_symbol_file = os.path.join(get_symbols_dir(),
                                         lib.name + '.symbols')
      if symbol_file != default_symbol_file and \
         os.path.isfile(default_symbol_file) and \
         filecmp.cmp(default_symbol_file, symbol_file):
        os.unlink(symbol_file)
  return 0


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