2009-12-18 05:23:04 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# Copyright 2009 Google Inc. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Redistribution and use in source and binary forms, with or without
|
|
|
|
# modification, are permitted provided that the following conditions are
|
|
|
|
# met:
|
|
|
|
#
|
|
|
|
# * Redistributions of source code must retain the above copyright
|
|
|
|
# notice, this list of conditions and the following disclaimer.
|
|
|
|
# * Redistributions in binary form must reproduce the above
|
|
|
|
# copyright notice, this list of conditions and the following disclaimer
|
|
|
|
# in the documentation and/or other materials provided with the
|
|
|
|
# distribution.
|
|
|
|
# * Neither the name of Google Inc. nor the names of its
|
|
|
|
# contributors may be used to endorse or promote products derived from
|
|
|
|
# this software without specific prior written permission.
|
|
|
|
#
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
"""Generates the gtest.def file to build Google Test as a DLL on Windows.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
Put diagnostic messages from building gtest_dll_test_.exe into
|
|
|
|
BUILD_RESULTS_FILE and invoke
|
|
|
|
|
|
|
|
generate_gtest_def.py <BUILD_RESULTS_FILE
|
|
|
|
|
|
|
|
Reads output of VC++ linker and re-generates the src/gtest.def file
|
|
|
|
required for building gtest as a DLL.
|
|
|
|
|
|
|
|
Use this script if you modify Google Test's source code and Visual
|
|
|
|
Studio linker starts complaining about unresolved external symbols.
|
|
|
|
You may have to repeate the build/re-generate cycle several times
|
|
|
|
because VC++ limits the number of unresolved external symbols it can
|
|
|
|
report at a time.
|
|
|
|
|
|
|
|
EXAMPLES
|
|
|
|
scons\scons.py | scripts\generate_gtest_def.py
|
|
|
|
|
|
|
|
This tool is experimental. Please report any problems to
|
|
|
|
googletestframework@googlegroups.com. You can read
|
|
|
|
http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for more
|
|
|
|
information.
|
|
|
|
"""
|
|
|
|
|
|
|
|
__author__ = 'vladl@google.com (Vlad Losev)'
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sets
|
|
|
|
import sys
|
|
|
|
|
|
|
|
# We assume that this file is in the scripts/ directory in the Google
|
|
|
|
# Test root directory.
|
2009-12-18 16:48:20 +00:00
|
|
|
GTEST_DEF_PATH = os.path.join(os.path.dirname(__file__), '../msvc/gtest.def')
|
2009-12-18 05:23:04 +00:00
|
|
|
|
|
|
|
# Locates the header of the EXPORTS section.
|
|
|
|
EXPORTS_SECTION_REGEX = re.compile(r'^EXPORTS\s*$', re.IGNORECASE)
|
|
|
|
|
|
|
|
# Determines if a line looks like an export definition in the EXPORTS
|
|
|
|
# section of a module definition file.
|
|
|
|
EXPORT_REGEX = re.compile(r'^\s+(\S+)')
|
|
|
|
|
|
|
|
# Determines if a given line contains an error message about unresolved
|
|
|
|
# linker symbol.
|
|
|
|
IS_UNRESOLVED_SYMBOL_REGEX = re.compile(r'\bunresolved external symbol\b')
|
|
|
|
|
|
|
|
# Fetches the symbol name from a line that contains an unresolved linker
|
|
|
|
# symbol message.
|
|
|
|
UNRESOLVED_SYMBOL_REGEX = re.compile(r'^.*?"[^"]+" \((\S+)\)')
|
|
|
|
|
|
|
|
|
|
|
|
def ReadDefExports(stream):
|
|
|
|
"""Reads contents of a def file and returns a list of exported symbols."""
|
|
|
|
|
|
|
|
is_export = False
|
|
|
|
exports = sets.Set()
|
|
|
|
for line in stream:
|
|
|
|
if EXPORTS_SECTION_REGEX.match(line):
|
|
|
|
is_export = True
|
|
|
|
elif EXPORT_REGEX.match(line):
|
|
|
|
if is_export:
|
|
|
|
exports.add(EXPORT_REGEX.match(line).group(1))
|
|
|
|
else:
|
|
|
|
is_export = False
|
|
|
|
|
|
|
|
return exports
|
|
|
|
|
|
|
|
|
|
|
|
def ReadUnresolvedExternals(stream):
|
|
|
|
"""Reads linker output and returns list of unresolved linker symbols."""
|
|
|
|
|
|
|
|
unresolved = sets.Set()
|
|
|
|
|
|
|
|
for line in stream:
|
|
|
|
if IS_UNRESOLVED_SYMBOL_REGEX.search(line):
|
|
|
|
unresolved.add(UNRESOLVED_SYMBOL_REGEX.match(line).group(1))
|
|
|
|
|
|
|
|
return unresolved
|
|
|
|
|
|
|
|
|
|
|
|
def AdjustExports(exports, unresolved):
|
|
|
|
"""Adjusts exports list based on the list of unresolved symbols."""
|
|
|
|
|
|
|
|
if unresolved & exports:
|
|
|
|
# There are symbols that are listed as exported but are also reported
|
|
|
|
# unresolved. This is most likely because they have been removed from
|
|
|
|
# Google Test but their mentions in gtest.def constitute references. We
|
|
|
|
# need to remove such symbols from the EXPORTS section. Also, their
|
|
|
|
# presence means that the Google Test DLL has failed to link and
|
|
|
|
# consequently linking of the test .exe was not attempted, meaning that
|
|
|
|
# at this time, there will be no unresolved externals that need to be
|
|
|
|
# added to the exports list.
|
|
|
|
exports -= unresolved
|
|
|
|
else:
|
|
|
|
# Finding unresolved exports means that the Google Test DLL had link
|
|
|
|
# errors and the build script did not build gtest_dll_test_.exe. The user
|
|
|
|
# has to build the test once again and run this script on the diagnostic
|
|
|
|
# output of the build.
|
|
|
|
exports |= unresolved
|
|
|
|
|
|
|
|
return exports
|
|
|
|
|
|
|
|
|
|
|
|
def WriteGtestDefFile(stream, exports):
|
|
|
|
"""Writes contents of gtest.def given a list of exported symbols."""
|
|
|
|
|
|
|
|
stream.write('; This file is auto-generated. DO NOT EDIT DIRECTLY.\n'
|
|
|
|
'; For more information, see scripts/generate_gtest_def.py.\n'
|
|
|
|
'\nLIBRARY\n'
|
|
|
|
'\nEXPORTS\n')
|
|
|
|
for symbol in sorted(exports):
|
|
|
|
stream.write(' %s\n' % symbol)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
unresolved = ReadUnresolvedExternals(sys.stdin)
|
|
|
|
if unresolved:
|
|
|
|
try:
|
|
|
|
gtest_def = open(GTEST_DEF_PATH, 'r')
|
|
|
|
exports = ReadDefExports(gtest_def)
|
|
|
|
gtest_def.close()
|
|
|
|
except IOError:
|
|
|
|
exports = sets.Set()
|
|
|
|
|
|
|
|
exports = AdjustExports(exports, unresolved)
|
|
|
|
WriteGtestDefFile(open(GTEST_DEF_PATH, 'w'), exports)
|
2009-12-18 16:48:20 +00:00
|
|
|
sys.stderr.write('Updated gtest.def. Please clean the .dll file\n'
|
2009-12-18 05:23:04 +00:00
|
|
|
'produced by your Google Test DLL build, run the build\n'
|
|
|
|
'again and pass its diagnostic output to this script\n'
|
|
|
|
'unless the build succeeds.\n')
|
|
|
|
else:
|
|
|
|
sys.stderr.write('The build diagnostic output indicates no unresolved\n'
|
2009-12-18 16:48:20 +00:00
|
|
|
'externals. gtest.def is likely up to date and\n'
|
2009-12-18 05:23:04 +00:00
|
|
|
'has not been updated.\n')
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|