From cd1bdf28a0a9c6ea99718291f6d04d71b7bf1318 Mon Sep 17 00:00:00 2001 From: bdbaddog Date: Thu, 25 Sep 2008 19:44:49 +0000 Subject: [PATCH] Fix for bugs 402 and 2082 - implement scanner for windows resource files. Basic unittest included git-svn-id: http://scons.tigris.org/svn/scons/trunk@3475 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Scanner/RC.py | 49 +++++++++ src/engine/SCons/Scanner/RCTests.py | 156 ++++++++++++++++++++++++++++ src/engine/SCons/Tool/msvc.py | 11 +- 3 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 src/engine/SCons/Scanner/RC.py create mode 100644 src/engine/SCons/Scanner/RCTests.py diff --git a/src/engine/SCons/Scanner/RC.py b/src/engine/SCons/Scanner/RC.py new file mode 100644 index 00000000..d7c68702 --- /dev/null +++ b/src/engine/SCons/Scanner/RC.py @@ -0,0 +1,49 @@ +"""SCons.Scanner.RC + +This module implements the depenency scanner for RC (Interface +Definition Language) files. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Node.FS +import SCons.Scanner +import re + +def RCScan(): + """Return a prototype Scanner instance for scanning RC source files""" + + res_re= r'^(?:\s*#\s*(?:include)|' \ + '.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY)' \ + '\s*.*?)' \ + '\s*(<|"| )([^>" \Z\t]+)(?:[>" ])*$' + resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner", + "$RCSUFFIXES", + "CPPPATH", + res_re ) + + return resScanner diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py new file mode 100644 index 00000000..0101742a --- /dev/null +++ b/src/engine/SCons/Scanner/RCTests.py @@ -0,0 +1,156 @@ +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestCmd +import SCons.Scanner.RC +import unittest +import sys +import os +import os.path +import SCons.Node.FS +import SCons.Warnings +import UserDict + +test = TestCmd.TestCmd(workdir = '') + +os.chdir(test.workpath('')) + +# create some source files and headers: + +test.write('t1.rc',''' +#include "t1.h" +''') + +test.write('t2.rc',""" +#include "t1.h" +ICO_TEST ICON DISCARDABLE "abc.ico" +BMP_TEST BITMAP DISCARDABLE "def.bmp" +cursor1 CURSOR "bullseye.cur" +ID_RESPONSE_ERROR_PAGE HTML "responseerrorpage.htm" +5 FONT "cmroman.fnt" +1 MESSAGETABLE "MSG00409.bin" +1 MESSAGETABLE MSG00410.bin +1 TYPELIB "testtypelib.tlb" +TEST_REGIS REGISTRY MOVEABLE PURE "testregis.rgs" +""") + + +# Create dummy include files +headers = ['t1.h', + 'abc.ico','def.bmp','bullseye.cur','responseerrorpage.htm','cmroman.fnt', + 'MSG00409.bin','MSG00410.bin','testtypelib.tlb','testregis.rgs'] + +for h in headers: + test.write(h, " ") + + +# define some helpers: + +class DummyEnvironment(UserDict.UserDict): + def __init__(self,**kw): + UserDict.UserDict.__init__(self) + self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) + + def Dictionary(self, *args): + return self.data + + def subst(self, arg, target=None, source=None, conv=None): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst + + def subst_path(self, path, target=None, source=None, conv=None): + if type(path) != type([]): + path = [path] + return map(self.subst, path) + + def has_key(self, key): + return self.Dictionary().has_key(key) + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + +global my_normpath +my_normpath = os.path.normpath + +if os.path.normcase('foo') == os.path.normcase('FOO'): + my_normpath = os.path.normcase + +def deps_match(self, deps, headers): + scanned = map(my_normpath, map(str, deps)) + expect = map(my_normpath, headers) + self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + +# define some tests: + +class RCScannerTestCase1(unittest.TestCase): + def runTest(self): + env = DummyEnvironment(RCSUFFIXES=['.rc','.rc2'], + CPPPATH=sys.path) + s = SCons.Scanner.RC.RCScan() + path = s.path(env) + deps = s(env.File('t1.rc'), env, path) + headers = ['t1.h'] + deps_match(self, deps, headers) + +class RCScannerTestCase2(unittest.TestCase): + def runTest(self): + env = DummyEnvironment(RCSUFFIXES=['.rc','.rc2'], + CPPPATH=sys.path) + s = SCons.Scanner.RC.RCScan() + path = s.path(env) + deps = s(env.File('t2.rc'), env, path) + headers = ['MSG00410.bin', + 'abc.ico','bullseye.cur', + 'cmroman.fnt','def.bmp', + 'MSG00409.bin', + 'responseerrorpage.htm', + 't1.h', + 'testregis.rgs','testtypelib.tlb'] + deps_match(self, deps, headers) + + + +def suite(): + suite = unittest.TestSuite() + suite.addTest(RCScannerTestCase1()) + suite.addTest(RCScannerTestCase2()) + return suite + +if __name__ == "__main__": + runner = unittest.TextTestRunner() + result = runner.run(suite()) + if not result.wasSuccessful(): + sys.exit(1) diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 8828d7da..036501ba 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -660,13 +660,17 @@ pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR') pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch', emitter=pch_emitter, source_scanner=SCons.Tool.SourceFileScanner) -res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') + + +# Logic to build .rc files into .res files (resource files) +res_scanner = SCons.Scanner.RCScan() +res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') res_builder = SCons.Builder.Builder(action=res_action, src_suffix='.rc', suffix='.res', src_builder=[], - source_scanner=SCons.Tool.SourceFileScanner) -SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan) + source_scanner=res_scanner) + def generate(env): """Add Builders and construction variables for MSVC++ to an Environment.""" @@ -711,6 +715,7 @@ def generate(env): env['RC'] = 'rc' env['RCFLAGS'] = SCons.Util.CLVar('') + env['RCSUFFIXES']=['.rc','.rc2'] env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES' env['BUILDERS']['RES'] = res_builder env['OBJPREFIX'] = '' -- 2.26.2