diff options
author | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2009-12-18 05:23:04 +0000 |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2009-12-18 05:23:04 +0000 |
commit | a3dd9d97c57eb1be851a27ffcd6edaed69ee816e (patch) | |
tree | 1b0ba9ecfc2d495d6c293110c6331a77304e35e1 /scripts | |
parent | 88e97c822c988eaa9f8bcbaa1ea5d702ffd7d384 (diff) | |
download | googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.tar.gz googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.tar.bz2 googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.zip |
Supports building gtest as a DLL (by Vlad Losev).
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/generate_gtest_def.py | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/scripts/generate_gtest_def.py b/scripts/generate_gtest_def.py new file mode 100755 index 00000000..9de7038b --- /dev/null +++ b/scripts/generate_gtest_def.py @@ -0,0 +1,169 @@ +#!/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. +GTEST_DEF_PATH = os.path.join(os.path.dirname(__file__), '../src/gtest.def') + +# 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) + sys.stderr.write('Updated test/gtest.def. Please clean the .dll file\n' + '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' + 'externals. test/gtest.def is likely up to date and\n' + 'has not been updated.\n') + +if __name__ == '__main__': + main() |