summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2008-09-25 19:44:49 (GMT)
committerWilliam Deegan <bill@baddogconsulting.com>2008-09-25 19:44:49 (GMT)
commit6677088ccceb9f105b1c5ef76fca53f0b5bfa997 (patch)
tree7e12bfeb47e09308f32f8a244b9ef6a265bcb0fb
parentd87f5622846b645ba21d68b4c2c0186183387786 (diff)
downloadSCons-6677088ccceb9f105b1c5ef76fca53f0b5bfa997.zip
SCons-6677088ccceb9f105b1c5ef76fca53f0b5bfa997.tar.gz
SCons-6677088ccceb9f105b1c5ef76fca53f0b5bfa997.tar.bz2
Fix for bugs 402 and 2082 - implement scanner for windows resource files.
Basic unittest included
-rw-r--r--src/engine/SCons/Scanner/RC.py49
-rw-r--r--src/engine/SCons/Scanner/RCTests.py156
-rw-r--r--src/engine/SCons/Tool/msvc.py11
3 files changed, 213 insertions, 3 deletions
diff --git a/src/engine/SCons/Scanner/RC.py b/src/engine/SCons/Scanner/RC.py
new file mode 100644
index 0000000..d7c6870
--- /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 0000000..0101742
--- /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 8828d7d..036501b 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'] = ''