catch up to 2.11.2 from fix wip
authorRichard Taylor <richard.i.taylor@nokia.com>
Fri, 11 Dec 2009 14:08:26 +0000
branchwip
changeset 78 796529273552
parent 77 4f372f7e27f5 (diff)
parent 42 0785cc0c667b (current diff)
child 79 540de0f551cf
catch up to 2.11.2 from fix
sbsv2/raptor/RELEASE-NOTES.txt
--- a/sbsv2/raptor/RELEASE-NOTES.txt	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/RELEASE-NOTES.txt	Fri Dec 11 14:08:26 2009 +0000
@@ -1,6 +1,12 @@
 
 Release Notes for Symbian Build System v2
 
+Next version
+
+Other Changes:
+Combine Linking and Postlinking into a single step
+
+
 version 2.11.2
 
 Defect Fixes:
--- a/sbsv2/raptor/lib/config/variants.xml	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/lib/config/variants.xml	Fri Dec 11 14:08:26 2009 +0000
@@ -187,7 +187,6 @@
 		<set name="OWN_LIBRARY_OPTION" value="--library_interface=aeabi_clib"/>
 		<set name="RELOCATABLE_IMAGE_OPTION" value=""/>
 		<set name="SPLIT_OPTION" value=""/>
-		<set name="STDLIB_OPTION" value=""/>
 		<set name="PLATMACROS.VAR" value="ARMCC_4 ARMCC_4_0"/>
 		<set name="ARMMACROS.VAR" value="__ARMCC_4__ __ARMCC_4_0__"/>
 		<set name="SYMBIAN_LINK_FLAGS.VAR" value="--override_visibility"/>
--- a/sbsv2/raptor/lib/flm/e32abiv2.flm	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/lib/flm/e32abiv2.flm	Fri Dec 11 14:08:26 2009 +0000
@@ -384,7 +384,24 @@
 # Generating the import library is enough if TARGETTYPE=implib #############
 
 ifneq ($(DOPOSTLINK),)
-include $(FLMHOME)/e32postlink.mk
+# Capabilities
+ADDED_CAPABILITIES:=$(subst $(CHAR_SPACE),+,$(filter-out -%,$(CAPABILITY)))
+SUBTRACTED_CAPABILITIES:=$(subst $(CHAR_SPACE),,$(filter -%,$(CAPABILITY)))
+FINAL_CAPABILITIES:=$(if $(ADDED_CAPABILITIES),$(ADDED_CAPABILITIES)$(SUBTRACTED_CAPABILITIES),NONE)
+
+# Paging options for the old postlinker
+POSTLINKER_PAGEDOPTION:=--defaultpaged
+ifeq ($(PAGED),1)
+  POSTLINKER_PAGEDOPTION:=--paged
+endif
+ifeq ($(PAGED),0)
+  POSTLINKER_PAGEDOPTION:--unpaged
+endif
+
+CLEANTARGETS:=$(CLEANTARGETS) $(E32TARGET)
+CLEANTARGETS:=$(CLEANTARGETS) $(GENERATED_DEFFILE)
+CLEANTARGETS:=$(CLEANTARGETS) $(GENERATED_DSO)
+
 endif # ifneq ($(DOPOSTLINK),)
 
 ifneq ($(TARGETTYPE),implib)
@@ -592,10 +609,10 @@
 # outside the relevant tags but it is also unavoidable.
 define linktarget_func
 ## The actual link target, dependencies and build step
-$(LINK_TARGET): $(if $(MULTIFILE_ENABLED),$(MULTIFILEOBJECT) $(CIAFILES_LINKOBJECTS),$(LINKOBJECTS)) $(escaped_e32abiv2_LIBS) $(LINKER_ENTRYPOINT_LIBDEP) $(if $(SUPPORTS_STDCPP_NEWLIB),$(CHECKLIB)) $(if $(LINKERFEEDBACK_STAGE2),$(FEEDBACKFILE),)
+$(E32TARGET): $(POSTLINKDEFFILE) $(ELF2E32) $(if $(MULTIFILE_ENABLED),$(MULTIFILEOBJECT) $(CIAFILES_LINKOBJECTS),$(LINKOBJECTS)) $(escaped_e32abiv2_LIBS) $(LINKER_ENTRYPOINT_LIBDEP) $(if $(SUPPORTS_STDCPP_NEWLIB),$(CHECKLIB)) $(if $(LINKERFEEDBACK_STAGE2),$(FEEDBACKFILE),) $(if $(HAVE_ORDERONLY),|,) $(EPOCROOT)/epoc32/build/TEM_LIB
 	$(if $(MULTIFILE_ENABLED),,@echo -n "" > $(VIAFILE);
 	$(call groupin10,$(LINKOBJECTS)) ;)
-	$(call startrule,link) \
+	$(call startrule,linkandpostlink) \
 	$(if $(PERTURBSTARTTIME),$(RANSLEEP) $(PERTURBMSECS) ;,) \
 	$(if $(SUPPORTS_STDCPP_NEWLIB),$(if $(located_STATICLIBRARIES),$(CHECKLIB) $(CHECKLIB_TYPE) --elf $(call dblquote,$(located_STATICLIBRARIES)) &&,),) \
 	$(LD) $(LINKER_MISC_FLAGS) $(LINKER_DEFAULT_LIB_PATHS) $(SYMBIAN_LINK_FLAGS) $(if $(DEBUG_INFO),$(LINKER_DEBUG_OPTION),$(LINKER_NODEBUG_OPTION)) \
@@ -605,19 +622,61 @@
 	  $(LINKER_ARCH_OPTION) \
 	  $(SYMVER_OPTION) $(SO_NAME_OPTION)=$(call dblquote,$(LINKASVERSIONED)) \
 	  $(LINKER_ENTRYPOINT_SETTING) \
-	  -o $$(call dblquote,$$@) \
+	  -o $$(call dblquote,$(LINK_TARGET)) \
 	  $(if $(LTCG),$(LTCG_OPTION),) \
 	  $(LINKER_SYMBOLS_OPTION) $(LINKER_SYMBOLS_FILE_OPTION)=$(call dblquote,$(MAPFILE)) \
   	  $(LINKEROPTION) \
 	  $(if $(MULTIFILE_ENABLED),$(call dblquote,$(MULTIFILEOBJECT) $(CIAFILES_LINKOBJECTS)),$(COMMANDFILE_OPTION)$(call dblquote,$(VIAFILE))) \
-          $(if $(GENERATELINKERFEEDBACK),$(FEEDBACK_OPTION)$(call dblquote,$(FEEDBACKFILE))) \
+      $(if $(GENERATELINKERFEEDBACK),$(FEEDBACK_OPTION)$(call dblquote,$(FEEDBACKFILE))) \
 	  $(if $(LINKER_ADD_STATIC_RUNTIME),$(if $(STATIC_RUNTIME_LIB),$(LINKER_GROUP_START_OPTION) $(STATIC_RUNTIME_DIR)/$(STATIC_RUNTIME_LIB) $(LINKER_GROUP_END_OPTION),)) \
-	  $(quoted_e32abiv2_LIBS) $(LINKER_DEFAULT_LIBS)\
-	$(call endrule,link)
+	  $(quoted_e32abiv2_LIBS) $(LINKER_DEFAULT_LIBS) && \
+	  $(ELF2E32) \
+	  --sid=0x$(if $(SID),$(SID),$(if $(UID3),$(UID3),0)) \
+	  --version=$(VERSION) \
+	  --capability=$(FINAL_CAPABILITIES) \
+	  --linkas=$(call dblquote,$(LINKASVERSIONED)) \
+	  --fpu=$(if $(ARMFPU),$(ARMFPU),$(POSTLINKER_FPU_DEFAULT)) \
+	  --targettype=$(POSTLINKTARGETTYPE) \
+	  --output=$$(call dblquote,$$@) \
+	  --elfinput=$(call dblquote,$(LINK_TARGET)) \
+	  $(if $(UID1),--uid1=0x$(UID1),) \
+	  $(if $(UID2),--uid2=0x$(UID2),) \
+	  $(if $(UID3),--uid3=0x$(UID3),) \
+	  $(if $(VENDORID),--vid=0x$(VENDORID),) \
+	  $(if $(EXPTARGET),--customdlltarget,) \
+	  $(if $(ARMLIBS),--excludeunwantedexports,) \
+	  $(if $(EPOCALLOWDLLDATA),--dlldata,) \
+	  $(if $(EPOCPROCESSPRIORITY),--priority=$(EPOCPROCESSPRIORITY),) \
+	  $(if $(EPOCSTACKSIZE),--stack=0x$(EPOCSTACKSIZE),) \
+	  $(if $(EPOCHEAPSIZEMIN),--heap=0x$(EPOCHEAPSIZEMIN)$(CHAR_COMMA)0x$(EPOCHEAPSIZEMAX),) \
+	  $(if $(EPOCFIXEDPROCESS),--fixedaddress,) \
+	  $(if $(EPOCDATALINKADDRESS),--datalinkaddress=$(EPOCDATALINKADDRESS),) \
+	  $(if $(NAMEDSYMLKUP),--namedlookup,) \
+	  $(if $(SMPSAFE),--smpsafe,) \
+	  $(if $(POSTLINKDEFFILE),--definput=$(POSTLINKDEFFILE),) \
+	  $(if $(EXPORTUNFROZEN),--unfrozen,) \
+	  $(if $(AUTOEXPORTS),--sysdef=$(call dblquote,$(AUTOEXPORTS)),) \
+	  $(if $(CANIGNORENONCALLABLE), \
+	    $(if $(IMPORTLIBRARYREQUIRED),,--ignorenoncallable),) \
+	  $(if $(CANHAVEEXPORTS), --defoutput=$(call dblquote,$(GENERATED_DEFFILE)) --dso=$(GENERATED_DSO)) \
+	  $(if $(filter $(VARIANTTYPE),$(DEBUGGABLE)),--debuggable,) \
+	  $(if $(POSTLINKER_SUPPORTS_WDP), \
+	    --codepaging=$(PAGEDCODE_OPTION) --datapaging=$(PAGEDDATA_OPTION), \
+	    $(POSTLINKER_PAGEDOPTION)) \
+	  $(if $(NOCOMPRESSTARGET),--uncompressed, \
+	    $(if $(INFLATECOMPRESSTARGET),--compressionmethod=inflate, \
+	      $(if $(BYTEPAIRCOMPRESSTARGET),--compressionmethod=bytepair, \
+	        --compressionmethod=$(POSTLINKER_COMPRESSION_DEFAULT)))) \
+	  --libpath="$(call concat,$(PATHSEP)$(CHAR_SEMIC),$(strip $(RUNTIME_LIBS_PATH) $(STATIC_LIBS_PATH)))" \
+	  $(if $(SAVESPACE),$(if $(EXPORTUNFROZEN),,&& { $(GNURM) -rf $(INTERMEDIATEPATH); true; })) \
+	$(call endrule,linkandpostlink)
 
-$(MAPFILE): $(LINK_TARGET)
+$(MAPFILE): $(E32TARGET)
+$(LINK_TARGET): $(E32TARGET)
 endef
+ifneq ($(DOPOSTLINK),)
 $(eval $(linktarget_func))
+endif # ifneq ($(DOPOSTLINK),)
 
 CLEANTARGETS:=$(CLEANTARGETS) $(VIAFILE) $(if $(GENERATELINKERFEEDBACK),$(FEEDBACKFILE)) $(if $(MULTIFILE_ENABLED),$(MULTIFILEOBJECT))
 WHATRELEASE:=$(WHATRELEASE) $(MAPFILE)
--- a/sbsv2/raptor/lib/flm/e32postlink.mk	Thu Dec 10 14:00:35 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-#
-# Copyright (c) 2009 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: 
-# ARMv5 e32 postlinking FLM
-# Knows how to postlink all possible ABIV2 executables for ARM
-#
-
-# Interface
-#
-#  Metadata supplied (or deduced from)
-#
-#   ARMFPU
-#   BYTEPAIRCOMPRESSTARGET
-#   CAPABILITY
-#   COMPRESSTARGET                    Not directly referenced, at least with the current approach to compression keywords
-#   DEBUGGABLE                        Can be "udeb" or "urel" or "udeb urel" or ""
-#   E32TARGET
-#   EPOCALLOWDLLDATA
-#   EPOCFIXEDPROCESS
-#   EPOCHEAPSIZEMAX
-#   EPOCHEAPSIZEMIN
-#   EPOCPROCESSPRIORITY
-#   EPOCSTACKSIZE
-#   EXPORTUNFROZEN
-#   INFLATECOMPRESSTARGET
-#   NOCOMPRESSTARGET
-#   POSTLINKTARGETTYPE
-#   SID
-#   SMPSAFE
-#   UID2
-#   UID3
-#   VERSION
-#   VENDORID
-#
-#  Other
-#
-#   ARMLIBS
-#   AUTOEXPORTS                       Symbols that must be assumed to exist for this TARGETTYPE in the format: export,ordinal;export,ordinal;..
-#   CANIGNORENONCALLABLE              If the TARGETTYPE allows it, disregard non-callable exports (v-tables, type information, etc.)
-#   CANHAVEEXPORTS
-#   CLEANTARGETS
-#   ELF2E32
-#   EPOCDATALINKADDRESS               Redundant?
-#   EPOCROOT
-#   EXPTARGET
-#   GENERATED_DEFFILE
-#   GENERATED_DSO
-#   HAVE_ORDERONLY
-#   IMPORTLIBRARYREQUIRED
-#   INTERMEDIATEPATH
-#   LINKASVERSIONED
-#   LINK_TARGET                       Postlinker elf input
-#   NAMEDSYMLKUP
-#   PAGEDCODE_OPTION
-#   POSTLINKDEFFILE
-#   POSTLINKER_COMPRESSION_DEFAULT    Default compression when either COMPRESSTARGET or no compression .mmp keyword is used
-#   POSTLINKER_FPU_DEFAULT
-#   POSTLINKER_SUPPORTS_WDP
-#   RUNTIME_LIBS_PATH
-#   SAVESPACE
-#   STATIC_LIBS_PATH
-#   UID1
-#   VARIANTTYPE
-
-
-# Capabilities
-ADDED_CAPABILITIES:=$(subst $(CHAR_SPACE),+,$(filter-out -%,$(CAPABILITY)))
-SUBTRACTED_CAPABILITIES:=$(subst $(CHAR_SPACE),,$(filter -%,$(CAPABILITY)))
-FINAL_CAPABILITIES:=$(if $(ADDED_CAPABILITIES),$(ADDED_CAPABILITIES)$(SUBTRACTED_CAPABILITIES),NONE)
-
-# Paging options for the old postlinker
-POSTLINKER_PAGEDOPTION:=--defaultpaged
-ifeq ($(PAGED),1)
-  POSTLINKER_PAGEDOPTION:=--paged
-endif
-ifeq ($(PAGED),0)
-  POSTLINKER_PAGEDOPTION:--unpaged
-endif
-
-# Postlink target
-define e32postlink
-$(E32TARGET): $(LINK_TARGET) $(POSTLINKDEFFILE) $(ELF2E32) $(if $(HAVE_ORDERONLY),|,) $(EPOCROOT)/epoc32/build/TEM_LIB
-	$(call startrule,postlink) \
-	$(ELF2E32) \
-	  --sid=0x$(if $(SID),$(SID),$(if $(UID3),$(UID3),0)) \
-	  --version=$(VERSION) \
-	  --capability=$(FINAL_CAPABILITIES) \
-	  --linkas=$(call dblquote,$(LINKASVERSIONED)) \
-	  --fpu=$(if $(ARMFPU),$(ARMFPU),$(POSTLINKER_FPU_DEFAULT)) \
-	  --targettype=$(POSTLINKTARGETTYPE) \
-	  --output=$$(call dblquote,$$@) \
-	  --elfinput=$(call dblquote,$(LINK_TARGET)) \
-	  $(if $(UID1),--uid1=0x$(UID1),) \
-	  $(if $(UID2),--uid2=0x$(UID2),) \
-	  $(if $(UID3),--uid3=0x$(UID3),) \
-	  $(if $(VENDORID),--vid=0x$(VENDORID),) \
-	  $(if $(EXPTARGET),--customdlltarget,) \
-	  $(if $(ARMLIBS),--excludeunwantedexports,) \
-	  $(if $(EPOCALLOWDLLDATA),--dlldata,) \
-	  $(if $(EPOCPROCESSPRIORITY),--priority=$(EPOCPROCESSPRIORITY),) \
-	  $(if $(EPOCSTACKSIZE),--stack=0x$(EPOCSTACKSIZE),) \
-	  $(if $(EPOCHEAPSIZEMIN),--heap=0x$(EPOCHEAPSIZEMIN)$(CHAR_COMMA)0x$(EPOCHEAPSIZEMAX),) \
-	  $(if $(EPOCFIXEDPROCESS),--fixedaddress,) \
-	  $(if $(EPOCDATALINKADDRESS),--datalinkaddress=$(EPOCDATALINKADDRESS),) \
-	  $(if $(NAMEDSYMLKUP),--namedlookup,) \
-	  $(if $(SMPSAFE),--smpsafe,) \
-	  $(if $(POSTLINKDEFFILE),--definput=$(POSTLINKDEFFILE),) \
-	  $(if $(EXPORTUNFROZEN),--unfrozen,) \
-	  $(if $(AUTOEXPORTS),--sysdef=$(call dblquote,$(AUTOEXPORTS)),) \
-	  $(if $(CANIGNORENONCALLABLE), \
-	    $(if $(IMPORTLIBRARYREQUIRED),,--ignorenoncallable),) \
-	  $(if $(CANHAVEEXPORTS), --defoutput=$(call dblquote,$(GENERATED_DEFFILE)) --dso=$(GENERATED_DSO)) \
-	  $(if $(filter $(VARIANTTYPE),$(DEBUGGABLE)),--debuggable,) \
-	  $(if $(POSTLINKER_SUPPORTS_WDP), \
-	    --codepaging=$(PAGEDCODE_OPTION) --datapaging=$(PAGEDDATA_OPTION), \
-	    $(POSTLINKER_PAGEDOPTION)) \
-	  $(if $(NOCOMPRESSTARGET),--uncompressed, \
-	    $(if $(INFLATECOMPRESSTARGET),--compressionmethod=inflate, \
-	      $(if $(BYTEPAIRCOMPRESSTARGET),--compressionmethod=bytepair, \
-	        --compressionmethod=$(POSTLINKER_COMPRESSION_DEFAULT)))) \
-	  --libpath="$(call concat,$(PATHSEP)$(CHAR_SEMIC),$(strip $(RUNTIME_LIBS_PATH) $(STATIC_LIBS_PATH)))" \
-	  $(if $(SAVESPACE),$(if $(EXPORTUNFROZEN),,&& { $(GNURM) -rf $(INTERMEDIATEPATH); true; })) \
-	$(call endrule,postlink)
-endef
-$(eval $(e32postlink))
-
-CLEANTARGETS:=$(CLEANTARGETS) $(E32TARGET)
-CLEANTARGETS:=$(CLEANTARGETS) $(GENERATED_DEFFILE)
-CLEANTARGETS:=$(CLEANTARGETS) $(GENERATED_DSO)
--- a/sbsv2/raptor/python/plugins/filter_terminal.py	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/python/plugins/filter_terminal.py	Fri Dec 11 14:08:26 2009 +0000
@@ -113,6 +113,7 @@
 		"asmcompile" : "asmcompile" ,
 		"compile" : "compile" ,
 		"postlink" : "target",
+		"linkandpostlink" : "target",
 		"resourcecompile" : "resource",
 		"genstringtable" : "strtable",
 		"tem" : "tem",
--- a/sbsv2/raptor/python/raptor.py	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/python/raptor.py	Fri Dec 11 14:08:26 2009 +0000
@@ -11,7 +11,7 @@
 #
 # Contributors:
 #
-# Description: 
+# Description:
 # raptor module
 # This module represents the running Raptor program. Raptor is started
 # either by calling the Main() function, which creates an instance of
@@ -119,7 +119,7 @@
 		self.type = type
 		self.specs = []
 		self.deps = []
-		self.children = set() 
+		self.children = set()
 		self.unfurled = False
 		self.parent = parent
 
@@ -163,15 +163,15 @@
 
 		for c in self.children:
 			c.unfurl_all(build)
-		
+
 
 	def realise_exports(self, build):
-		"""Do the things that are needed such that we can fully unfurl all 
+		"""Do the things that are needed such that we can fully unfurl all
 		   sibling nodes.  i.e. this step is here to "take care" of the dependencies
-		   between siblings.  
+		   between siblings.
 		"""
 		pass
-	
+
 	def realise_makefile(self, build, specs):
 		makefilename_base = build.topMakefile
 		if self.name is not None:
@@ -190,16 +190,16 @@
 				key = str(makefile.path))
 
 		return makefileset
-		
+
 
 
 	def realise(self, build):
-		"""Give the spec trees to the make engine and actually 
-		"build" the product represented by this model node"""	
+		"""Give the spec trees to the make engine and actually
+		"build" the product represented by this model node"""
 		# Must ensure that all children are unfurled at this point
 		self.unfurl_all(build)
 
-		sp = self.specs	
+		sp = self.specs
 
 		build.AssertBuildOK()
 
@@ -210,8 +210,8 @@
 		result = build.Make(m)
 		build.InfoEndTime(object_type = "layer", task = "build",
 				key = (str(m.directory) + "/" + str(m.filenamebase)))
-		
-		
+
+
 		return result
 
 
@@ -229,7 +229,7 @@
 
 	def makefile(self, makefilename_base, engine, named = False):
 		"""Makefiles for individual mmps not feasible at the moment"""
-		pass # Cannot, currently, "unfurl an mmp" directly but do want 
+		pass # Cannot, currently, "unfurl an mmp" directly but do want
 		     # to be able to simulate the overall recursive unfurling of a build.
 
 class Component(ModelNode):
@@ -252,9 +252,9 @@
 
 
 class Layer(ModelNode):
-	""" 	Some components that should be built togther 
-		e.g. a Layer in the system definition. 
-	""" 
+	""" 	Some components that should be built togther
+		e.g. a Layer in the system definition.
+	"""
 	def __init__(self, name, componentlist=[]):
 		super(Layer,self).__init__(name)
 		self.name = name
@@ -263,11 +263,11 @@
 			self.children.add(Component(c))
 
 	def unfurl(self, build):
-		"""Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps). 
+		"""Discover the children of this layer. This involves parsing the component MetaData (bld.infs, mmps).
 		Takes a raptor object as a parameter (build), together with a list of Configurations.
 
 		We currently have parsers that work on collections of components/bld.infs and that cannot
-		parse at a "finer" level.  So one can't 'unfurl' an mmp at the moment.  
+		parse at a "finer" level.  So one can't 'unfurl' an mmp at the moment.
 
 		Returns True if the object was successfully unfurled.
 		"""
@@ -300,7 +300,7 @@
 	def meta_realise(self, build):
 		"""Generate specs that can be used to "take care of" finding out more
 		about this metaunit - i.e. one doesn't want to parse it immediately
-		but to create a makefile that will parse it. 
+		but to create a makefile that will parse it.
 		In this case it allows bld.infs to be parsed in parallel by make."""
 
 		# insert the start time into the Makefile name?
@@ -310,44 +310,44 @@
 
 		# Pass certain CLI flags through to the makefile-generating sbs calls
 		cli_options = ""
-			
+
 		if build.debugOutput == True:
 			cli_options += " -d"
-				
+
 		if build.ignoreOsDetection == True:
 			cli_options += " -i"
-			
+
 		if build.keepGoing == True:
 			cli_options += " -k"
-			
+
 		if build.quiet == True:
 			cli_options += " -q"
-			
+
 		if build.timing == True:
 			cli_options += " --timing"
 
-		
+
 		nc = len(self.children)
 		number_blocks = build.jobs
 		block_size = (nc / number_blocks) + 1
 		component_blocks = []
 		spec_nodes = []
-		
+
 		b = 0
 		childlist = list(self.children)
 		while b < nc:
 			component_blocks.append(childlist[b:b+block_size])
 			b += block_size
-			
+
 		while len(component_blocks[-1]) <= 0:
 			component_blocks.pop()
 			number_blocks -= 1
-	
+
 		build.Info("Parallel Parsing: bld.infs split into %d blocks\n", number_blocks)
-		# Cause the binding makefiles to have the toplevel makefile's 
-		# name.  The bindee's have __pp appended.	
+		# Cause the binding makefiles to have the toplevel makefile's
+		# name.  The bindee's have __pp appended.
 		tm = build.topMakefile.Absolute()
-		binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File()))		
+		binding_makefiles = raptor_makefile.MakefileSet(str(tm.Dir()), build.maker.selectors, makefiles=None, filenamebase=str(tm.File()))
 		build.topMakefile = generic_path.Path(str(build.topMakefile) + "_pp")
 
 		loop_number = 0
@@ -357,16 +357,16 @@
 
 			componentList = " ".join([str(c.bldinf_filename) for c in block])
 
-			
+
 			configList = " ".join([c.name for c in self.configs if c.name != "build" ])
-			
+
 			makefile_path = str(build.topMakefile) + "_" + str(loop_number)
 			try:
 				os.unlink(makefile_path) # until we have dependencies working properly
 			except Exception,e:
 				# print "couldn't unlink %s: %s" %(componentMakefileName, str(e))
 				pass
-			
+
 			# add some basic data in a component-wide variant
 			var = raptor_data.Variant()
 			var.AddOperation(raptor_data.Set("COMPONENT_PATHS", componentList))
@@ -385,13 +385,13 @@
 			if build.noBuild:
 				var.AddOperation(raptor_data.Set("NO_BUILD", "1"))
 			specNode.AddVariant(var)
-	
+
 			try:
 				interface = build.cache.FindNamedInterface("build.makefiles")
 				specNode.SetInterface(interface)
 			except KeyError:
 				build.Error("Can't find flm interface 'build.makefiles' ")
-				
+
 			spec_nodes.append(specNode)
 			binding_makefiles.addInclude(str(makefile_path)+"_all")
 
@@ -430,7 +430,7 @@
 
 
 	M_BUILD = 1
-	M_VERSION = 2	
+	M_VERSION = 2
 
 	def __init__(self, home = None):
 
@@ -554,7 +554,7 @@
 			self.Warn("ignoring target %s because --what or --check is specified.\n", target)
 		else:
 			self.targets.append(target)
-			
+
 	def AddSourceTarget(self, filename):
 		# source targets are sanitised and then added as if they were a "normal" makefile target
 		# in addition they have a default, empty, top-level target assigned in order that they can
@@ -615,7 +615,7 @@
 	def SetNoDependInclude(self, TrueOrFalse):
 		self.noDependInclude = TrueOrFalse
 		return True
-		
+
 	def SetKeepGoing(self, TrueOrFalse):
 		self.keepGoing = TrueOrFalse
 		return True
@@ -669,7 +669,7 @@
 			return False
 
 		return True
-	
+
 	def SetTiming(self, TrueOrFalse):
 		self.timing = TrueOrFalse
 		return True
@@ -717,9 +717,9 @@
 		self.Info("Set-up %s", str(self.raptorXML))
 		self.Info("Command-line-arguments %s", " ".join(self.args))
 		self.Info("Current working directory %s", os.getcwd())
-		
+
 		# the inherited environment
-		for e, value in os.environ.items():
+		for e, value in sorted( os.environ.items() ):
 			self.Info("Environment %s=%s", e, value.replace("]]>", "]]&gt;"))
 
 		# and some general debug stuff
@@ -822,7 +822,7 @@
 				return self.home.Append(aGenericPath)
 			else:
 				return aGenericPath
-		
+
 		# make generic paths absolute (if required)
 		self.configPath = map(mkAbsolute, self.configPath)
 		self.cache.Load(self.configPath)
@@ -859,12 +859,12 @@
 		return x
 
 	def GetBuildUnitsToBuild(self, configNames):
-		"""Return a list of the configuration objects that correspond to the 
+		"""Return a list of the configuration objects that correspond to the
 		   list of configuration names in the configNames parameter.
 
 		raptor.GetBuildUnitsToBuild(["armv5", "winscw"])
 		>>> [ config1, config2, ... , configN ]
-		""" 
+		"""
 
 		if len(configNames) == 0:
 			# use default config
@@ -878,9 +878,9 @@
 
 		for c in set(configNames):
 			self.Debug("BuildUnit: %s", c)
-			try:		
+			try:
 				x = self.GetConfig(c)
-				gb = x.GenerateBuildUnits(self.cache) 
+				gb = x.GenerateBuildUnits(self.cache)
 				buildUnitsToBuild.update( gb )
 			except Exception, e:
 				self.FatalError(str(e))
@@ -894,7 +894,7 @@
 		return buildUnitsToBuild
 
 	def CheckToolset(self, evaluator, configname):
-		"""Check the toolset for a particular config, allow other objects access 
+		"""Check the toolset for a particular config, allow other objects access
 		to the toolset for this build (e.g. the raptor_make class)."""
 		if self.toolset is None:
 			if self.toolcheck == 'on':
@@ -968,7 +968,7 @@
 
 
 	def FindComponentIn(self, aDir = None):
-		# look for a bld.inf 
+		# look for a bld.inf
 
 		if aDir is None:
 			dir = generic_path.CurrentDir()
@@ -1109,14 +1109,14 @@
 		for a,v in dictionary.items():
 			atts += " " + a + "='" + v + "'"
 		return atts
-	
+
 	def Info(self, format, *extras, **attributes):
 		"""Send an information message to the configured channel
 				(XML control characters will be escaped)
 		"""
 		self.out.write("<info" + self.attributeString(attributes) + ">" +
 		               escape(format % extras) + "</info>\n")
-		
+
 	def InfoDiscovery(self, object_type, count):
 		if self.timing:
 			try:
@@ -1124,7 +1124,7 @@
 						count = count))
 			except Exception, exception:
 				Error(exception.Text, function = "InfoDiscoveryTime")
-		
+
 	def InfoStartTime(self, object_type, task, key):
 		if self.timing:
 			try:
@@ -1132,7 +1132,7 @@
 						task = task, key = key))
 			except Exception, exception:
 				Error(exception.Text, function = "InfoStartTime")
-		
+
 	def InfoEndTime(self, object_type, task, key):
 		if self.timing:
 			try:
@@ -1154,7 +1154,7 @@
 		"""Send a warning message to the configured channel
 				(XML control characters will be escaped)
 		"""
-		self.out.write("<warning" + self.attributeString(attributes) + ">" + 
+		self.out.write("<warning" + self.attributeString(attributes) + ">" +
 		               escape(format % extras) + "</warning>\n")
 
 	def FatalError(self, format, *extras, **attributes):
@@ -1165,7 +1165,7 @@
 		   further errors are probably triggered by the first.
 		"""
 		if not self.fatalErrorState:
-			self.out.write("<error" + self.attributeString(attributes) + ">" + 
+			self.out.write("<error" + self.attributeString(attributes) + ">" +
 			               (format % extras) + "</error>\n")
 			self.errorCode = 1
 			self.fatalErrorState = True
@@ -1174,7 +1174,7 @@
 		"""Send an error message to the configured channel
 				(XML control characters will be escaped)
 		"""
-		self.out.write("<error" + self.attributeString(attributes) + ">" + 
+		self.out.write("<error" + self.attributeString(attributes) + ">" +
 		               escape(format % extras) + "</error>\n")
 		self.errorCode = 1
 
@@ -1212,7 +1212,7 @@
 		if self.systemDefinitionFile != None:
 			systemModel = raptor_xml.SystemModel(self, self.systemDefinitionFile, self.systemDefinitionBase)
 			layers = self.GatherSysModelLayers(systemModel, self.systemDefinitionRequestedLayers)
-			
+
 		# Now get components specified on a commandline - build them after any
 		# layers in the system definition.
 		if len(self.commandlineComponents) > 0:
@@ -1246,7 +1246,7 @@
 			self.Introduction()
 			# establish an object cache
 			self.AssertBuildOK()
-			
+
 			self.LoadCache()
 
 			# find out what configurations to build
@@ -1299,7 +1299,7 @@
 				for l in layers:
 					# create specs for a specific group of components
 					l.realise(self)
-					
+
 		except BuildCannotProgressException,b:
 			if str(b) != "":
 				self.Info(str(b))
@@ -1326,7 +1326,7 @@
 		build.ProcessConfig()
 		build.CommandLine(argv)
 
-		return build 
+		return build
 
 
 
--- a/sbsv2/raptor/python/raptor_data.py	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/python/raptor_data.py	Fri Dec 11 14:08:26 2009 +0000
@@ -722,15 +722,23 @@
 	def Apply(self, oldValue):
 		try:
 			value = os.environ[self.name]
-
-			# if this value is a "path" or a "tool" then we need to make sure
-			# it is a proper absolute path in our preferred format.
-			if value and (self.type == "path" or self.type == "tool"):
-				try:
-					path = generic_path.Path(value)
-					value = str(path.Absolute())
-				except ValueError,e:
-					raise BadToolValue("the environment variable %s is incorrect: %s" % (self.name, str(e)))
+			
+			if value:
+				# if this value is a "path" or a "tool" then we need to make sure
+				# it is a proper absolute path in our preferred format.
+				if self.type == "path" or self.type == "tool":
+					try:
+						path = generic_path.Path(value)
+						value = str(path.Absolute())
+					except ValueError,e:
+						raise BadToolValue("the environment variable %s is incorrect: %s" % (self.name, str(e)))				
+				# if this value ends in an un-escaped backslash, then it will be treated as a line continuation character
+				# in makefile parsing - un-escaped backslashes at the end of values are therefore escaped
+				elif value.endswith('\\'):
+					# an odd number of backslashes means there's one to escape
+					count = len(value) - len(value.rstrip('\\'))
+					if count % 2:
+						value += '\\'	
 		except KeyError:
 			if self.default != None:
 				value = self.default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv2/raptor/test/timing_tests/parse_time_exports_mmps.py	Fri Dec 11 14:08:26 2009 +0000
@@ -0,0 +1,77 @@
+
+from raptor_tests import SmokeTest, ReplaceEnvs
+import os
+
+def generate_files():
+	try:
+		os.makedirs(ReplaceEnvs("$(SBS_HOME)/test/timing_tests/test_resources/parse_time"))
+	except:
+		pass
+	bldinf_path = ReplaceEnvs("$(SBS_HOME)/test/timing_tests/test_resources/parse_time/bld.inf")
+	bldinf = open(bldinf_path, "w")
+	bldinf_content = """prj_mmpfiles
+"""
+	test_dir = ReplaceEnvs("$(SBS_HOME)/test/timing_tests/test_resources/parse_time")
+	for number in range(0, 250):
+		mmp_path = ("parse_timing_" + str(number).zfill(3) + ".mmp")
+		mmp_file = open((test_dir + "/" + mmp_path), "w")
+		mmp_file.write("""targettype	none
+""")
+		mmp_file.close()
+		bldinf_content += (mmp_path + "\n")
+		
+	bldinf_content += "\nprj_exports\n"
+
+	for number1 in range(0, 10):
+		source_dir = ("export_source_" + str(number1))
+		try:
+			os.mkdir(test_dir + "/" + source_dir)
+		except:
+			pass
+		
+		for number2 in range (0, 10):
+			source_file = ("/file_" + str(number2) + ".txt ")
+			export_file = open((test_dir + "/" + source_dir + source_file), "w")
+			export_file.write(str(number2))
+			export_file.close()
+			
+			for number3 in range (0, 10):
+				dest_dir = ("epoc32/include/export_destination_" + \
+						str(number1) + str(number2) + str(number3))
+				
+				for number4 in range(0, 10):
+					bldinf_content += source_dir + source_file + dest_dir + \
+							"/export_destination_" + str(number4) + "\n"
+	bldinf.write(bldinf_content)
+	bldinf.close()
+	
+	
+def delete_files():
+	import shutil
+	
+	test_dir = ReplaceEnvs("$(SBS_HOME)/test/timing_tests/test_resources/parse_time")
+	objects = os.listdir(test_dir)
+	for object in objects:
+		object_path = (test_dir + "/" + object)
+		if os.path.isfile(object_path):
+			os.remove(object_path)
+		else:
+			shutil.rmtree(object_path)
+	
+
+def run():
+	
+	generate_files()
+	
+	t = SmokeTest()
+	
+	t.id = "1"
+	t.name = "parse_time_exports_mmps"
+	t.description = """Test to measure time taken to parse a large number of
+			exports and mmps"""
+	t.command = "sbs -b timing_tests/test_resources/parse_time/bld.inf -n " + \
+			"-c armv5_urel --toolcheck=off --timing"
+	t.run()
+	
+	delete_files()
+	return t
--- a/sbsv2/raptor/test/unit_suite/raptor_data_unit.py	Thu Dec 10 14:00:35 2009 +0000
+++ b/sbsv2/raptor/test/unit_suite/raptor_data_unit.py	Fri Dec 11 14:08:26 2009 +0000
@@ -30,24 +30,18 @@
 		
 		
 	def SetEnv(self, name, value):
-		# set environment variable and remember the old value
-		
-		try:
-			old = os.environ[name]
-			self.envStack[name] = old
-			os.environ[name] = value
-		except KeyError:
-			self.envStack[name] = None    # was not defined
+		# set environment variable and remember the old value (if there is one)		
+		if os.environ.has_key(name):
+			self.envStack[name] = os.environ[name]
+		os.environ[name] = value
 		
 			
 	def RestoreEnv(self, name):
 		# put environment back to its state before SetEnv
-		saved = self.envStack[name]
-		
-		if saved == None:
+		if self.envStack.has_key(name):
+			os.environ[name] = self.envStack[name]
+		else:
 			del os.environ[name]    # was not defined
-		else:
-			os.environ[name] = saved
 			
 			
 	def testSimpleSpecification(self):
@@ -359,6 +353,32 @@
 		# test the Resolve wrt EPOCROOT
 		varcfg = eval.Resolve("VARIANT_CFG")
 		self.assertEqual(varcfg, "/C/variant/variant.cfg")
+		
+	def testProblematicEnvironment(self):
+		# ask for environment variable values that will break makefile parsing due to
+		# backslashes forming line continuation characters
+		self.SetEnv("ENVVAR_BSLASH_END1", "C:\\test1a\\;C:\\test1b\\")
+		self.SetEnv("ENVVAR_BSLASH_END2", "C:\\test2a\\;C:\\test2b\\\\")
+		self.SetEnv("ENVVAR_BSLASH_END3", "C:\\test3a\\;C:\\test3b\\\\\\")
+		var = raptor_data.Variant("my.var")
+		var.AddOperation(raptor_data.Env("ENVVAR_BSLASH_END1"))
+		var.AddOperation(raptor_data.Env("ENVVAR_BSLASH_END2"))
+		var.AddOperation(raptor_data.Env("ENVVAR_BSLASH_END3"))
+
+		aRaptor = raptor.Raptor()
+		eval = aRaptor.GetEvaluator(None, var.GenerateBuildUnits(aRaptor.cache)[0])
+		self.RestoreEnv("ENVVAR_BSLASH_END1")
+		self.RestoreEnv("ENVVAR_BSLASH_END2")
+		self.RestoreEnv("ENVVAR_BSLASH_END3")
+		
+		value = eval.Get("ENVVAR_BSLASH_END1")
+		self.assertEqual(value, "C:\\test1a\\;C:\\test1b\\\\")
+		
+		value = eval.Get("ENVVAR_BSLASH_END2")
+		self.assertEqual(value, "C:\\test2a\\;C:\\test2b\\\\")
+		
+		value = eval.Get("ENVVAR_BSLASH_END3")
+		self.assertEqual(value, "C:\\test3a\\;C:\\test3b\\\\\\\\")
 	
 	def testMissingEnvironment(self):
 		# ask for an environment variable that is not set