#!/usr/bin/env python

# NOTE: This script requires python 3.

"""Script to generate Chromium's Abseil .def files at roll time.

This script generates //third_party/abseil-app/absl/symbols_*.def at Abseil
roll time.

Since Abseil doesn't export symbols, Chromium is forced to consider all
Abseil's symbols as publicly visible. On POSIX it is possible to use
-fvisibility=default but on Windows a .def file with all the symbols
is needed.

Unless you are on a Windows machine, you need to set up your Chromium
checkout for cross-compilation by following the instructions at
https://chromium.googlesource.com/chromium/src.git/+/main/docs/win_cross.md.
If you are on Windows, you may need to tweak this script to run, e.g. by
changing "gn" to "gn.bat", changing "llvm-nm-9" to the name of your copy of
llvm-nm, etc.
"""

import fnmatch
import logging
import os
import re
import subprocess
import sys
import tempfile
import time

# Matches a mangled symbol that has 'absl' in it, this should be a good
# enough heuristic to select Abseil symbols to list in the .def file.
ABSL_SYM_RE = re.compile(r'0* [BT] (?P<symbol>(\?+)[^\?].*absl.*)')
if sys.platform == 'win32':
  # Typical dumpbin /symbol lines look like this:
  # 04B 0000000C SECT14 notype       Static       | ?$S1@?1??SetCurrent
  # ThreadIdentity@base_internal@absl@@YAXPAUThreadIdentity@12@P6AXPAX@Z@Z@4IA
  #  (unsigned int `void __cdecl absl::base_internal::SetCurrentThreadIdentity...
  # We need to start on "| ?" and end on the first " (" (stopping on space would
  # also work).
  # This regex is identical inside the () characters except for the ? after .*,
  # which is needed to prevent greedily grabbing the undecorated version of the
  # symbols.
  ABSL_SYM_RE = '.*External     \| (?P<symbol>(\?+)[^\?].*?absl.*?) \(.*'
  # Typical exported symbols in dumpbin /directives look like:
  #    /EXPORT:?kHexChar@numbers_internal@absl@@3QBDB,DATA
  ABSL_EXPORTED_RE = '.*/EXPORT:(.*),.*'


def _DebugOrRelease(is_debug):
  return 'dbg' if is_debug else 'rel'


def _GenerateDefFile(cpu, is_debug, extra_gn_args=[], suffix=None):
  """Generates a .def file for the absl component build on the specified CPU."""
  if extra_gn_args:
    assert suffix != None, 'suffix is needed when extra_gn_args is used'

  flavor = _DebugOrRelease(is_debug)
  gn_args = [
      'ffmpeg_branding = "Chrome"',
      'is_component_build = true',
      'is_debug = {}'.format(str(is_debug).lower()),
      'proprietary_codecs = true',
      'symbol_level = 0',
      'target_cpu = "{}"'.format(cpu),
      'target_os = "win"',
  ]
  gn_args.extend(extra_gn_args)

  gn = 'gn'
  autoninja = 'autoninja'
  symbol_dumper = ['llvm-nm-9']
  if sys.platform == 'win32':
    gn = 'gn.bat'
    autoninja = 'autoninja.bat'
    symbol_dumper = ['dumpbin', '/symbols']
    import shutil
    if not shutil.which('dumpbin'):
      logging.error('dumpbin not found. Run tools\win\setenv.bat.')
      exit(1)
  with tempfile.TemporaryDirectory() as out_dir:
    logging.info('[%s - %s] Creating tmp out dir in %s', cpu, flavor, out_dir)
    subprocess.check_call([gn, 'gen', out_dir, '--args=' + ' '.join(gn_args)],
                          cwd=os.getcwd())
    logging.info('[%s - %s] gn gen completed', cpu, flavor)
    subprocess.check_call(
        [autoninja, '-C', out_dir, 'third_party/abseil-cpp:absl_component_deps'],
        cwd=os.getcwd())
    logging.info('[%s - %s] autoninja completed', cpu, flavor)

    obj_files = []
    for root, _dirnames, filenames in os.walk(
        os.path.join(out_dir, 'obj', 'third_party', 'abseil-cpp')):
      matched_files = fnmatch.filter(filenames, '*.obj')
      obj_files.extend((os.path.join(root, f) for f in matched_files))

    logging.info('[%s - %s] Found %d object files.', cpu, flavor, len(obj_files))

    absl_symbols = set()
    dll_exports = set()
    if sys.platform == 'win32':
      for f in obj_files:
        # Track all of the functions exported with __declspec(dllexport) and
        # don't list them in the .def file - double-exports are not allowed. The
        # error is "lld-link: error: duplicate /export option".
        exports_out = subprocess.check_output(['dumpbin', '/directives', f], cwd=os.getcwd())
        for line in exports_out.splitlines():
          line = line.decode('utf-8')
          match = re.match(ABSL_EXPORTED_RE, line)
          if match:
            dll_exports.add(match.groups()[0])
    for f in obj_files:
      stdout = subprocess.check_output(symbol_dumper + [f], cwd=os.getcwd())
      for line in stdout.splitlines():
        try:
          line = line.decode('utf-8')
        except UnicodeDecodeError:
          # Due to a dumpbin bug there are sometimes invalid utf-8 characters in
          # the output. This only happens on an unimportant line so it can
          # safely and silently be skipped.
          # https://developercommunity.visualstudio.com/content/problem/1091330/dumpbin-symbols-produces-randomly-wrong-output-on.html
          continue
        match = re.match(ABSL_SYM_RE, line)
        if match:
          symbol = match.group('symbol')
          assert symbol.count(' ') == 0, ('Regex matched too much, probably got '
                                          'undecorated name as well')
          # Avoid getting names exported with dllexport, to avoid
          # "lld-link: error: duplicate /export option" on symbols such as:
          # ?kHexChar@numbers_internal@absl@@3QBDB
          if symbol in dll_exports:
            continue
          absl_symbols.add(symbol)

    logging.info('[%s - %s] Found %d absl symbols.', cpu, flavor, len(absl_symbols))

    if extra_gn_args:
      def_file = os.path.join('third_party', 'abseil-cpp',
                              'symbols_{}_{}_{}.def'.format(cpu, flavor, suffix))
    else:
      def_file = os.path.join('third_party', 'abseil-cpp',
                             'symbols_{}_{}.def'.format(cpu, flavor))

    with open(def_file, 'w', newline='') as f:
      f.write('EXPORTS\n')
      for s in sorted(absl_symbols):
        f.write('    {}\n'.format(s))

    # Hack, it looks like there is a race in the directory cleanup.
    time.sleep(10)

  logging.info('[%s - %s] .def file successfully generated.', cpu, flavor)


if __name__ == '__main__':
  logging.getLogger().setLevel(logging.INFO)

  if sys.version_info.major == 2:
    logging.error('This script requires Python 3.')
    exit(1)

  if not os.getcwd().endswith('src') or not os.path.exists('chrome/browser'):
    logging.error('Run this script from a chromium/src/ directory.')
    exit(1)

  _GenerateDefFile('x86', True)
  _GenerateDefFile('x86', False)
  _GenerateDefFile('x64', True)
  _GenerateDefFile('x64', False)
  _GenerateDefFile('x64', False, ['is_asan = true'], 'asan')
  _GenerateDefFile('arm64', True)
  _GenerateDefFile('arm64', False)
