sbs version 2.15.2
authorJon Chatten
Mon, 13 Sep 2010 14:04:04 +0100
changeset 641 8dd670a9f34f
parent 640 ac0bbc1e5d79
child 643 27cf35f95864
child 647 53d1ab72f5bc
sbs version 2.15.2
sbsv2/raptor/RELEASE-NOTES.html
sbsv2/raptor/bin/annofile.py
sbsv2/raptor/bin/createvmap.py
sbsv2/raptor/bin/install_raptor.sh
sbsv2/raptor/bin/sbs_index.py
sbsv2/raptor/examples/os_properties.xml
sbsv2/raptor/lib/config/arm.xml
sbsv2/raptor/lib/config/empty.hrh
sbsv2/raptor/lib/config/gcc.xml
sbsv2/raptor/lib/config/gccxml.xml
sbsv2/raptor/lib/config/locations.xml
sbsv2/raptor/lib/config/logfile_regex.csv
sbsv2/raptor/lib/config/root.xml
sbsv2/raptor/lib/config/variants.xml
sbsv2/raptor/lib/config/winscw.xml
sbsv2/raptor/lib/config/x86.xml
sbsv2/raptor/lib/flm/e32abiv2.flm
sbsv2/raptor/lib/flm/run.mk
sbsv2/raptor/lib/flm/stringtable.flm
sbsv2/raptor/lib/flm/tools2exe.flm
sbsv2/raptor/notes/filter_html.txt
sbsv2/raptor/notes/tools_env_vars.txt
sbsv2/raptor/notes/variant_cfg.txt
sbsv2/raptor/python/plugins/filter_html.py
sbsv2/raptor/python/raptor_cli.py
sbsv2/raptor/python/raptor_meta.py
sbsv2/raptor/python/raptor_utilities.py
sbsv2/raptor/python/raptor_version.py
sbsv2/raptor/style/filter_html.css
sbsv2/raptor/test/common/raptor_tests.py
sbsv2/raptor/test/smoke_suite/capability_arm.py
sbsv2/raptor/test/smoke_suite/export.py
sbsv2/raptor/test/smoke_suite/featurevariants.py
sbsv2/raptor/test/smoke_suite/romfile.py
sbsv2/raptor/test/smoke_suite/stringtable_zip_whatlog.py
sbsv2/raptor/test/smoke_suite/test_resources/bv/variant1/CreateStaticDLL_variant1.mmp
sbsv2/raptor/test/smoke_suite/test_resources/simple_export/read_only.h
sbsv2/raptor/test/smoke_suite/test_resources/simple_zip_export/archive.zip
sbsv2/raptor/test/smoke_suite/test_resources/tools2/bootstrap.inf
sbsv2/raptor/test/smoke_suite/tools2.py
sbsv2/raptor/test/smoke_suite/zip_export_plus_clean.py
sbsv2/raptor/test/smoke_suite/zip_export_what.py
sbsv2/raptor/test/unit_suite/data/html_filter/config/logfile_regex.csv
sbsv2/raptor/test/unit_suite/data/html_filter/style/filter_html.css
sbsv2/raptor/test/unit_suite/filter_html_unit.py
sbsv2/raptor/test/unit_suite/raptor_unit.py
sbsv2/raptor/test/unit_suite/raptor_xml_unit.py
sbsv2/raptor/util/python.mk
--- a/sbsv2/raptor/RELEASE-NOTES.html	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/RELEASE-NOTES.html	Mon Sep 13 14:04:04 2010 +0100
@@ -6,6 +6,22 @@
 
 <h1>Release Notes for Symbian Build System v2</h1>
 
+<h2>version 2.15.2</h2>
+
+<h3>Engineering Changes</h3>
+<ul>
+<li><a href="notes/variant_cfg.txt">Allow .hrh files to be defined in XML instead of variant.cfg</a></li>
+<li><a href="notes/tools_env_vars.txt">Environment variables for tools</a></li>
+</ul>
+
+<h3>Defect Fixes</h3>
+<ul>
+<li><a href="notes/filter_html.txt">Report no-rule-to-make errors correctly in the HTML log filter</a></li>
+<li><a href="http://developer.symbian.org/bugs/show_bug.cgi?id=2412">SF Bug 2412</a> - createvmap fails when the list of source files becomes too long</li>
+<li><a href="http://developer.symbian.org/bugs/show_bug.cgi?id=2437">SF Bug 2437</a> - End-user installation script does not fully describe or report missing build dependencies (libbz2-dev, etc. needed)</li>
+<li><a href="http://developer.symbian.org/bugs/show_bug.cgi?id=3647">SF Bug 3647</a> - Raptor retains read-only attribute when exporting files</li>
+</ul>
+
 <h2>version 2.15.1</h2>
 
 <h3>Defect Fixes</h3>
--- a/sbsv2/raptor/bin/annofile.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/bin/annofile.py	Mon Sep 13 14:04:04 2010 +0100
@@ -24,6 +24,7 @@
 	def __init__(self, name, maxagents=30):
 		self.name = name
 		self.overallAggregateTime = 0
+		self.duration = 0
 		self.inJob = False
 		self.inMetricDuration = False
 		self.jobType = ''
--- a/sbsv2/raptor/bin/createvmap.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/bin/createvmap.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -24,6 +24,11 @@
 import traceback
 from optparse import OptionParser
 
+# Need to find the raptor utilities.
+sys.path.append(os.path.join(os.environ['SBS_HOME'],"python"))
+from raptor_utilities import expand_command_options
+
+
 # the script will exit with 0 if there are no errors
 global exitCode
 exitCode = 0
@@ -184,7 +189,18 @@
 		parser.add_option("-u","--userinc",action="append",dest="user_include",help="User Include Folders")
 		parser.add_option("-x","--systeminc",action="append",dest="system_include",help="System Include Folders")
 
-		(options, leftover_args) = parser.parse_args(sys.argv[1:])
+
+		# The following allows the use of the --command option.
+		# The add_option() is redundant since --command  is
+		# expanded well before it can take effect but it does
+		# allow us to print out a useful help message.
+		parser.add_option("--command",action="store",
+			dest="preinclude",
+			help="""Specify a command file with more commandline options 
+				in it (for very large components)""")
+		expanded_args = expand_command_options(sys.argv[1:])
+
+		(options, leftover_args) = parser.parse_args(expanded_args)
 
 		if leftover_args:
 			for invalids in leftover_args:
--- a/sbsv2/raptor/bin/install_raptor.sh	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/bin/install_raptor.sh	Mon Sep 13 14:04:04 2010 +0100
@@ -50,6 +50,12 @@
    echo "You DON'T appear to have the ncurses dev libraries - please install them (ncurses-dev or ncurses-devel)"
 fi
 
+if [ -f "/usr/include/bzlib.h" ]; then
+   echo "You appear to have the bzip2 dev libraries"
+else
+   echo "You DON'T appear to have the bzip2 dev libraries - please install them (bzip2-dev or bzip2-devel)"
+fi
+
 echo "Do you wish to continue (Y or y for 'yes' anything else for no)?"
 
 read X
--- a/sbsv2/raptor/bin/sbs_index.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/bin/sbs_index.py	Mon Sep 13 14:04:04 2010 +0100
@@ -6,20 +6,16 @@
 # under the terms of the License "Symbian Foundation License v1.0"
 # which accompanies this distribution, and is available
 # at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description:
-#
-# Tie together a set of HTML build summaries by creating a single index page
-# which shows the total number of Errors, Warnings etc. across all the parts
-# of the build and links to the individual summaries.
+
+'''
+Tie together a set of HTML build summaries by creating a single index page
+which shows the total number of Errors, Warnings etc. across all the parts
+of the build and links to the individual summaries.
+'''
 
 import os
 import sys
+import time
 
 # get the absolute path to this script
 script = os.path.abspath(sys.argv[0])
@@ -104,8 +100,13 @@
 		for row in reader:
 			type = int(row[0])
 			style = row[1]
-			count = int(row[2])
-			if count == 0 or filter_html.Records.SUBDIRS[type] == style:
+			
+			if style == 'time':
+				count = float(row[2])
+			else:
+				count = int(row[2])
+				
+			if count == 0 or filter_html.Records.CLASSES[type] == style:
 				grandtotal[type] += count
 				columns.append((style,count))
 			else:
@@ -119,7 +120,11 @@
 			linkname = os.path.relpath(os.path.join(linktext, "index.html"), indexdir)
 			index.write('<tr><td class="name"><a href="%s">%s</a></td>' % (linkname, linktext))
 			for (style, count) in columns:
-				index.write('<td class="%s">%d</td>' % (style, count))
+				if style == 'time':
+					n = time.strftime("%H:%M:%S", time.gmtime(count + 0.5))
+				else:
+					n = str(count)
+				index.write('<td class="%s">%s</td>' % (style, n))
 			index.write("</tr>")
 		except:
 			sys.stderr.write("error: cannot write index file %s\n" % indexfile)
@@ -129,10 +134,16 @@
 try:
 	index.write('<tr><td>&nbsp;</td></tr><tr><td class="name">total</td>')
 	for i, count in enumerate(grandtotal):
+		style = filter_html.Records.CLASSES[i]
+		if style == 'time':
+			n = time.strftime("%H:%M:%S", time.gmtime(count + 0.5))
+		else:
+			n = str(count)
+					
 		if count == 0:
 			index.write('<td class="zero">0</td>')
 		else:
-			index.write('<td class="%s">%d</td>' % (filter_html.Records.SUBDIRS[i], count))
+			index.write('<td class="%s">%s</td>' % (style, n))
 	index.write("</tr></table>")
 	index.write("</body></html>\n")
 	index.close()
--- a/sbsv2/raptor/examples/os_properties.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/examples/os_properties.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -11,14 +11,13 @@
 	The file can have any name as long as it ends with ".xml"
 	
 	-->
-	
-	<!-- changes required for v9.4, TB91, and TB91sf -->
 		 
 	<var name="root.changes">
 		<set name='POSTLINKER_SUPPORTS_WDP' value=''/>
 		<set name='SUPPORTS_STDCPP_NEWLIB' value=''/>
 		<set name='RVCT_PRE_INCLUDE' value='$(EPOCINCLUDE)/rvct2_2/rvct2_2.h'/>
 		<set name="SUPPORTS_ABIV1_IMPLIBS" value='1'/>
+		<set name='VARIANT_HRH' value='$(EPOCINCLUDE)/feature_settings.hrh'/>
 	</var>
 	
 </build>
--- a/sbsv2/raptor/lib/config/arm.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/arm.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -7,17 +7,23 @@
 		
 		<!-- tools and scripts -->
 		<env name="BMCONV" default="$(EPOCROOT)/epoc32/tools/bmconv$(DOTEXE)" type="tool"/>
-		<env name="CHECKLIB" default="$(EPOCROOT)/epoc32/tools/checklib$(DOTEXE)" type="tool"/>
+		<env name="SBS_CHECKLIB" default="$(EPOCTOOLS)/checklib$(DOTEXE)" type="tool"/>
+		<set name="CHECKLIB" value="$(SBS_CHECKLIB)"/>
 		<env name="CPPFILT" default="$(GCCPREFIX)c++filt$(DOTEXE)" type="tool"/>
-		<env name="EFREEZE" default="$(PERL) $(EPOCROOT)/epoc32/tools/efreeze.pl" type="script"/>
-		<env name="ELF2E32" default="$(EPOCROOT)/epoc32/tools/elf2e32$(DOTEXE)" type="tool"/>
-		<env name="PREPDEF" default="$(PERL) $(EPOCROOT)/epoc32/tools/prepdef.pl" type="script"/>
-		<env name="RCOMP" default="$(EPOCROOT)/epoc32/tools/rcomp$(DOTEXE)" type="tool"/>
+		<env name="SBS_EFREEZE" default="$(PERL) $(EPOCTOOLS)/efreeze.pl" type="script"/>
+		<set name="EFREEZE" value="$(SBS_EFREEZE)"/>
+		<env name="SBS_ELF2E32" default="$(EPOCTOOLS)/elf2e32$(DOTEXE)" type="tool"/>
+		<set name="ELF2E32" value="$(SBS_ELF2E32)"/>
+		<env name="SBS_PREPDEF" default="$(PERL) $(EPOCTOOLS)/prepdef.pl" type="script"/>
+		<set name="PREPDEF" value="$(SBS_PREPDEF)"/>
+		<env name="SBS_RCOMP" default="$(EPOCTOOLS)/rcomp$(DOTEXE)" type="tool"/>
+		<set name="RCOMP" value="$(SBS_RCOMP)"/>
 		<!-- RANSLEEP is a program that can be used to cause a random delay in milliseconds. This is only useful in parallel builds. See the PERTURBSTARTTIME switch for more details.  -->
 		<env name="RANSLEEP" default="$(SBS_HOME)/bin/$(HOSTPLATFORM_DIR)/ransleep$(DOTEXE)" type="tool"/>
 		<env name="SBSV1MAKE" default="$(EPOCROOT)/epoc32/tools/make$(DOTEXE)" type="tool"/>
 		<env name="STRINGTABLE" default="$(PERL) $(EPOCROOT)/epoc32/tools/stringtable.pl" type="script"/>
-		<env name="TRANASM" default="$(PERL) $(EPOCROOT)/epoc32/tools/tranasm.pl" type="script"/>
+		<env name="SBS_TRANASM" default="$(PERL) $(EPOCTOOLS)/tranasm.pl" type="script"/>
+		<set name="TRANASM" value="$(SBS_TRANASM)"/>
 
 		<set name="BASE_ARCH" value="arm"/>		
 		<set name="POSTLINKER" value="$(ELF2E32)"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/lib/config/empty.hrh	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,9 @@
+/*
+
+There is a general assumption that there is always a pre-include file
+in every build. So for the cases where there is no .hrh file in the
+epoc32 tree, yet, you can use this file.
+
+The "nohrh" variant points VARIANT_HRH at this file.
+
+*/
--- a/sbsv2/raptor/lib/config/gcc.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/gcc.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -94,7 +94,7 @@
 	<alias name="tools2_deb" meaning="tools2_base.t_deb"/>
 	
 	<var name="t_rel">
-		<set name='TOOLSPATH' value='$(EPOCTOOLS)'/> <!-- install -->
+		<set name='TOOLSPATH' value='$(EPOCROOT)/epoc32/tools'/> <!-- install -->
 		<set name='VARIANTTYPE' value='rel'/>
 
 		<append name='CFLAGS' value='-s'/>
--- a/sbsv2/raptor/lib/config/gccxml.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/gccxml.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -11,9 +11,12 @@
 		<env name='CPP' default='$(GNUCPP)' type='tool'/>
 		<env name='CREATERFIFILE' default='$(PERL) $(SBS_HOME)/bin/createrfifile.pl ' type='script'/>
 		<env name='GNUAWK' default='$(GNUPREFIX)gawk$(DOTEXE)' type='tool' versionCommand='$(GNUAWK) --version' versionResult='GNU Awk [3-9].*'/>
-		<env name='MAKEDEF' default='$(PERL) $(EPOCROOT)/epoc32/tools/makedef.pl' type='script'/>
-		<env name='PREPDEF' default='$(PERL) $(EPOCROOT)/epoc32/tools/prepdef.pl' type='script'/>
-		<env name='RCOMP' default='$(EPOCROOT)/epoc32/tools/rcomp$(DOTEXE)' type='tool'/>
+		<env name='SBS_MAKEDEF' default='$(PERL) $(EPOCTOOLS)/makedef.pl' type='script'/>
+		<set name='MAKEDEF' value='$(SBS_MAKEDEF)'/>
+		<env name='SBS_PREPDEF' default='$(PERL) $(EPOCTOOLS)/prepdef.pl' type='script'/>
+		<set name='PREPDEF' value='$(SBS_PREPDEF)'/>
+		<env name='SBS_RCOMP' default='$(EPOCTOOLS)/rcomp$(DOTEXE)' type='tool'/>
+		<set name='RCOMP' value='$(SBS_RCOMP)'/>
 		<env name='STRINGTABLE' default='$(PERL) $(EPOCROOT)/epoc32/tools/stringtable.pl' type='script'/>
 
 		<!-- link to bld.inf and mmp platform names -->
--- a/sbsv2/raptor/lib/config/locations.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/locations.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -7,29 +7,32 @@
 	-->
 
 	<var name="hostplatform.locations" host='linux.*'>	
+		<env name='SBS_SLASHBIN' default='/bin'/>
+		<env name='SBS_USRBIN' default='/usr/bin'/>
+				
 		<set name='DOTEXE' value=''/>
-		<set name='GCCPREFIX' value='/usr/bin/'/>
-		<set name='GNUPREFIX' value='/bin/'/>
+		<set name='GCCPREFIX' value='$(SBS_USRBIN)/'/>
+		<set name='GNUPREFIX' value='$(SBS_SLASHBIN)/'/>
 		
 		<env name='HOSTPLATFORM_DIR' default='linux-i386' />
 		<env name='HOSTPLATFORM' default='linux i386'/>
 		
-		<env name='SBS_GNUCPP' default='/usr/bin/cpp' type='tool'/>
-		<env name='SBS_GNUDATE' default='/bin/date' type='tool'/>
+		<env name='SBS_GNUCPP' default='$(SBS_USRBIN)/cpp' type='tool'/>
+		<env name='SBS_GNUDATE' default='$(SBS_SLASHBIN)/date' type='tool'/>
 		<env name='SBS_GNUMAKE38' default='$(SBS_HOME)/$(HOSTPLATFORM_DIR)/bin/make' type='tool'/>
-		<env name='SBS_GNUSED' default='/bin/sed' type='tool'/>
-		<env name='SBS_GNUMKDIR' default='/bin/mkdir' type='tool'/>
-		<env name='SBS_GNUMV' default='/bin/mv' type='tool'/>
-		<env name='SBS_GNUCP' default='/bin/cp' type='tool'/>
-		<env name='SBS_GNUCAT' default='/bin/cat' type='tool'/>
-		<env name='SBS_GNURM' default='/bin/rm' type='tool'/>
-		<env name='SBS_GNULN' default='/bin/ln' type='tool'/>
-		<env name='SBS_GNURMDIR' default='/bin/rmdir' type='tool'/>
-		<env name='SBS_GNUCHMOD' default='/bin/chmod' type='tool'/>
-		<env name='SBS_GNUMD5SUM' default='/usr/bin/md5sum' type='tool'/>
-		<env name='SBS_GNUTOUCH' default='/bin/touch' type='tool'/>
-		<env name='SBS_GNUFIND' default='/usr/bin/find' type='tool'/>
-		<env name='SBS_GNUGREP' default='/bin/grep' type='tool'/>
+		<env name='SBS_GNUSED' default='$(SBS_SLASHBIN)/sed' type='tool'/>
+		<env name='SBS_GNUMKDIR' default='$(SBS_SLASHBIN)/mkdir' type='tool'/>
+		<env name='SBS_GNUMV' default='$(SBS_SLASHBIN)/mv' type='tool'/>
+		<env name='SBS_GNUCP' default='$(SBS_SLASHBIN)/cp' type='tool'/>
+		<env name='SBS_GNUCAT' default='$(SBS_SLASHBIN)/cat' type='tool'/>
+		<env name='SBS_GNURM' default='$(SBS_SLASHBIN)/rm' type='tool'/>
+		<env name='SBS_GNULN' default='$(SBS_SLASHBIN)/ln' type='tool'/>
+		<env name='SBS_GNURMDIR' default='$(SBS_SLASHBIN)/rmdir' type='tool'/>
+		<env name='SBS_GNUCHMOD' default='$(SBS_SLASHBIN)/chmod' type='tool'/>
+		<env name='SBS_GNUMD5SUM' default='$(SBS_USRBIN)/md5sum' type='tool'/>
+		<env name='SBS_GNUTOUCH' default='$(SBS_SLASHBIN)/touch' type='tool'/>
+		<env name='SBS_GNUFIND' default='$(SBS_USRBIN)/find' type='tool'/>
+		<env name='SBS_GNUGREP' default='$(SBS_SLASHBIN)/grep' type='tool'/>
 		<env name='SBS_GNUSORT' default='sort' type='tool'/>
 		<env name='SBS_SHELL' default="$(SBS_HOME)/$(HOSTPLATFORM_DIR)/bin/sh" type='tool'/>
 		<env name='SBS_ZIP' default="$(SBS_HOME)/$(HOSTPLATFORM_DIR)/bin/zip" type='tool'/>
--- a/sbsv2/raptor/lib/config/logfile_regex.csv	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/logfile_regex.csv	Mon Sep 13 14:04:04 2010 +0100
@@ -1,37 +1,65 @@
-priority,regex,modifiers
-ERROR,error\s*:,ignorecase
-ERROR,ERROR\t,
-ERROR,cannot create regular file,
-ERROR,Missing file:,
-ERROR,is not recognized as an internal or external command,
-ERROR,MISSING:,
-ERROR,fatal error,
-ERROR,warning U4010,
-ERROR,Internal fault,
-ERROR,target .* given more than once in the same rule,
-ERROR,[Nn]o such file or directory,
-ERROR,Exception: [A-Z0-9_]+,
-ERROR,ERROR EC\d+:,
-ERROR,Errors caused tool to abort,
-ERROR,Traceback \(most recent call last\),
-ERROR,Application encountered an unexpected error,
-ERROR,Unable to write dump file,
-ERROR,Unable to connect to CM:,
-ERROR,: Incorrect,
-ERROR,The system cannot find the path specified,
-ERROR,[Ww]arning:?\s+(#111-D|#1166-D|#117-D|#128-D|#1293-D|#1441-D|#170-D|#174-D|#175-D|#185-D|#186-D|#223-D|#231-D|#257-D|#284-D|#368-D|#414-D|#430-D|#47-D|#514-D|#546-D|#68-D|#69-D|#830-D|#940-D|#836-D|A1495E|L6318W|C2874W|C4127|C4355|C4530|C4702|C4786|LNK4049),
-REMARK,No feature macros were found in the source,
-REMARK,is shorter than expected,
-REMARK,Command line warning D4025 :,
-REMARK,REMARK:,
-REMARK,EventType:\s+Error\s+Source:\s+GNU\s+Make,
-REMARK,: note:,
-WARNING,\(\d+\) : warning C,
-WARNING,mwld.exe:,
-WARNING,Command line warning,
-WARNING,ERROR: bad relocation:,
-WARNING,\d+ warning,
-WARNING,EventType:\s+Error\s+Source:\s+SweepNT,
-WARNING,WARN\t,
-WARNING,LINK : warning,
-WARNING,warning\s*:,ignorecase
+priority,regex,description
+CRITICAL,.*Error:.*mingw_make\.exe.*,
+ERROR,.*\: cannot create regular file.*,
+ERROR,.*\): Missing file:.*,
+ERROR,(?:(?:\s*\d+\)\s*)|(?:\s*\*\*\*\s*))ERROR:.*,
+ERROR,.*is not recognized as an internal or external command.*,
+ERROR,MISSING:.*,
+ERROR,.*FLEXlm error:.*,
+ERROR,.*(ABLD|BLDMAKE)\s*ERROR:.*,
+ERROR,.*FATAL ERROR\(S\):.*,
+ERROR,.*fatal error C1001: INTERNAL COMPILER ERROR.*,
+ERROR,.*fatal error U1077.*,
+ERROR,^fatal error.*,
+ERROR,.*warning U4010.*,
+ERROR,make(?:\.exe)?\s*(?:\[\d+\])\s*?\:\s*\*\*\*.*,
+ERROR,make(?:\.exe)(?:\[\d+\])?\:.*\s+not\s+remade.*,
+ERROR,make(?:\.exe)\s*:\s*\*\*\*.*\s*[Nn]o rule.*,
+ERROR,"\""(?:.*)\"" , line (\d+): (Error: +(.\d+.*?):.*)",
+ERROR,error: ((Internal fault):.*)$,
+ERROR,.*Exception: STATUS_ACCESS_VIOLATION.*,
+ERROR,.*target .* given more than once in the same rule.*,
+ERROR,ERROR:.*,
+ERROR,Error:.*,
+ERROR,ERROR\t.*,
+ERROR,^.*\s*elf2e32\s*:\s*Error\s*:\s*,
+ERROR,.*[Nn]o such file or directory\s*.*,
+ERROR,Exception: [A-Z0-9_]+.*,
+ERROR,.*target .* given more than once in the same rule.*,
+ERROR,ERROR EC\d+:.*,
+ERROR,Errors caused tool to abort..*,
+ERROR,ERROR\t.*,
+ERROR,.*Traceback \(most recent call last\).*,
+ERROR,Application encountered an unexpected error\.\s*Stopping\.\s*,
+ERROR,Unable to write dump file .+,
+ERROR,Unable to connect to CM: .*,
+ERROR,.*: Incorrect slash in .*,
+ERROR,.*: Incorrect case for epoc32 tree in .*,
+ERROR,.*: Incorrect case versus exclusion list in .*,
+ERROR,The system cannot find the path specified.*,
+CRITICAL,.*[Ww]arning:?\s+(#111-D|#1166-D|#117-D|#128-D|#1293-D|#1441-D|#170-D|#174-D|#175-D|#185-D|#186-D|#223-D|#231-D|#257-D|#284-D|#368-D|#414-D|#430-D|#47-D|#514-D|#546-D|#68-D|#69-D|#830-D|#940-D|#836-D|A1495E|L6318W|C2874W|C4127|C4355|C4530|C4702|C4786|LNK4049).*,
+WARNING,(\d+\))?\s.*WARNING:.*,
+WARNING,(BLDMAKE |MAKEDEF )?WARNING:.*,
+WARNING,.*\(\d+\) : warning C.*,
+WARNING,.*\d+: warning:.*,
+WARNING,.*Usage Warning:.*,
+WARNING,.*mwld.exe:.*,
+WARNING,Command line warning.*,
+WARNING,.*ERROR: bad relocation:.*,
+WARNING,(\d+) warning.*,
+WARNING,.*EventType:\s+Error\s+Source:\s+SweepNT.*,
+WARNING,WARN\t.*,
+WARNING,.*LINK : warning.*,
+WARNING,.*\s*elf2e32\s*:\s*Warning\s*:\s*,
+WARNING,Warning:.*,
+REMARK,"\"".*\""\, line \d+: Warning: +(.\d+.*?):.*",
+REMARK,.*Command line warning D4025 : .*,
+REMARK,REMARK: .*,
+REMARK,EventType:\s+Error\s+Source:\s+GNU\s+Make.*,
+REMARK,".*:\d+: warning: cannot find matching deallocation function.*",
+REMARK,(:\d+)*: note: .*,
+INFO,INFO:.*,
+WARNING,"line \d+: Warning:'\, r':\s+warning\s+\w+:.*",
+WARNING,"\""(.*)\""\, line (\d+): (Warning: +(?!A1495E)(.\d+.*?):.*)",
+WARNING,Warning\s*:\s*.*,
+ERROR,.*Error\s*:\s*.*,
\ No newline at end of file
--- a/sbsv2/raptor/lib/config/root.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/root.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -23,17 +23,18 @@
 	<!-- Common folders and files -->
 	<var name="root.places">
 		<env name='EPOCROOT' default='/' type='path'/>
+		<env name='SBS_EPOCTOOLS' default='$(EPOCROOT)/epoc32/tools' type='path'/>
 		
 		<set name='EPOCINCLUDE' value='$(EPOCROOT)/epoc32/include'/>
-		<set name='EPOCTOOLS' value='$(EPOCROOT)/epoc32/tools'/>
+		<set name='EPOCTOOLS' value='$(SBS_EPOCTOOLS)'/>
 
 		<!-- Place where intermediate files are built -->
 		<env name='SBS_BUILD_DIR' default='$(EPOCROOT)/epoc32/build' type='path'/> 
 
 		<!-- Configuration files and directories -->
 		<set name='PRODUCT_INCLUDE' value='$(EPOCINCLUDE)/variant/symbian_os.hrh'/>
-		<set name='VARIANT_CFG' value='$(EPOCTOOLS)/variant/variant.cfg'/>
-		<set name='MAKEFILE_TEMPLATES' value='$(EPOCTOOLS)/makefile_templates'/>
+		<set name='VARIANT_CFG' value='$(EPOCROOT)/epoc32/tools/variant/variant.cfg'/>
+		<set name='MAKEFILE_TEMPLATES' value='$(EPOCROOT)/epoc32/tools/makefile_templates'/>
 		<set name='FLM_EXPORT_DIR' value='$(MAKEFILE_TEMPLATES)'/>
 	</var>
 	
--- a/sbsv2/raptor/lib/config/variants.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/variants.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -287,4 +287,8 @@
 		<set name="DEBUG_INFO" value=""/>
 	</var>
 
+	<!-- for builds which don't need a populated .hrh file -->
+	<var name="nohrh">
+		<set name="VARIANT_HRH" value="$(SBS_HOME)/lib/config/empty.hrh"/>
+	</var>
 </build>
--- a/sbsv2/raptor/lib/config/winscw.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/winscw.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -16,14 +16,20 @@
 		
 		<!-- tools and scripts -->
 		<env name="BMCONV" default="$(EPOCROOT)/epoc32/tools/bmconv$(DOTEXE)" type="tool"/>
-		<env name="CHECKLIB" default="$(EPOCROOT)/epoc32/tools/checklib$(DOTEXE)" type="tool"/>
-		<env name="EFREEZE" default="$(PERL) $(EPOCROOT)/epoc32/tools/efreeze.pl" type="script"/>
-		<env name="MAKEDEF" default="$(PERL) $(EPOCROOT)/epoc32/tools/makedef.pl" type="script"/>
-		<env name="PREPDEF" default="$(PERL) $(EPOCROOT)/epoc32/tools/prepdef.pl" type="script"/>
-		<env name="RCOMP" default="$(EPOCROOT)/epoc32/tools/rcomp$(DOTEXE)" type="tool"/>
+		<env name="SBS_CHECKLIB" default="$(EPOCTOOLS)/checklib$(DOTEXE)" type="tool"/>
+		<set name="CHECKLIB" value="$(SBS_CHECKLIB)"/>
+		<env name="SBS_EFREEZE" default="$(PERL) $(EPOCTOOLS)/efreeze.pl" type="script"/>
+		<set name="EFREEZE" value="$(SBS_EFREEZE)"/>
+		<env name='SBS_MAKEDEF' default='$(PERL) $(EPOCTOOLS)/makedef.pl' type='script'/>
+		<set name='MAKEDEF' value='$(SBS_MAKEDEF)'/>
+
+		<env name="SBS_PREPDEF" default="$(PERL) $(EPOCTOOLS)/prepdef.pl" type="script"/>
+		<set name="PREPDEF" value="$(SBS_PREPDEF)"/>
+		<env name="SBS_RCOMP" default="$(EPOCTOOLS)/rcomp$(DOTEXE)" type="tool"/>
+		<set name="RCOMP" value="$(SBS_RCOMP)"/>
 		<env name="SBSV1MAKE" default="$(EPOCROOT)/epoc32/tools/make$(DOTEXE)" type="tool"/>
 		<env name="STRINGTABLE" default="$(PERL) $(EPOCROOT)/epoc32/tools/stringtable.pl" type="script"/>	
-		
+	
 		<!-- link to bld.inf and mmp platform names -->
 		<set name="TRADITIONAL_PLATFORM" value="WINSCW"/>
 
@@ -121,7 +127,8 @@
 		<set name="STDCPP_INCLUDE" value="$(EPOCINCLUDE)/stdapis"/>
 		<set name="STDCPP_WCHAR_DEF" value="__wchar_t_defined"/>
 		<set name="SYMLOOKUPARGS" value="--ignore_export_dir"/>
-		<set name="SYMLOOKUPUTIL" value="$(PERL) $(EPOCROOT)/epoc32/tools/sym_lkup_util.pl"/>
+		<env name="SBS_SYMLOOKUPUTIL" default="$(PERL) $(EPOCTOOLS)/sym_lkup_util.pl" type="tool"/>
+		<set name="SYMLOOKUPUTIL" value="$(SBS_SYMLOOKUPUTIL)"/>
 		<set name="SYSTEMINCLUDE" value=""/>
 		<set name="TARGET" value="TARGET_WAS_NOT_SET_PROPERLY"/>
 		<set name="TARGETPATH" value=""/>
--- a/sbsv2/raptor/lib/config/x86.xml	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/config/x86.xml	Mon Sep 13 14:04:04 2010 +0100
@@ -7,21 +7,28 @@
 		
 		<!-- tools and scripts -->
 		<env name="BMCONV" default="$(EPOCROOT)/epoc32/tools/bmconv$(DOTEXE)" type="tool"/>
-		<env name="CHECKLIB" default="$(EPOCROOT)/epoc32/tools/checklib$(DOTEXE)" type="tool"/>
+		<env name="SBS_CHECKLIB" default="$(EPOCTOOLS)/checklib$(DOTEXE)" type="tool"/>
+		<set name="CHECKLIB" value="$(SBS_CHECKLIB)"/>
 		<env name="CPPFILT" default="$(GCCPREFIX)c++filt$(DOTEXE)" type="tool"/>
-		<env name="EFREEZE" default="$(PERL) $(EPOCROOT)/epoc32/tools/efreeze.pl" type="script"/>
+		<env name="SBS_EFREEZE" default="$(PERL) $(EPOCTOOLS)/efreeze.pl" type="script"/>
+		<set name="EFREEZE" value="$(SBS_EFREEZE)"/>
 		<env name="GENDEF" default="$(PERL) $(EPOCROOT)/epoc32/tools/gendef.pl" type="script"/>
-		<env name="PETRAN" default="$(EPOCROOT)/epoc32/tools/petran$(DOTEXE)" type="tool"/>
-		<env name="PREPDEF" default="$(PERL) $(EPOCROOT)/epoc32/tools/prepdef.pl" type="script"/>
-		<env name="RCOMP" default="$(EPOCROOT)/epoc32/tools/rcomp$(DOTEXE)" type="tool"/>
+		<env name="SBS_PETRAN" default="$(EPOCTOOLS)/petran$(DOTEXE)" type="tool"/>
+		<set name="PETRAN" value="$(SBS_PETRAN)"/>
+		<env name="SBS_PREPDEF" default="$(PERL) $(EPOCTOOLS)/prepdef.pl" type="script"/>
+		<set name="PREPDEF" value="$(SBS_PREPDEF)"/>
+
+		<env name="SBS_RCOMP" default="$(EPOCTOOLS)/rcomp$(DOTEXE)" type="tool"/>
+		<set name="RCOMP" value="$(SBS_RCOMP)"/>
 		<!-- RANSLEEP is a program that can be used to cause a random delay in milliseconds. This is only useful in parallel builds. See the PERTURBSTARTTIME switch for more details.  -->
 		<env name="RANSLEEP" default="$(SBS_HOME)/bin/$(HOSTPLATFORM_DIR)/ransleep$(DOTEXE)" type="tool"/>
 		<env name="SBSV1MAKE" default="$(EPOCROOT)/epoc32/tools/make$(DOTEXE)" type="tool"/>
 		<env name="STRINGTABLE" default="$(PERL) $(EPOCROOT)/epoc32/tools/stringtable.pl" type="script"/>
-		<env name="TRANASM" default="$(PERL) $(EPOCROOT)/epoc32/tools/tranasm.pl" type="script"/>
+		<env name="SBS_TRANASM" default="$(PERL) $(EPOCTOOLS)/tranasm.pl" type="script"/>
+		<set name="TRANASM" value="$(SBS_TRANASM)"/>
 		
 		<set name="BASE_ARCH" value="x86"/>
-		<set name="POSTLINKER" value="$(PETRAN)"/>
+		<set name="POSTLINKER" value="$(SBS_PETRAN)"/>
 		<set name="IMPLIBTOOL" value="$(DLLTOOL)"/>
 		<set name="DEFGENTOOL" value="$(GENDEF)"/>
 		
--- a/sbsv2/raptor/lib/flm/e32abiv2.flm	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/flm/e32abiv2.flm	Mon Sep 13 14:04:04 2010 +0100
@@ -1133,7 +1133,6 @@
 TARGET:: $(OUTPUTVMAP)
 VMAPNEEDS:=$(E32TARGET) $(SOURCE) $(PROJECT_META)
 
-BV_SOURCELIST:=$(addprefix -s ,$(SOURCE) $(PROJECT_META))
 BV_FEATURELIST:=$(addprefix -f ,$(FEATURELISTFILES))
 BV_USER_INCLUDES:=$(addprefix -u ,$(USERINCLUDE))
 BV_SYSTEM_INCLUDES:=$(addprefix -x ,$(SYSTEMINCLUDE))
@@ -1141,12 +1140,24 @@
 # translate double quoted macros because $(shell) messes them up in some make engines
 BV_MACROLIST:=$(COMPILER_INTERWORK_DEFINES) $(CDEFS) $(if $(ALWAYS_BUILD_AS_ARM),,$(COMPILER_THUMB_DEFINES))
 BV_DEFINES:=$(call makemacrodef,-D,$(subst ",__SBS__QUOTE__,$(BV_MACROLIST)))
+VMAPCOMMANDFILE:=$(INTERMEDIATEPATH)/$(TARGET).vmap.cmdfile
+
+CLEANTARGETS:=$(CLEANTARGETS) $(VMAPCOMMANDFILE)
 
 # the script to generate our .vmap file and hash value
-VMAPCOMMAND:=$(CREATEVMAP) -o $(OUTPUTVMAP) $(BV_FEATURELIST) $(BV_DEFINES) -p $(PREINCLUDE) $(BV_SOURCELIST) $(BV_USER_INCLUDES) $(BV_SYSTEM_INCLUDES) -c $(CREATEVMAPCPP)
+define createvmap
+
+$(OUTPUTVMAP): $(VMAPNEEDS)
+	@echo -n "" > $(VMAPCOMMANDFILE);
+	$(call groupin10infile,$(VMAPCOMMANDFILE),$(addprefix -s,$(SOURCE) $(PROJECT_META))) ;
+	$(call startrule,createvmap) \
+	$(CREATEVMAP) -o $(OUTPUTVMAP) $(BV_FEATURELIST) $(BV_DEFINES) -p $(PREINCLUDE) --command=$(VMAPCOMMANDFILE) $(BV_USER_INCLUDES) $(BV_SYSTEM_INCLUDES) -c $(CREATEVMAPCPP) \
+	$(call endrule,createvmap)
+
+endef
 
 # a recipe to create the .vmap from the "sources" with the createvmap script
-$(call raptor_recipe,createvmap,$(OUTPUTVMAP),$(VMAPNEEDS),$(VMAPCOMMAND))
+$(eval $(createvmap))
 
 endif # E32TARGET != ""
 endif # FEATUREVARIANTNAME != ""
--- a/sbsv2/raptor/lib/flm/run.mk	Mon Sep 13 13:11:19 2010 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-.PHONY:: ALL
-ALL:: # Default target
-
-HOSTPLATFORM:=win 32
-HOSTPLATFORM_DIR:=win32
-OSTYPE:=cygwin
-FLMHOME:=E:/wip2/lib/flm
-SHELL:=E:/wip2/win32/cygwin/bin/sh.exe
-
-
-USE_TALON:=
-
-
-
-include E:/wip2/lib/flm/globals.mk
-
-# dynamic default targets
-
-# call E:/wip2/lib/flm/config/default.flm
-SBS_SPECIFICATION:=Symbian.config.default
-SBS_CONFIGURATION:=armv5_urel
-
-EPOCROOT:=E:/wip2/test/epocroot
-ELF2E32:=E:/wip2/test/epocroot/epoc32/tools/elf2e32.exe
-WHATLOG:=
-include E:/wip2/lib/flm/config/default.flm
-
-
-component_paths:=$(SBS_HOME)/test/smoke_suite/test_resources/simple/bld.inf|c:/make_test/a.mk \
-$(SBS_HOME)/test/smoke_suite/test_resources/simple_dll/bld.inf|c:/make_test/b.mk \
-$(SBS_HOME)/test/smoke_suite/test_resources/simple/always_build_as_arm_bld.inf|c:/make_test/c.mk \
-$(SBS_HOME)/test/smoke_suite/test_resources/simple/debuggable_bld.inf|c:/make_test/d.mk \
-$(SBS_HOME)/test/smoke_suite/test_resources/simple_export/bld.inf|c:/make_test/e.mk
-
-configs:=armv5 armv7
-
-cli_options:=-d
-
-include build.flm
--- a/sbsv2/raptor/lib/flm/stringtable.flm	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/flm/stringtable.flm	Mon Sep 13 14:04:04 2010 +0100
@@ -66,7 +66,7 @@
 
 $(STRINGTABLEHEADER): $(SOURCE) 
 	$(call startrule,stringtable,FORCESUCCESS) \
-	$(GNUCP) --no-preserve=mode $(SOURCE) $(TEMPSOURCE)  && $(GNUCHMOD) a+w $(TEMPSOURCE) &&  \
+	$(GNUCP) --remove-destination --no-preserve=mode $(SOURCE) $(TEMPSOURCE)  && $(GNUCHMOD) a+w $(TEMPSOURCE) &&  \
 	$(STRINGTABLE) $(TEMPSOURCE)  \
 	$(call endrule,stringtable)
 
--- a/sbsv2/raptor/lib/flm/tools2exe.flm	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/lib/flm/tools2exe.flm	Mon Sep 13 14:04:04 2010 +0100
@@ -73,7 +73,7 @@
 define tools2install
 $(INSTALLED): $(EXETARGET)
 	$(call startrule,tools2install) \
-	$(GNUCP) "$(EXETARGET)" "$(INSTALLED)" && \
+	$(GNUCP) --remove-destination "$(EXETARGET)" "$(INSTALLED)" && \
 	$(GNUCHMOD) a+rwx "$(INSTALLED)" \
 	$(call endrule,tools2install)
 endef
--- a/sbsv2/raptor/notes/filter_html.txt	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/notes/filter_html.txt	Mon Sep 13 14:04:04 2010 +0100
@@ -1,15 +1,15 @@
 There is a new log filter to generate HTML output. For example,
 
-sbs --filters=html -f logdir
+sbs --filters=html -f name
 
-will produce an output file "logdir/index.html" and other supporting files
-in the directory "logdir". This can be used alongside the Bz2 filter to
+will produce an output file "name_html/index.html" and other supporting files
+in the directory "name_html". This can be used alongside the Bz2 filter to
 generate both a human readable summary and a compressed log for further
 detailed machine analysis if required: for example,
 
 sbs --filters=html,bz2log -f name
 
-will produce a folder "name" and a file "name.bz2".
+will produce a folder "name_html" and a file "name.bz2".
 
 
 If a build is done in several parts, for example,
@@ -21,7 +21,7 @@
 Then there is a new script "SBS_HOME/bin/sbs_index.py" which can produce a
 single index linking to all the individual parts: for example,
 
-sbs_index.py build/part1 build/part2 build/part3 build/index.html
+sbs_index.py build/part{1,2,3}_html build/index.html
 
 the first parameters are the directories to search for summaries and the
 last parameter is the name of the overall index file. Directories are
@@ -30,12 +30,32 @@
 sbs_index.py build build/index.html
 
 
-Text in the Raptor logs is classified as Error, Warning or Remark using the
-list of regular expressions in the file SBS_HOME/lib/config/logfile_regex.csv
+Text in the Raptor logs is classified as Error, Critical, Warning or Remark
+using the list of regular expressions in the file,
+
+SBS_HOME/lib/config/logfile_regex.csv
+
 but this can be overriden by placing a file of the same name in the kit in
 its EPOCROOT/epoc32/sbs_config folder.
 
 
 The filter also checks that all the files which were listed in "what" output
 actually exist at the end of the build. Any files which don't exist are
-recorded as "Missing files".
\ No newline at end of file
+recorded as "Missing files".
+
+
+Sometimes when a target cannot be built you will see errors like this in the
+HTML report,
+"
+/opt/nokia/wk99/epoc32/build/something
+
+required the following files which could not be found,
+
+/opt/nokia/wk99/epoc32/include/foo
+/opt/nokia/wk99/epoc32/include/bar
+"
+
+which means that a dependency was created on "foo" and "bar" but the build
+did not contain any information anywhere on how to build those files. This
+is often caused by someone just forgetting to add files to the asset.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/notes/tools_env_vars.txt	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,37 @@
+A requirement on Raptor is to allow all the tools to be configurable via 
+environment variables. To this end, updates have been made to extend the list 
+of tools that can be configured using environment variables.
+
+The list of new SBS_*** environment variables and their purpose is given below:
+
+SBS_EPOCTOOLS       Directory for epoc32 tools; defaults to $EPOCROOT/epoc32/tools
+                    Changes the default locations for all of the following tools.
+SBS_CHECKLIB        Full path to checklib program
+SBS_EFREEZE         perl, followed by full path to efreeze.pl
+SBS_ELF2E32         Full path to elf2e32 program
+SBS_PREPDEF         perl, followed by full path to prepdef.pl
+SBS_RCOMP           Full path to rcomp program
+SBS_TRANASM         perl, followed by full path to tranasm.pl
+SBS_MAKEDEF         perl, followed by full path to makedef.pl
+SBS_PETRAN          perl, followed by full path to petran.pl
+SBS_SYMLOOKUPUTIL   perl, followed by full path to sym_lkup_util.pl
+SBS_SLASHBIN        Linux only: location of /bin, i.e. an alternative location for
+                    GCC and associated tools
+SBS_USRBIN          Linux only: location of /usr/bin, i.e. an alternative location 
+                    for Gnu tools such as the Core Utils
+
+In the case Perl scripts (.pl files), "perl" can be replaced with the full path to 
+the perl program.
+
+The above variables supercede the following environment variables:
+
+CHECKLIB
+EFREEZE
+ELF2E32
+MAKEDEF
+PETRAN
+PREPDEF
+RCOMP
+TRANASM
+
+which are no longer in use.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/notes/variant_cfg.txt	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,25 @@
+The pre-included header file used in builds (.hrh) is normally defined
+inside a text file located at $(EPOCROOT)/epoc32/tools/variant/variant.cfg
+in each kit.
+
+This is an unnecessary extra file to maintain if you already define all the
+other kit properties in an XML file in the $(EPOCROOT)/epoc32/sbs_config
+folder.
+
+This change allows kit owners to define the .hrh file name in the XML instead
+of using an additional variant.cfg file.
+
+An example of this is shown in $(SBS_HOME)/examples/os_properties.xml
+where the VARIANT_HRH parameter is set as follows,
+
+<set name='VARIANT_HRH' value='$(EPOCINCLUDE)/feature_settings.hrh'/>
+
+
+In the unusual case where you want to build without a .hrh file at all (maybe
+to create an epoc32 tree from scratch) there is a variant "nohrh" which
+simply sets VARIANT_HRH as above to an empty file. Example usage would be,
+
+sbs -b bootstrap/bld.inf -c tools2.nohrh
+
+Note that, in general, actual code will not build properly without a .hrh
+file to configure it.
--- a/sbsv2/raptor/python/plugins/filter_html.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/python/plugins/filter_html.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,19 +1,14 @@
-#
+
 # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
 # which accompanies this distribution, and is available
 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description: 
-# Filter class for generating HTML summary pages
-#
+
+'''
+Filter class for generating HTML summary pages
+'''
 
 import os
 import re
@@ -21,6 +16,7 @@
 import sys
 import shutil
 import tempfile
+import time
 import filter_interface
 
 class HTML(filter_interface.FilterSAX):
@@ -49,6 +45,10 @@
 				self.regex = self.readregex(str(csv))
 				break
 		
+		# regexes for important "make" errors
+		self.noruletomake = re.compile("No rule to make target `(.+)', needed by `(.+)'")
+		
+		# all our lists are empty
 		self.elements = []
 		self.recipe_tag = None
 		self.error_tag = None
@@ -56,10 +56,15 @@
 		
 		self.components = {}
 		self.configurations = {}
+		self.missed_depends = {}
+		self.parse_start = {}
 		self.totals = Records()
+
+		self.progress_started = 0
+		self.progress_stopped = 0
 		
 		# create all the directories
-		for s in Records.SUBDIRS:
+		for s in Records.CLASSES:
 			dir = os.path.join(self.dirname, s)
 			if not os.path.isdir(dir):
 				try:
@@ -104,9 +109,10 @@
 	def startElement(self, name, attributes):
 		"call the start handler for this element if we defined one."
 		
-		self.generic_start(name)    # tracks element nesting
+		ns_name = name.replace(":", "_")
+		self.generic_start(ns_name)    # tracks element nesting
 		
-		function_name = "start_" + name
+		function_name = "start_" + ns_name
 		try:
 			HTML.__dict__[function_name](self, attributes)
 		except KeyError:
@@ -124,7 +130,7 @@
 	def endElement(self, name):
 		"call the end handler for this element if we defined one."
 		
-		function_name = "end_" + name
+		function_name = "end_" + name.replace(":", "_")
 		try:
 			HTML.__dict__[function_name](self)
 		except KeyError:
@@ -137,6 +143,12 @@
 		self.existencechecks()
 		self.dumptotals()
 		try:
+			if self.progress_started > 0:
+				t_from = time.asctime(time.localtime(self.progress_started))
+				t_to = time.asctime(time.localtime(self.progress_stopped))
+				self.index.write("<p>start: " + t_from + "\n")
+				self.index.write("<br>end&nbsp;&nbsp;: " + t_to + "\n")
+				
 			self.index.write("<p><table><tr><th></th>")
 			
 			for title in Records.TITLES:
@@ -239,6 +251,23 @@
 		except KeyError:
 			pass
 	
+	def char_buildlog(self, char):
+		'''process text in the top-level element.
+		
+		ideally all text will be inside <recipe> tags, but some will not.
+		"make" errors in particular appear inside the buildlog tag itself.'''
+		
+		text = char.strip()
+		if text:
+			match = self.noruletomake.search(text)
+			if match:
+				target = match.group(2)
+				depend = match.group(1)
+				if target in self.missed_depends:
+					self.missed_depends[target].append(depend)
+				else:
+					self.missed_depends[target] = [depend]
+		
 	def end_buildlog(self):
 		pass
 		
@@ -271,6 +300,46 @@
 				self.err("status element not inside a recipe element")
 		except KeyError:
 			pass
+	
+	def start_time(self, attributes):
+		try:
+			if self.recipe_tag:
+				self.recipe_tag.time = float(attributes['elapsed'])
+			else:
+				self.err("status element not inside a recipe element")
+		except KeyError:
+			pass
+	
+	def start_progress_start(self, attributes):
+		'''on progress:start note the parse starting timestamp.
+		
+		and keep track of the earliest timestamp of all as that shows
+		us when the sbs command was run.'''
+		try:
+			t = float(attributes['time'])
+			if self.progress_started == 0 or t < self.progress_started:
+				self.progress_started = t
+				
+			if attributes['task'] == 'parse':
+				self.parse_start[attributes['key']] = t
+		except KeyError:
+			pass
+		
+	def start_progress_end(self, attributes):
+		'''on progress:end add the elapsed parse time to the total time.
+		
+		also keep track of the latest timestamp of all as that shows
+		us when the sbs command finished.'''
+		try:
+			t = float(attributes['time'])
+			if t > self.progress_stopped:
+				self.progress_stopped = t
+				
+			if attributes['task'] == 'parse':
+				elapsed = t - self.parse_start[attributes['key']]
+				self.totals.inc(Records.TIME, elapsed)
+		except KeyError:
+			pass
 		
 	def start_error(self, attributes):
 		self.error_tag = TaggedText(attributes)
@@ -367,7 +436,34 @@
 			self.tmp.write(self.build_tag.strip() + "\n")
 		except:
 			return self.err("could not write to temporary file")
-				
+	
+	def start_clean(self, attributes):
+		try:
+			for attrib in ['bldinf', 'config']:
+				self.tmp.write("|")
+				if attrib in attributes:
+					self.tmp.write(attributes[attrib])
+			self.tmp.write("\n")
+		except:
+			return self.err("could not write to temporary file")
+	
+	def start_file(self, attributes):
+		'''opening file tag.
+		
+		in the temporary file we need to mark the "clean" targets with a
+		leading ">" character so they can be treated differently from 
+		the "releasable" targets'''
+		self.file_tag = ">"
+		
+	def char_file(self, char):
+		self.file_tag += char
+		
+	def end_file(self):
+		try:
+			self.tmp.write(self.file_tag.strip() + "\n")
+		except:
+			return self.err("could not write to temporary file")
+						
 	# even if we ignore an element we need to mark its coming and going
 	# so that we know which element any character data belongs to.
 	
@@ -436,7 +532,7 @@
 			# we don't want to show successes, just count them
 			return
 		
-		linkname = os.path.join(Records.SUBDIRS[type], "overall.html")
+		linkname = os.path.join(Records.CLASSES[type], "overall.html")
 		filename = os.path.join(self.dirname, linkname)
 		title = Records.TITLES[type] + " for all configurations"
 		try:
@@ -448,17 +544,18 @@
 		except:
 			return self.err("cannot create file '%s'" % filename)
 		
-		self.totals.set(type, 'filename', filename)
-		self.totals.set(type, 'linkname', linkname)
+		self.totals.set_filename(type, filename)
+		self.totals.set_linkname(type, linkname)
 	
 	def appendoverallfile(self, type, taggedtext):
-		self.totals.inc(type, 'N')   # one more and counting
+		self.totals.inc(type)   # one more and counting
+		self.totals.inc(Records.TIME, taggedtext.time)
 		
 		if type == Records.OK:
 			# we don't want to show successes, just count them
 			return
 		
-		filename = self.totals.get(type, 'filename')
+		filename = self.totals.get_filename(type)
 		try:
 			file = open(filename, "a")
 			file.write("<p>component: %s " % taggedtext.bldinf)
@@ -473,7 +570,7 @@
 			# we don't want to show successes, just count them
 			return
 		
-		linkname = os.path.join(Records.SUBDIRS[type], "cfg_" + configuration + ".html")
+		linkname = os.path.join(Records.CLASSES[type], "cfg_" + configuration + ".html")
 		filename = os.path.join(self.dirname, linkname)
 		title = Records.TITLES[type] + " for configuration " + configuration
 		try:
@@ -485,17 +582,18 @@
 		except:
 			return self.err("cannot create file '%s'" % filename)
 		
-		self.configurations[configuration].set(type, 'filename', filename)
-		self.configurations[configuration].set(type, 'linkname', linkname)
+		self.configurations[configuration].set_filename(type, filename)
+		self.configurations[configuration].set_linkname(type, linkname)
 	
 	def appendconfigurationfile(self, configuration, type, taggedtext):
-		self.configurations[configuration].inc(type, 'N')   # one more and counting
+		self.configurations[configuration].inc(type)   # one more and counting
+		self.configurations[configuration].inc(Records.TIME, taggedtext.time)
 		
 		if type == Records.OK:
 			# we don't want to show successes, just count them
 			return
 		
-		filename = self.configurations[configuration].get(type, 'filename')
+		filename = self.configurations[configuration].get_filename(type)
 		try:
 			file = open(filename, "a")
 			file.write("<p>component: %s\n" % taggedtext.bldinf)
@@ -509,7 +607,7 @@
 			# we don't want to show successes, just count them
 			return
 		
-		linkname = os.path.join(Records.SUBDIRS[type], "bld_" + re.sub("[/:]","_",component) + ".html")
+		linkname = os.path.join(Records.CLASSES[type], "bld_" + re.sub("[/:]","_",component) + ".html")
 		filename = os.path.join(self.dirname, linkname)
 		title = Records.TITLES[type] + " for component " + component
 		try:
@@ -521,17 +619,18 @@
 		except:
 			return self.err("cannot create file '%s'" % filename)
 		
-		self.components[component].set(type, 'filename', filename)
-		self.components[component].set(type, 'linkname', linkname)
+		self.components[component].set_filename(type, filename)
+		self.components[component].set_linkname(type, linkname)
 	
 	def appendcomponentfile(self, component, type, taggedtext):
-		self.components[component].inc(type, 'N')   # one more and counting
+		self.components[component].inc(type)   # one more and counting
+		self.components[component].inc(Records.TIME, taggedtext.time)
 		
 		if type == Records.OK:
 			# we don't want to show successes, just count them
 			return
 		
-		filename = self.components[component].get(type, 'filename')
+		filename = self.components[component].get_filename(type)
 		try:
 			file = open(filename, "a")
 			file.write("<p>config: %s\n" % taggedtext.config)
@@ -556,12 +655,37 @@
 					missing_tag = TaggedText(attribs)
 				else:
 					filename = line.strip()
-					if not filename in missed and not os.path.isfile(filename):
-						missing_tag.text = filename
-						self.record(missing_tag, Records.MISSING)
-						missed.add(filename)
+					if filename.startswith(">"):
+						# a clean target, so we don't care if it exists
+						# but we care if it has a missing dependency
+						filename = filename[1:]
+					else:
+						# a releasable target so it must exist
+						if not filename in missed and not os.path.isfile(filename):
+							missing_tag.text = filename
+							self.record(missing_tag, Records.MISSING)
+							missed.add(filename)
+						
+					if filename in self.missed_depends:
+						missing_tag.text = filename + \
+						"\n\nrequired the following files which could not be found,\n\n"
+						for dep in self.missed_depends[filename]:
+							missing_tag.text += dep + "\n"
+						self.record(missing_tag, Records.ERROR)
+						del self.missed_depends[filename]
 					
 			self.tmp.close()	# this also deletes the temporary file
+			
+			# any missed dependencies left over are not attributable to any
+			# specific component but should still be reported
+			missing_tag = TaggedText({})
+			for filename in self.missed_depends:
+				missing_tag.text = filename + \
+				"\n\nrequired the following files which could not be found,\n\n"
+				for dep in self.missed_depends[filename]:
+					missing_tag.text += dep + "\n"
+				self.record(missing_tag, Records.ERROR)
+						
 		except Exception,e:
 			return self.err("could not close temporary file " + str(e))
 	
@@ -593,8 +717,10 @@
 				try:
 					type = None
 					
-					if row[0] == "CRITICAL" or row[0] == "ERROR":
+					if row[0] == "ERROR":
 						type = Records.ERROR
+					elif row[0] == "CRITICAL":
+						type = Records.CRITICAL
 					elif row[0] == "WARNING":
 						type = Records.WARNING
 					elif row[0] == "REMARK":
@@ -615,52 +741,65 @@
 			return []
 		
 		return regexlist
+
+class CountItem(object):
+	def __init__(self):
+		self.N = 0
+		self.filename = None
+		self.linkname = None
+
+	def num_str(self):
+		return str(self.N)
 	
+class TimeItem(CountItem):
+	def num_str(self):
+		return time.strftime("%H:%M:%S", time.gmtime(self.N + 0.5))
+		
 class Records(object):
 	"a group of related records e.g. errors, warnings and remarks."
 	
 	# the different types of record we want to group together
-	OK      = 0
-	ERROR   = 1
-	WARNING = 2
-	REMARK  = 3
-	MISSING = 4
+	TIME     = 0
+	OK       = 1
+	ERROR    = 2
+	CRITICAL = 3
+	WARNING  = 4
+	REMARK   = 5
+	MISSING  = 6
 	
-	SUBDIRS = [ "ok", "error", "warning", "remark", "missing" ]
-	TITLES = [ "OK", "Errors", "Warnings", "Remarks", "Missing files" ]
+	CLASSES = [ "time", "ok", "error", "critical", "warning", "remark", "missing" ]
+	TITLES = [ "CPU Time", "OK", "Errors", "Criticals", "Warnings", "Remarks", "Missing files" ]
 	
 	def __init__(self):
-		self.data = [ {'N':0}, {'N':0}, {'N':0}, {'N':0}, {'N':0} ]
-	
-	def get(self, index, item):
-		try:
-			return self.data[index][item]
-		except KeyError:
-			return None
+		self.data = [ TimeItem(), CountItem(), CountItem(), CountItem(), CountItem(), CountItem(), CountItem() ]
+		
+	def get_filename(self, index):
+		return self.data[index].filename
 		
-	def inc(self, index, item):
-		self.data[index][item] += 1
-	
+	def inc(self, index, increment=1):
+		self.data[index].N += increment
+
 	def isempty(self, index):
-		return (self.data[index]['N'] == 0)
+		return (self.data[index].N == 0)
 		
-	def set(self, index, item, value):
-		self.data[index][item] = value
+	def set_filename(self, index, value):
+		self.data[index].filename = value
 	
+	def set_linkname(self, index, value):
+		self.data[index].linkname = value
+		
 	def tablerow(self, name):
 		row = '<tr><td class="name">%s</td>' % name
-
+		
 		for i,datum in enumerate(self.data):
-			number = datum['N']
-			if number == 0:
+			if datum.N == 0:
 				row += '<td class="zero">0</td>'
 			else:
-				row += '<td class="' + Records.SUBDIRS[i] + '">'
-				try:
-					link = datum['linkname']
-					row += '<a href="%s">%d</a></td>' % (link,number)
-				except KeyError:
-					row += '%d</td>' % number
+				row += '<td class="' + Records.CLASSES[i] + '">'
+				if datum.linkname:
+					row += '<a href="%s">%s</a></td>' % (datum.linkname,datum.num_str())
+				else:
+					row += '%s</td>' % datum.num_str()
 							
 		row += "</tr>"
 		return row
@@ -668,12 +807,11 @@
 	def textdump(self):
 		text = ""
 		for i,datum in enumerate(self.data):
-			number = datum['N']
-			if number == 0:
+			if datum.N == 0:
 				style = "zero"
 			else:
-				style = Records.SUBDIRS[i]
-			text += str(i) + ',' + style + "," + str(number) + "\n"
+				style = Records.CLASSES[i]
+			text += str(i) + ',' + style + "," + str(datum.N) + "\n"
 		return text
 				
 class TaggedText(object):
@@ -687,5 +825,6 @@
 					self.__dict__[attrib] = value
 
 		self.text = ""
+		self.time = 0.0
 		
 # the end
\ No newline at end of file
--- a/sbsv2/raptor/python/raptor_cli.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/python/raptor_cli.py	Mon Sep 13 14:04:04 2010 +0100
@@ -22,9 +22,7 @@
 import raptor
 
 from optparse import OptionParser # for parsing command line parameters
-
-fullCommandOption = "--command"
-miniCommandOption = "--co"  # update this if another "co" option is added
+from raptor_utilities import expand_command_options
 
 # raptor_cli module attributes
 
@@ -179,51 +177,6 @@
 	"Process command line arguments for a Raptor object"
 	return DoRaptor(Raptor,args)
 
-def ReadCommandFile(filename, used):
-	if filename in used:
-		raise IOError("command file '%s' refers to itself" % filename)
-
-	args = []
-	try:
-		file = open(filename, "r")
-		for line in file.readlines():
-			args.extend(line.split())
-		file.close()
-	except:
-		raise IOError("couldn't read command file '%s'" % filename)
-
-	# expand any command files in the options we just read.
-	# making sure we don't get stuck in a loop.
-	usedPlusThis = used[:]
-	usedPlusThis.append(filename)
-	return ExpandCommandOptions(args, usedPlusThis)
-
-def ExpandCommandOptions(args, files = []):
-	"""recursively expand --command options."""
-	expanded = []
-	previousWasOpt = False
-
-	for a in args:
-		if previousWasOpt: # then this one is the filename
-			expanded.extend(ReadCommandFile(a, files))
-			previousWasOpt = False
-			continue
-
-		if a.startswith(miniCommandOption):
-			if "=" in a: # then this is opt=filename
-				opt = a.split("=")
-				if fullCommandOption.startswith(opt[0]):
-					expanded.extend(ReadCommandFile(opt[1], files))
-					continue
-			else: # the next one is the filename
-				if fullCommandOption.startswith(a):
-					previousWasOpt = True
-					continue
-
-		expanded.append(a) # an ordinary arg, nothing to do with command files
-
-	return expanded
-
 def DoRaptor(Raptor, args):
 	"Process raptor arguments"
 	#
@@ -236,7 +189,7 @@
 	non_ascii_error = "Non-ASCII character in argument or command file"
 
 	try:
-		expanded_args = ExpandCommandOptions(args)
+		expanded_args = expand_command_options(args)
 		for arg in expanded_args:
 			for c in arg:
 				if ord(c) > 127:
--- a/sbsv2/raptor/python/raptor_meta.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/python/raptor_meta.py	Mon Sep 13 14:04:04 2010 +0100
@@ -2599,11 +2599,14 @@
 				self.__Raptor.Debug("Automatic OS detection disabled.")
 
 			# is this a feature variant config or an ordinary variant
-			fv = evaluator.Get("FEATUREVARIANTNAME")
-			if fv:
-				variantHdr = evaluator.CheckedGet("VARIANT_HRH")
+			fvn = evaluator.Get("FEATUREVARIANTNAME")
+			detail['ISFEATUREVARIANT'] = (fvn != None and fvn != '')
+
+			# get the .hrh name from VARIANT_HRH if it is set, otherwise read
+			# the name from the contents of the file named in VARIANT_CFG
+			variantHdr = evaluator.Get("VARIANT_HRH")
+			if variantHdr:
 				variantHRH = generic_path.Path(variantHdr)
-				detail['ISFEATUREVARIANT'] = True
 			else:
 				variantCfg = evaluator.CheckedGet("VARIANT_CFG")
 				variantCfg = generic_path.Path(variantCfg)
@@ -2616,12 +2619,11 @@
 						self.__Raptor.Warn("missing flag ENABLE_ABIV2_MODE in %s file. ABIV1 builds are not supported.",
 										   str(variantCfg))
 				variantHRH = variantCfgs[variantCfg]
-				detail['ISFEATUREVARIANT'] = False
 
 			detail['VARIANT_HRH'] = variantHRH
 			self.__Raptor.Info("'%s' uses variant hrh file '%s'", buildConfig.name, variantHRH)
 			detail['SYSTEMINCLUDE'] = evaluator.CheckedGet("SYSTEMINCLUDE")
-            
+
 			detail['TARGET_TYPES'] = evaluator.CheckedGet("TARGET_TYPES")
 
 			# find all the interface names we need
@@ -2996,8 +2998,7 @@
 			destDir = destination.Dir()
 			if not destDir.isDir():
 				os.makedirs(str(destDir))
-				# preserve permissions
-				shutil.copy(source_str, dest_str)
+				shutil.copyfile(source_str, dest_str)
 				return exportwhatlog
 
 			sourceMTime = 0
@@ -3016,14 +3017,12 @@
 						self.__Raptor.Error(message, bldinf=bldInfFile)
 
 			if destMTime == 0 or destMTime < sourceMTime:
-				# remove old version
-				#	- not having ownership prevents chmod
-				#	- avoid clobbering the original if it is a hard link
 				if os.path.exists(dest_str):
-					os.unlink(dest_str)
-				# preserve permissions
-				shutil.copy(source_str, dest_str)
-
+					os.chmod(dest_str,stat.S_IREAD | stat.S_IWRITE)
+				shutil.copyfile(source_str, dest_str)
+
+				# Ensure that the destination file remains executable if the source was also:
+				os.chmod(dest_str,sourceStat[stat.ST_MODE] | stat.S_IREAD | stat.S_IWRITE | stat.S_IWGRP ) 
 				self.__Raptor.Info("Copied %s to %s", source_str, dest_str)
 			else:
 				self.__Raptor.Info("Up-to-date: %s", dest_str)
--- a/sbsv2/raptor/python/raptor_utilities.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/python/raptor_utilities.py	Mon Sep 13 14:04:04 2010 +0100
@@ -239,3 +239,56 @@
 		raise IOError(message)
 
 	return 
+
+
+
+## Commandline processing utilities ##
+
+fullCommandOption = "--command"
+miniCommandOption = "--co"  # update this if another "co" option is added
+
+def read_command_file(filename, used):
+	"""Read commandline options in from a file"""
+	if filename in used:
+		raise IOError("command file '%s' refers to itself" % filename)
+
+	args = []
+	try:
+		file = open(filename, "r")
+		for line in file.readlines():
+			args.extend(line.split())
+		file.close()
+	except:
+		raise IOError("couldn't read command file '%s'" % filename)
+
+	# expand any command files in the options we just read.
+	# making sure we don't get stuck in a loop.
+	usedPlusThis = used[:]
+	usedPlusThis.append(filename)
+	return expand_command_options(args, usedPlusThis)
+
+def expand_command_options(args, files = []):
+	"""process commandline options to recursively expand command files (--command options) into a full list of options."""
+	expanded = []
+	previousWasOpt = False
+
+	for a in args:
+		if previousWasOpt: # then this one is the filename
+			expanded.extend(read_command_file(a, files))
+			previousWasOpt = False
+			continue
+
+		if a.startswith(miniCommandOption):
+			if "=" in a: # then this is opt=filename
+				opt = a.split("=")
+				if fullCommandOption.startswith(opt[0]):
+					expanded.extend(read_command_file(opt[1], files))
+					continue
+			else: # the next one is the filename
+				if fullCommandOption.startswith(a):
+					previousWasOpt = True
+					continue
+
+		expanded.append(a) # an ordinary arg, nothing to do with command files
+
+	return expanded
--- a/sbsv2/raptor/python/raptor_version.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/python/raptor_version.py	Mon Sep 13 14:04:04 2010 +0100
@@ -19,7 +19,7 @@
 #
 # both of these are done automatically by the installer builder.
 
-version=(2,15,1,"ISODATE","symbian build system","CHANGESET")
+version=(2,15,2,"ISODATE","symbian build system","CHANGESET")
 
 def numericversion():
 	"""Raptor version string"""
--- a/sbsv2/raptor/style/filter_html.css	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/style/filter_html.css	Mon Sep 13 14:04:04 2010 +0100
@@ -25,8 +25,10 @@
 {
 	text-align: left;
 }
+td.time { background: #80ff80; }
 td.ok { background: #80ff80; }
 td.error { background: #ff8080; }
+td.critical { background: #ffc080; }
 td.warning { background: #ffff80; }
 td.remark { background: #8080ff; }
 td.missing { background: #c0c0c0; }
--- a/sbsv2/raptor/test/common/raptor_tests.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/common/raptor_tests.py	Mon Sep 13 14:04:04 2010 +0100
@@ -323,7 +323,7 @@
 		return "-f " + self.logfile();
 	
 	def logfile(self):
-		return logDir + "/" + self.name + ".log"
+		return logDir + "/" + self.name.replace(" ","_") + ".log"
 	
 	def makefileOption(self):
 		return "-m " + self.makefile();
@@ -367,6 +367,7 @@
 		
 		print "\nID:", self.id
 		print "TEST:", self.name
+		print "LOGFILE:", self.logfile()
 
 		return self.clean()
 			
--- a/sbsv2/raptor/test/smoke_suite/capability_arm.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/capability_arm.py	Mon Sep 13 14:04:04 2010 +0100
@@ -16,13 +16,15 @@
 
 from raptor_tests import SmokeTest
 import sys
+import os
 
 def run():
 	t = SmokeTest()
 	t.usebash = True
 
-
-	if sys.platform.startswith("win"):
+	if "SBS_ELF2E32" in os.environ:
+		elf2e32 = os.environ["SBS_ELF2E32"]
+	elif sys.platform.startswith("win"):
 		elf2e32 = "$(EPOCROOT)/epoc32/tools/elf2e32.exe"
 	else:
 		elf2e32 = "$(EPOCROOT)/epoc32/tools/elf2e32"
--- a/sbsv2/raptor/test/smoke_suite/export.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/export.py	Mon Sep 13 14:04:04 2010 +0100
@@ -14,7 +14,7 @@
 # Description: 
 #
 
-from raptor_tests import SmokeTest, AntiTargetSmokeTest
+from raptor_tests import AntiTargetSmokeTest
 import os
 
 def run():
@@ -23,9 +23,9 @@
 	# reallyclean_simple_export tests to use so that we can put the
 	# username into the output filenames - which helps a lot when
 	# several people run tests on the same computer (e.g. linux machines)
-	bld = open('smoke_suite/test_resources/simple_export/expbld.inf', 'w')
+	bld_inf = open('smoke_suite/test_resources/simple_export/expbld.inf', 'w')
 	user = os.environ['USER']
-	bld.write("""
+	bld_inf.write("""
 	
 PRJ_PLATFORMS
 ARMV5 WINSCW
@@ -48,20 +48,16 @@
 "file with a space.doc" "exportedfilewithspacesremoved.doc"
 "file with a space.doc" "exported file with a space.doc"
 
-simple_exp1.h /tmp/%s/  //
-simple_exp2.h \\tmp\\%s/  //
-simple_exp3.h /tmp/%s/simple_exp3.h 
+simple_exp1.h /tmp/{0}/  //
+simple_exp2.h \\tmp\\{0}/  //
+simple_exp3.h /tmp/{0}/simple_exp3.h 
 simple_exp4.h //
+read_only.h was_read_only.h //
 
-""" % (user, user, user))
-	bld.close()
-
-
-	t = SmokeTest()
-	t.id = "0023a"
-	t.name = "export"
-	t.command = "sbs -b smoke_suite/test_resources/simple_export/expbld.inf export"
-	t.targets = [
+""".format(user))
+	bld_inf.close()
+	
+	exported_files = [
 		"$(EPOCROOT)/epoc32/include/exported_1.h",
 		"$(EPOCROOT)/epoc32/include/exported_2.h",
 		"$(EPOCROOT)/epoc32/include/exported_3.h",
@@ -71,79 +67,51 @@
 		"/tmp/$(USER)/simple_exp2.h",
 		"/tmp/$(USER)/simple_exp3.h",
 		"$(EPOCROOT)/epoc32/include/executable_file",
-		"$(EPOCROOT)/epoc32/include/simple_exp4.h"
+		"$(EPOCROOT)/epoc32/include/simple_exp4.h",
+		"$(EPOCROOT)/epoc32/include/was_read_only.h",
 		]
+
+	t = AntiTargetSmokeTest()
+	
+	# Check basic export success
+	t.name = "export_basic"
+	t.command = "sbs -b smoke_suite/test_resources/simple_export/expbld.inf export"
+	t.targets = exported_files
+	t.antitargets = []
 	t.run()
 	
-
-	t = SmokeTest()
-	t.id = "0023a1"
-	t.name = "export"
+	# Confirm executable permissions are retained on Linux
+	t.name = "export_executable_permissions"
 	t.usebash = True
 	t.command = "ls -l ${EPOCROOT}/epoc32/include/executable_file"
 	t.mustmatch = [ "^.rwxrwxr.x[\.\+]? .*executable_file.*$" ]
-	t.targets = []
+	t.targets = [] # prevent auto clean-up up of target files from previous test
+	t.antitargets = []
 	t.run("linux")
-	t.usebash = False
 
-
-	# Testing if clean deletes any exports which it is not supposed to
-	t.id = "0023b"
-	t.name = "export_clean" 
+	# Check clean does not delete exports
+	t.name = "export_clean"
 	t.command = "sbs -b smoke_suite/test_resources/simple_export/expbld.inf clean"
 	t.mustmatch = []
-	t.targets = [
-		"$(EPOCROOT)/epoc32/include/exported_1.h",
-		"$(EPOCROOT)/epoc32/include/exported_2.h",
-		"$(EPOCROOT)/epoc32/include/exported_3.h",
-		"$(EPOCROOT)/epoc32/include/executable_file",
-		"$(EPOCROOT)/epoc32/include/exportedfilewithspacesremoved.doc",
-		"$(EPOCROOT)/epoc32/include/exported file with a space.doc",
-		"/tmp/$(USER)/simple_exp1.h",
-		"/tmp/$(USER)/simple_exp2.h",
-		"/tmp/$(USER)/simple_exp3.h"
-		]
+	t.targets = exported_files
+	t.antitargets = []
 	t.run()
 
-
-	t = AntiTargetSmokeTest()
-	t.id = "0023c"
+	# Confirm reallyclean deletes all exports, including those that were read-only
+	# as source (and so should now be removable at their destination)
 	t.name = "export_reallyclean" 
 	t.command = "sbs -b smoke_suite/test_resources/simple_export/expbld.inf reallyclean"
-	t.antitargets = [
-		'$(EPOCROOT)/epoc32/include/exported_1.h',
-		'$(EPOCROOT)/epoc32/include/exported_2.h',
-		'$(EPOCROOT)/epoc32/include/exported_3.h',
-		"$(EPOCROOT)/epoc32/include/executable_file",
-		'$(EPOCROOT)/epoc32/include/exportedfilewithspacesremoved.doc',
-		'$(EPOCROOT)/epoc32/include/exported file with a space.doc',
-		'/tmp/$(USER)/simple_exp1.h',
-		'/tmp/$(USER)/simple_exp2.h',
-		'/tmp/$(USER)/simple_exp3.h',
-		'$(EPOCROOT)/epoc32/include/simple_exp4.h'
-	]
+	t.targets = []
+	t.antitargets = exported_files
 	t.run()
 
-	# Check that the --noexport feature really does prevent exports from happening
-	t = AntiTargetSmokeTest()
-	t.id = "0023d"
+	# Check --noexport suppresses exports
 	t.name = "export_noexport" 
 	t.command = "sbs -b smoke_suite/test_resources/simple_export/expbld.inf --noexport -n"
-	t.antitargets = [
-		'$(EPOCROOT)/epoc32/include/exported_1.h',
-		'$(EPOCROOT)/epoc32/include/exported_2.h',
-		'$(EPOCROOT)/epoc32/include/exported_3.h',
-		"$(EPOCROOT)/epoc32/include/executable_file",
-		'$(EPOCROOT)/epoc32/include/exportedfilewithspacesremoved.doc',
-		'$(EPOCROOT)/epoc32/include/exported file with a space.doc',
-		'/tmp/$(USER)/simple_exp1.h',
-		'/tmp/$(USER)/simple_exp2.h',
-		'/tmp/$(USER)/simple_exp3.h',
-		'$(EPOCROOT)/epoc32/include/simple_exp4.h'
-	]
+	t.targets = []
+	t.antitargets = exported_files
 	t.run()
-		
-	t.id = "23"
+	
 	t.name = "export"
 	t.print_result()
 	return t
--- a/sbsv2/raptor/test/smoke_suite/featurevariants.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/featurevariants.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,4 +1,4 @@
-#
+
 # Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
@@ -15,11 +15,20 @@
 #
 
 from raptor_tests import AntiTargetSmokeTest, ReplaceEnvs
+from raptor_meta import BldInfFile
 import os
 
 def run():
 	t = AntiTargetSmokeTest()
 	t.usebash = True
+
+	# create some empty source files just to test createvmaps command file handling:
+	test_cpp_files = []
+	for i in xrange(0,16):
+		tf = "smoke_suite/test_resources/bv/variant1/test_createvmap{0:02}.cpp".format(i)
+		f = open(tf,"w+")
+		f.close()
+		test_cpp_files.append(tf)
 	
 	preBuiltTargets = [
 		"$(EPOCROOT)/epoc32/release/armv5/udeb/dummy.lib",
@@ -300,26 +309,46 @@
 		"dummy_var3_exe/dummy_var3_dummy.rsc.d"
 		]
 	
-	sbscommand = "sbs -b smoke_suite/test_resources/bv/bld.inf -c armv5 " + \
-				"-c armv5.test_bv_1 -c armv5.test_bv_2 -c armv5.test_bv_3 -f- " + \
-				"--configpath=test/smoke_suite/test_resources/bv/config/variants"
+	bldinf = 'smoke_suite/test_resources/bv/bld.inf'
+	sbscommand = "sbs -b {0} -c armv5 -c armv5.test_bv_1 -c armv5.test_bv_2 -c armv5.test_bv_3 -f- --configpath=test/smoke_suite/test_resources/bv/config/variants".format(bldinf)
 	
 	t.id = "56a"
 	t.description = """Build variant and invariant components.
 		In this default mode of operation, all components build for the non-product armv5 config whereas
 		only variant components build for the armv5.* bv configs."""
 	t.name = "featurevariant_build"
-	t.command = sbscommand
+
+	t.command = "{0} && cat $(EPOCROOT)/epoc32/build/{1}/{2}".format(sbscommand, BldInfFile.outputPathFragment(bldinf), "createstaticdll_variant1_dll/armv5.three/udeb/createstaticdll_variant1.vmap.cmdfile")
 	t.targets = preBuiltTargets + invariantTargets + variantTargetsGeneric + variantTargetsDefaultTree + variantTargetsProductTrees							
-	t.addbuildtargets('smoke_suite/test_resources/bv/bld.inf',
+	t.addbuildtargets(bldinf,
 				invariantBuildTargets + variantBuildTargetsGeneric + variantBuildTargetsDefaultTree + variantBuildTargetsProductTrees	
 				)
+	
 	# Test that static libs are linked from the invariant place.
 	t.mustmatch = [
 		"armlink.*epoc32/release/armv5/urel/bv_static_lib.lib",
-		"armlink.*epoc32/release/armv5/udeb/bv_static_lib.lib"
+		"armlink.*epoc32/release/armv5/udeb/bv_static_lib.lib",
+		"\s*-s.*variant1/CreateStaticDLL_variant1.cpp",
+		"\s*-s.*variant1/test_createvmap01.cpp",
+		"\s*-s.*variant1/test_createvmap02.cpp",
+		"\s*-s.*variant1/test_createvmap03.cpp",
+		"\s*-s.*variant1/test_createvmap04.cpp",
+		"\s*-s.*variant1/test_createvmap05.cpp",
+		"\s*-s.*variant1/test_createvmap06.cpp",
+		"\s*-s.*variant1/test_createvmap07.cpp",
+		"\s*-s.*variant1/test_createvmap08.cpp",
+		"\s*-s.*variant1/test_createvmap09.cpp",
+		"\s*-s.*variant1/test_createvmap10.cpp",
+		"\s*-s.*variant1/test_createvmap11.cpp",
+		"\s*-s.*variant1/test_createvmap12.cpp",
+		"\s*-s.*variant1/test_createvmap13.cpp",
+		"\s*-s.*variant1/test_createvmap14.cpp",
+		"\s*-s.*variant1/test_createvmap15.cpp",
+		"\s*-s.*variant1/CreateStaticDLL_variant1.mmp"
 		]
 	t.run()
+
+
 	
 	t.id = "56b"
 	t.description = """Build variant and invariant components using an os_properties.xml that sets FEATUREVARIANTSAFE=1.
@@ -342,6 +371,7 @@
 		]
 	t.run()
 
+
 	
 	# tests for the createvmap script
 	createvmap = "python $(SBS_HOME)/bin/createvmap.py"
@@ -413,6 +443,11 @@
 	t.targets = [vmapfile]
 	t.mustmatch = ["A_1=defined", "B_1000=undefined"]
 	t.run()
+
+
+	# clean up test cpp files from the first test (do it noow after they are no longer needed)
+	for tf in test_cpp_files:
+		os.unlink(tf)
 	
 	
 	# print the overall result
--- a/sbsv2/raptor/test/smoke_suite/romfile.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/romfile.py	Mon Sep 13 14:04:04 2010 +0100
@@ -16,24 +16,27 @@
 
 
 from raptor_tests import SmokeTest
-import os
 
 def run():
 	t = SmokeTest()
 	t.description = """
 		Tests the creation and content of an .iby romfile for the armv5.test
 		configuration. Also tests for creation of relevant test batch files.
-		"""
-	t.id = "55a"
-	t.name = "romfile_general"
+		"""	
 	t.usebash = True
-	t.command = "sbs -b $(EPOCROOT)/src/ongoing/group/romfile/other_name.inf " \
-			+ "-c armv5.test ROMFILE -f - " \
-			+ "&& cat $(EPOCROOT)/epoc32/rom/src/ongoing/group/romfile/armv5test.iby"
-	
 	# Don't allow -m or -f to be appended
 	t.logfileOption = lambda :""
 	t.makefileOption = lambda :""
+	
+	t.id = "55a"
+	# Check content of iby file is correct
+	# Check batch files are generated
+	t.name = "romfile_general"
+	
+	t.command = "sbs -b $(EPOCROOT)/src/ongoing/group/romfile/other_name.inf " \
+			+ "-c armv5.test ROMFILE -m ${SBSMAKEFILE} -f ${SBSLOGFILE} " \
+			+ "&& cat $(EPOCROOT)/epoc32/rom/src/ongoing/group/romfile/armv5test.iby"
+	
 	t.targets = [
 		"$(EPOCROOT)/epoc32/rom/src/ongoing/group/romfile/armv5test.iby",
 		"$(EPOCROOT)/epoc32/data/z/test/src/armv5.auto.bat",
@@ -41,13 +44,7 @@
 		]
 
 	# Check the content of the generated .iby file.
-
 	t.mustmatch = [
-		# Check whatlog output includes batch files and .iby file
-		r".*/epoc32/rom/src/ongoing/group/romfile/armv5test.iby</build>.*",
-		r".*/epoc32/data/z/test/src/armv5.auto.bat</build>.*",
-		r".*/epoc32/data/z/test/src/armv5.manual.bat</build>.*",
-		
 		# The comment that is put at the start of the file.
 		r".*// epoc32/rom/src/ongoing/group/romfile/armv5test\.iby\n.*",
 
@@ -76,21 +73,27 @@
 		# without flagging C++ style comments.
 		r"\w//+\w"
 		]
-
-	t.run("windows")
+	t.warnings = 0 if t.onWindows else 2
+	t.run()
+	
 
-	if t.result == SmokeTest.SKIP:
-		t.command = "sbs -b $(EPOCROOT)/src/ongoing/group/romfile/other_name.inf" \
-				+ " -c armv5.test ROMFILE -f -" \
-				+ " && cat $(EPOCROOT)/epoc32/rom/src/ongoing/group/romfile/armv5test.iby"
-
-		# These two warnings are because gnumakefiles are not supported on
-		# Linux:
-		t.warnings = 2
-		t.run("linux")
+	t.id = "55b"
+	# t.targets and t.warnings are the same as above and thus omitted
+	t.name = "romfile_whatlog"
+	t.command = "sbs -b $(EPOCROOT)/src/ongoing/group/romfile/other_name.inf " \
+			+ "-c armv5.test ROMFILE -f -"
+	
+	t.mustmatch = [
+		# Check whatlog output includes batch files and .iby file
+		r".*/epoc32/rom/src/ongoing/group/romfile/armv5test.iby</build>.*",
+		r".*/epoc32/data/z/test/src/armv5.auto.bat</build>.*",
+		r".*/epoc32/data/z/test/src/armv5.manual.bat</build>.*"
+		]
+	t.mustnotmatch = []
+	t.run()
 
 
-	t.id = "55b"
+	t.id = "55c"
 	t.name = "romfile_mmp_include_twice"
 	t.command = "sbs -b $(EPOCROOT)/src/e32test/group/bld.inf " \
 	        + "-b $(EPOCROOT)/src/falcon/test/bld.inf " \
@@ -115,6 +118,7 @@
 	t.warnings = 0
 	t.run()
 
+
 	t.id = "55"
 	t.name = "romfile"
 	t.print_result()
--- a/sbsv2/raptor/test/smoke_suite/stringtable_zip_whatlog.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/stringtable_zip_whatlog.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -43,6 +43,7 @@
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin",
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt",
 		"$(EPOCROOT)/epoc32/build/" + markerfile
 		]
 	t.addbuildtargets('smoke_suite/test_resources/simple_stringtable/bld.inf', [
@@ -60,6 +61,7 @@
 		"<member>$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt</member>",
 		"<member>$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt</member>",
 		"<member>$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin</member>",
+		"<member>$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt</member>",
 		"<zipmarker>$(EPOCROOT)/epoc32/build/" + markerfile + "</zipmarker>"
 	]
 	t.run()
--- a/sbsv2/raptor/test/smoke_suite/test_resources/bv/variant1/CreateStaticDLL_variant1.mmp	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/test_resources/bv/variant1/CreateStaticDLL_variant1.mmp	Mon Sep 13 14:04:04 2010 +0100
@@ -29,6 +29,23 @@
 SOURCEPATH    .
 SOURCE        CreateStaticDLL_variant1.cpp
 
+// > 10 files to test the createvmap handling of command files
+SOURCE        test_createvmap01.cpp
+SOURCE        test_createvmap02.cpp
+SOURCE        test_createvmap03.cpp
+SOURCE        test_createvmap04.cpp
+SOURCE        test_createvmap05.cpp
+SOURCE        test_createvmap06.cpp
+SOURCE        test_createvmap07.cpp
+SOURCE        test_createvmap08.cpp
+SOURCE        test_createvmap09.cpp
+SOURCE        test_createvmap10.cpp
+SOURCE        test_createvmap11.cpp
+SOURCE        test_createvmap12.cpp
+SOURCE        test_createvmap13.cpp
+SOURCE        test_createvmap14.cpp
+SOURCE        test_createvmap15.cpp
+
 USERINCLUDE   .
 APP_LAYER_SYSTEMINCLUDE_SYMBIAN
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/smoke_suite/test_resources/simple_export/read_only.h	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,17 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
Binary file sbsv2/raptor/test/smoke_suite/test_resources/simple_zip_export/archive.zip has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/smoke_suite/test_resources/tools2/bootstrap.inf	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,22 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+PRJ_PLATFORMS
+TOOLS2
+
+PRJ_EXPORTS
+header_abc.h bootstrap_header_abc.h
--- a/sbsv2/raptor/test/smoke_suite/tools2.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/tools2.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -18,11 +18,11 @@
 
 def run():
 	t = SmokeTest()
-	t.id = "51"
-	t.name = "tools2"
+	
+	t.id = "51a"
+	t.name = "tools2_exe_lib"
 	t.command = "sbs -b smoke_suite/test_resources/tools2/bld.inf -c tools2"
 
-
 	t.targets = [
 		"$(EPOCROOT)/epoc32/release/tools2/deb/libtool_lib1.a",
 		"$(EPOCROOT)/epoc32/release/tools2/deb/libtool_lib2.a",
@@ -74,5 +74,19 @@
 			"tool_exe_exe/tool_exe_exe/tools2/deb/$(HOSTPLATFORM_DIR)/tool_exe_a.o"
 			])
 		t.run("linux") # tools2 output is platform dependent
-		
+	
+	t.id = "51b"
+	t.name = "tools2_nohrh"
+	t.usebash = True
+	t.command = "sbs -b smoke_suite/test_resources/tools2/bootstrap.inf -c tools2.nohrh -f -"
+	t.targets = ["$(EPOCROOT)/epoc32/include/bootstrap_header_abc.h"]
+	t.mustmatch_singleline = ["empty\.hrh"]
+	t.mustnotmatch_singleline = ["Symbian_OS.hrh",
+								 "symbian_os.hrh",
+								 "feature_settings.hrh"]
+	t.run()
+	
+	t.id = "51"
+	t.name = "tools2"
+	t.print_result()
 	return t
--- a/sbsv2/raptor/test/smoke_suite/zip_export_plus_clean.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/zip_export_plus_clean.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -14,7 +14,7 @@
 # Description: 
 #
 
-from raptor_tests import SmokeTest, AntiTargetSmokeTest, ReplaceEnvs
+from raptor_tests import AntiTargetSmokeTest, ReplaceEnvs
 from raptor_meta import MetaReader
 from raptor_utilities import sanitise
 import re
@@ -23,9 +23,9 @@
 	premarkerfile = sanitise(ReplaceEnvs("$(SBS_HOME)_test_smoke_suite_test_resources_simple_zip_export_archive.zip$(EPOCROOT)_epoc32_testunzip"))
 	markerfile = MetaReader.unzippedPathFragment(premarkerfile) + ".unzipped"
 	
-	t = SmokeTest()
-	
-	t.id = "0024a"
+	t = AntiTargetSmokeTest()
+
+	# Check basic export success	
 	t.name = "zip_export"
 	t.command = "sbs -b smoke_suite/test_resources/simple_zip_export/bld.inf"
 	t.targets = [
@@ -34,33 +34,35 @@
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin",
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt",
 		"$(EPOCROOT)/epoc32/build/" + markerfile
 	]
 	t.run()
-	
-	t.id = "0024aa"
+
+	# Confirm executable permissions are retained on Linux	
 	t.name = "zip_export_execute_permissions"
 	t.usebash = True
-	t.targets = []
+	t.targets = [] # prevent auto clean-up up of target files from previous test
 	t.command = "ls -l $(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin"
 	t.mustmatch = ["-[rw-]{2}x[rw-]{2}x[rw-]{2}x"]
 	t.run("linux")
-	
-	t = AntiTargetSmokeTest()
-	t.id = "0024b"
+
+	# Confirm reallyclean deletes all exports, including those that were read-only
+	# as source (and so should now be removable at their destination)	
 	t.name = "zip_export_reallyclean"
-	t.command = "sbs -b smoke_suite/test_resources/simple_zip_export/bld.inf REALLYCLEAN"
+	t.command = "sbs -b smoke_suite/test_resources/simple_zip_export/bld.inf reallyclean"
+	t.mustmatch = []
 	t.antitargets = [
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile1.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile2.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt",
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin",
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt",
 		"$(EPOCROOT)/epoc32/build/" + markerfile
 	]
 	t.run()
 	
-	t.id = "24"
 	t.name = "zip_export_plus_clean"
 	t.print_result()
 	return t
--- a/sbsv2/raptor/test/smoke_suite/zip_export_what.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/smoke_suite/zip_export_what.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -26,14 +26,14 @@
 	t = CheckWhatSmokeTest()
 	t.id = "25"
 	t.name = "zip_export_what"
-	t.command = "sbs --what " + \
-			"-b smoke_suite/test_resources/simple_zip_export/bld.inf"
+	t.command = "sbs --what -b smoke_suite/test_resources/simple_zip_export/bld.inf"
 	t.stdout = [
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile1.txt',
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile2.txt',
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt',
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt',
-		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin"
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin",
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt"
 	]
 	
 	t.targets = [
@@ -42,6 +42,7 @@
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile3.txt',
 		'$(EPOCROOT)/epoc32/testunzip/archive/archivefile4.txt',
 		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilelinuxbin",
+		"$(EPOCROOT)/epoc32/testunzip/archive/archivefilereadonly.txt",
 		"$(EPOCROOT)/epoc32/build/" + markerfile
 	]
 	t.run()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/unit_suite/data/html_filter/config/logfile_regex.csv	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,65 @@
+priority,regex,description
+CRITICAL,.*Error:.*mingw_make\.exe.*,
+ERROR,.*\: cannot create regular file.*,
+ERROR,.*\): Missing file:.*,
+ERROR,(?:(?:\s*\d+\)\s*)|(?:\s*\*\*\*\s*))ERROR:.*,
+ERROR,.*is not recognized as an internal or external command.*,
+ERROR,MISSING:.*,
+ERROR,.*FLEXlm error:.*,
+ERROR,.*(ABLD|BLDMAKE)\s*ERROR:.*,
+ERROR,.*FATAL ERROR\(S\):.*,
+ERROR,.*fatal error C1001: INTERNAL COMPILER ERROR.*,
+ERROR,.*fatal error U1077.*,
+ERROR,^fatal error.*,
+ERROR,.*warning U4010.*,
+ERROR,make(?:\.exe)?\s*(?:\[\d+\])\s*?\:\s*\*\*\*.*,
+ERROR,make(?:\.exe)(?:\[\d+\])?\:.*\s+not\s+remade.*,
+ERROR,make(?:\.exe)\s*:\s*\*\*\*.*\s*[Nn]o rule.*,
+ERROR,"\""(?:.*)\"" , line (\d+): (Error: +(.\d+.*?):.*)",
+ERROR,error: ((Internal fault):.*)$,
+ERROR,.*Exception: STATUS_ACCESS_VIOLATION.*,
+ERROR,.*target .* given more than once in the same rule.*,
+ERROR,ERROR:.*,
+ERROR,Error:.*,
+ERROR,ERROR\t.*,
+ERROR,^.*\s*elf2e32\s*:\s*Error\s*:\s*,
+ERROR,.*[Nn]o such file or directory\s*.*,
+ERROR,Exception: [A-Z0-9_]+.*,
+ERROR,.*target .* given more than once in the same rule.*,
+ERROR,ERROR EC\d+:.*,
+ERROR,Errors caused tool to abort..*,
+ERROR,ERROR\t.*,
+ERROR,.*Traceback \(most recent call last\).*,
+ERROR,Application encountered an unexpected error\.\s*Stopping\.\s*,
+ERROR,Unable to write dump file .+,
+ERROR,Unable to connect to CM: .*,
+ERROR,.*: Incorrect slash in .*,
+ERROR,.*: Incorrect case for epoc32 tree in .*,
+ERROR,.*: Incorrect case versus exclusion list in .*,
+ERROR,The system cannot find the path specified.*,
+CRITICAL,.*[Ww]arning:?\s+(#111-D|#1166-D|#117-D|#128-D|#1293-D|#1441-D|#170-D|#174-D|#175-D|#185-D|#186-D|#223-D|#231-D|#257-D|#284-D|#368-D|#414-D|#430-D|#47-D|#514-D|#546-D|#68-D|#69-D|#830-D|#940-D|#836-D|A1495E|L6318W|C2874W|C4127|C4355|C4530|C4702|C4786|LNK4049).*,
+WARNING,(\d+\))?\s.*WARNING:.*,
+WARNING,(BLDMAKE |MAKEDEF )?WARNING:.*,
+WARNING,.*\(\d+\) : warning C.*,
+WARNING,.*\d+: warning:.*,
+WARNING,.*Usage Warning:.*,
+WARNING,.*mwld.exe:.*,
+WARNING,Command line warning.*,
+WARNING,.*ERROR: bad relocation:.*,
+WARNING,(\d+) warning.*,
+WARNING,.*EventType:\s+Error\s+Source:\s+SweepNT.*,
+WARNING,WARN\t.*,
+WARNING,.*LINK : warning.*,
+WARNING,.*\s*elf2e32\s*:\s*Warning\s*:\s*,
+WARNING,Warning:.*,
+REMARK,"\"".*\""\, line \d+: Warning: +(.\d+.*?):.*",
+REMARK,.*Command line warning D4025 : .*,
+REMARK,REMARK: .*,
+REMARK,EventType:\s+Error\s+Source:\s+GNU\s+Make.*,
+REMARK,".*:\d+: warning: cannot find matching deallocation function.*",
+REMARK,(:\d+)*: note: .*,
+INFO,INFO:.*,
+WARNING,"line \d+: Warning:'\, r':\s+warning\s+\w+:.*",
+WARNING,"\""(.*)\""\, line (\d+): (Warning: +(?!A1495E)(.\d+.*?):.*)",
+WARNING,Warning\s*:\s*.*,
+ERROR,.*Error\s*:\s*.*,
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/unit_suite/data/html_filter/style/filter_html.css	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,35 @@
+body
+{
+	font-family: monospace;
+}
+
+pre { background: #cccccc; }
+
+table
+{
+	width: 100%;
+	border: 1px solid black;
+}
+
+th.numbers
+{
+	width: 10%;
+}
+
+td
+{
+	text-align: center;
+}
+
+td.name
+{
+	text-align: left;
+}
+td.time { background: #80ff80; }
+td.ok { background: #80ff80; }
+td.error { background: #ff8080; }
+td.critical { background: #ffc080; }
+td.warning { background: #ffff80; }
+td.remark { background: #8080ff; }
+td.missing { background: #c0c0c0; }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/unit_suite/filter_html_unit.py	Mon Sep 13 14:04:04 2010 +0100
@@ -0,0 +1,88 @@
+
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of the License "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+
+'''
+Test the HTML class in plugins/filter_html.py
+'''
+
+import os
+import shutil
+import sys
+import unittest
+
+test_data = os.path.join(os.getcwd(),"unit_suite","data","html_filter")
+
+# add the plugins directory to the python path
+sys.path.append(os.path.join(os.environ['SBS_HOME'], "python", "plugins"))
+# so that we can import the filter module directly
+import filter_html
+import generic_path
+
+class Mock(object):
+	'''empty object for attaching arbitrary attributes and functions.'''
+	pass
+	
+class TestFilterHtml(unittest.TestCase):
+	'''test cases for the HTML log filter.
+	
+	This is a minimal set of tests for starters. As people start using this
+	filter and reporting bugs and niggles we can add test cases here to
+	avoid regressions.'''
+	
+	def setUp(self):
+		self.mock_params = Mock()
+		self.mock_params.configPath = [generic_path.Path("config")]
+		self.mock_params.home = generic_path.Path(test_data)
+		self.mock_params.logFileName = generic_path.Path("tmp/foo")
+		self.mock_params.timestring = "now"
+		
+		# where do we expect the output to be written
+		self.html_dir = str(self.mock_params.logFileName) + "_html"
+		
+	def tearDown(self):
+		'''remove all the generated output files and directories.'''
+		if os.path.isdir(self.html_dir):
+			shutil.rmtree(self.html_dir)
+	
+	def testPass(self):
+		'''are the setUp and tearDown methods sane.'''
+		pass
+	
+	def testConstructor(self):
+		'''simply construct an HTML object.'''
+		html = filter_html.HTML()
+
+	def testMinimalLog(self):
+		'''process a minimal log file.'''
+		html = filter_html.HTML()
+		self.assertTrue( html.open(self.mock_params) )
+		self.assertTrue( html.write('<?xml version="1.0" encoding="ISO-8859-1" ?>\n') )
+		self.assertTrue( html.write('<buildlog sbs_version="2.99.9 [hi]">') )
+		self.assertTrue( html.write('</buildlog>') )
+		self.assertTrue( html.close() )
+		
+		self.assertTrue( os.path.isfile(self.html_dir + "/index.html") )
+		self.assertTrue( os.path.isfile(self.html_dir + "/style.css") )
+		
+# run all the tests
+
+from raptor_tests import SmokeTest
+
+def run():
+	t = SmokeTest()
+	t.name = "filter_html_unit"
+
+	tests = unittest.makeSuite(TestFilterHtml)
+	result = unittest.TextTestRunner(verbosity=2).run(tests)
+
+	if result.wasSuccessful():
+		t.result = SmokeTest.PASS
+	else:
+		t.result = SmokeTest.FAIL
+
+	return t
--- a/sbsv2/raptor/test/unit_suite/raptor_unit.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/unit_suite/raptor_unit.py	Mon Sep 13 14:04:04 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -108,7 +108,8 @@
 			if len(c.specs) > 0: 
 				# something will be built from this component because
 				# it has at least one spec
-				shortname = str(c.bldinf_filename)[len(os.environ['SBS_HOME'])+1:]
+				sbsHome = os.environ['SBS_HOME'].rstrip('\\/')
+				shortname = str(c.bldinf_filename)[len(sbsHome)+1:]
 				self.assertTrue(shortname in expected_spec_output)
 				hits += 1
 
--- a/sbsv2/raptor/test/unit_suite/raptor_xml_unit.py	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/test/unit_suite/raptor_xml_unit.py	Mon Sep 13 14:04:04 2010 +0100
@@ -122,9 +122,9 @@
 		self.assertTrue(systemModel.IsLayerBuildable("Seventh Layer"))
 		self.assertTrue(len(self.__logger.errors) == 1)
 		sbsHome = os.environ["SBS_HOME"]
-		sysDefPath = sbsHome + "/test/metadata/system/system_definition_multi_layers.xml"
+		sysDefPath = os.path.join(sbsHome, "test/metadata/system/system_definition_multi_layers.xml")
 		sysDefPath = sysDefPath.replace("\\","/")
-		bldInfPath = sbsHome + "/test/smoke_suite/test_resources/does_not_exist/bld.inf"
+		bldInfPath = os.path.join(sbsHome, "test/smoke_suite/test_resources/does_not_exist/bld.inf")
 		bldInfPath = bldInfPath.replace("\\","/")
 		self.assertEquals(self.__logger.errors[0],
 		  ("System Definition layer \"Seventh Layer\" from system definition file \"%s\" refers to non existent bld.inf file %s" % (sysDefPath, bldInfPath)))
--- a/sbsv2/raptor/util/python.mk	Mon Sep 13 13:11:19 2010 +0800
+++ b/sbsv2/raptor/util/python.mk	Mon Sep 13 14:04:04 2010 +0100
@@ -36,7 +36,7 @@
 	tar -xjf $(PYTHON_TAR) && \
 	(  \
 	cd $(PYTHON_SOURCEDIR) && \
-	CFLAGS="-O3 $(GCCTUNE) -s" ./configure --prefix=$(PYINSTALLROOT) --enable-shared --with-threads && \
+	CFLAGS="-O3 $(GCCTUNE) -s" ./configure --prefix=$(PYINSTALLROOT) --enable-shared --with-threads --enable-bzip2 && \
 	$(MAKE) -j8 && $(MAKE) install \
 	)