Commit 9d7e1bca authored by Bruce Dawson's avatar Bruce Dawson Committed by Commit Bot

Generate abseil def files on Windows

This ports the abseil .def file generation to Windows, using dumpbin to
get the lists of symbols. It also fixes some glitches such as the
Chromium-repo detection, and file-endings on export. It works around one
dumpbin bug that will be fixed in some future VS release.

The results are not identical to those on Linux but this is a solid step
in that direction.

Bug: 1046390
Change-Id: I37e7055b9b774e4d923e5572dd00268b0d563c53
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2264493Reviewed-by: default avatarDanil Chapovalov <danilchap@chromium.org>
Reviewed-by: default avatarMirko Bonadei <mbonadei@chromium.org>
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804437}
parent ace4c4c2
......@@ -25,12 +25,27 @@ 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):
......@@ -54,13 +69,20 @@ def _GenerateDefFile(cpu, is_debug, extra_gn_args=[], suffix=None):
]
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']
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)],
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'],
[autoninja, '-C', out_dir, 'third_party/abseil-cpp:absl_component_deps'],
cwd=os.getcwd())
logging.info('[%s - %s] autoninja completed', cpu, flavor)
......@@ -73,12 +95,40 @@ def _GenerateDefFile(cpu, is_debug, extra_gn_args=[], suffix=None):
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(['llvm-nm-9', f], cwd=os.getcwd())
stdout = subprocess.check_output(symbol_dumper + [f], cwd=os.getcwd())
for line in stdout.splitlines():
match = re.match(ABSL_SYM_RE, line.decode('utf-8'))
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:
absl_symbols.add(match.group('symbol'))
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))
......@@ -89,7 +139,7 @@ def _GenerateDefFile(cpu, is_debug, extra_gn_args=[], suffix=None):
def_file = os.path.join('third_party', 'abseil-cpp',
'symbols_{}_{}.def'.format(cpu, flavor))
with open(def_file, 'w') as f:
with open(def_file, 'w', newline='') as f:
f.write('EXPORTS\n')
for s in sorted(absl_symbols):
f.write(' {}\n'.format(s))
......@@ -103,8 +153,8 @@ def _GenerateDefFile(cpu, is_debug, extra_gn_args=[], suffix=None):
if __name__ == '__main__':
logging.getLogger().setLevel(logging.INFO)
if not os.getcwd().endswith('chromium/src'):
logging.error('Run this script from Chromium\'s src/ directory.')
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment