sbsv1_os/e32toolp/platform/ide_cw.pm
changeset 0 83f4b4db085c
child 1 d4b442d23379
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv1_os/e32toolp/platform/ide_cw.pm	Tue Feb 02 01:39:43 2010 +0200
@@ -0,0 +1,4518 @@
+# Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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:
+# Makmake-module for creating XML files which can be imported as CodeWarrior IDE projects
+# 
+#
+
+package Ide_cw;
+
+my $CW_minimum_supported_version = 2.8;
+
+# declare variables global for module
+my $BaseAddress="";
+my %IdeBlds=();
+my %PrjHdrs=();
+my @Win32LibList=();
+my $Win32Resrc;
+my $Win32StdHeaders;
+
+my $ExtraFilesPath="";
+my @KnownRoots=();
+
+my @addedFiles=();
+my $addHeaders = 1;
+my $addDocuments = 1;
+
+my %processedPlatforms;
+
+require Exporter;
+@ISA=qw(Exporter);
+
+@EXPORT=qw(
+	PMHelp_Mmp
+
+	PMCheckPlatformL
+
+	PMPlatProcessMmp
+
+	PMStartBldList
+		PMBld
+			PMResrcBld
+
+	PMEndSrcList
+);
+
+require Cl_bpabi;
+use strict;
+use BPABIutl;
+use E32Variant;
+use E32Plat; 
+use Winutl;
+use Armutl;
+use Pathutl;
+use Win32API::Registry qw( :ALL );
+use Preprocessor;
+use RVCT_plat2set;
+
+sub PMHelp_Mmp {
+	&Winutl_Help_Mmp;
+}
+
+my $RVCTMajorVersion = Armutl_RVCTMajorVersion();
+my $RVCTMinorVersion = Armutl_RVCTMinorVersion();
+my $RVCTVersion = "${RVCTMajorVersion}_${RVCTMinorVersion}";
+
+my $oP = "--";
+$oP = "-" if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2);
+
+my $cfgMacro = &Variant_GetMacro();
+
+use FindBin;
+use lib $FindBin::Bin."\\perllib";
+
+#use the DOM xml module
+use XML::DOM;
+
+my $projectTemplate;
+my $linkDescriptorTemplate;
+
+my $xmlParser;
+my $xmlProjectDoc;
+my $xmlLinkDescriptorDoc;
+my $xmlLinkDescriptorCommandParent;
+my $xmlLinkDescriptorSymbolParent;
+my $xmlLinkDescriptorDumpFileParent;
+
+my $xmlLinkOrder;		# for accumulating the link order
+my $xmlFileList;		# for accumulating the file list
+my $xmlSourceGroup;		# for accumulating the source
+my $xmlHeadersGroup;	# for accumulating local header files
+my $xmlRootGroup;		# for accumulating files to be added outside of project groups
+my $xmlLinkGroup;		# for accumulating the link descriptor files
+my $xmlLibGroup;		# for accumulating the libraries
+my $xmlResourcesGroup;	# for accumulating resource related files
+my $xmlDocumentsGroup;	# for accumulating supported files specified with DOCUMENT in the .mmp file
+
+my $MmpFile;
+my $VariantFile;
+my $PrefixFile;
+
+my $CW_major_version;
+my $CW_minor_version;
+my $CW_libpath;
+my @CW_librarypath;
+my @ToolChainLibList;
+
+# Hash to store configuration makefile data for furthur processing
+my %configdata;
+
+sub RoundUp1k($) {
+	# Accept C hexadecimal number (0xNNN).  Convert argument to Kb
+	# rounded up to the next 1kb boundary.
+	use integer;
+	return (hex($_[0]) + 1023) / 1024;
+}
+
+use Genutl;
+use cl_generic;
+
+my $ToolPrefix='';
+my $HelperLib='';
+my %PlatOpt=(
+	'Dlltool'=>'',
+	'Entry'=>'-e',
+	'Gcc'=>'',
+	'Ld'=>'',
+	'Petran'=>'',
+	'Optimize'=>'-O'
+);
+my $Dlltool;
+my $Archive;
+my $Link;
+my $Objcopy;
+
+my %CompatibleABIs=(
+	ARMI=>['ARM4', 'THUMB'],
+	ARM4=>['ARMI'],
+	THUMB=>['ARMI'],
+	ARMV5=>['ARMV5_ABIV1'],
+	GCCE=>['GCCE'],
+	BPABI=>['ARMV5_ABIV2']
+);
+my @CompatibleABIs;
+
+my $Makecmd;
+my %ABILibPath=();
+
+sub SystemTarget() {
+	return 1 if &main::SystemTrg;
+	my $ExportLibrary=&main::ExportLibrary;
+	# N.B. should get better way to detect kernel probably!!
+	return 1 if ($ExportLibrary =~ /EKERN/i);
+	
+	return 0;
+}
+
+sub SysTrg () {
+	return 1 if &main::SystemTrg;
+	my $ExportLibrary=&main::ExportLibrary;
+	return 1 if ($ExportLibrary =~ /EKERN/i);
+	my $Trg=&main::Trg;
+	return 1 if ($Trg =~ /KSRT/i);
+	return 0;
+}
+
+sub PMUnderlyingABI($) {
+	my ($ABI) = @_;
+	if ($ABI eq 'ARM4T') {
+		if (&main::BuildAsARM) {
+			return 'ARMI';
+		}
+		elsif (SystemTarget()) {
+			return 'ARM4';
+		}
+		else {
+			return 'ARMV4';
+		}
+	}
+	return $ABI;
+}
+
+##### ARMV5 specific options #####
+my $diag_suppressions;
+my $diag_warnings;
+my $diag_errors;
+
+#The options here are handcoded for ABIV1 mode.
+my $contingentOptions;
+my $exceptions = ' --exceptions --exceptions_unwind';
+my $thumbOptions = '--thumb ';
+my $armOptions = '--arm ';
+my $kernelOptions = '--arm --no_exceptions --no_exceptions_unwind';
+my $invariantOptions = 
+  '--cpu 5T --enum_is_int -Ono_known_library --fpmode ieee_no_fenv --export_all_vtbl --no_vfe --apcs /inter';
+$invariantOptions .= ' --dllimport_runtime' unless ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2);  
+# specify floating point model here
+my $floatingpointmodel = "softvfp";
+if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i)) {
+	$floatingpointmodel = "vfpv2";
+}
+my $floatingpoint = ' --fpu '.$floatingpointmodel.'';
+
+# Set compiler settings
+$diag_suppressions = '--diag_suppress 66,161,611,654,997,1152,1300,1464,1488,6318,6331';
+$diag_warnings = '';
+$diag_errors = '--diag_error 1267';
+my $commonOptions = "$diag_suppressions $diag_warnings $diag_errors";  
+# variables added to fetch the options from the BSF files
+my @commonOptions;
+my @thumbOptions;
+my @armOptions;
+my @kernelOptions;
+my @invariantOptions;
+my @linkerOptions;
+my @archiverOptions;
+
+my $linkCommand = "";		
+# variables to process and store the default and BSF file options
+my $invopts = $invariantOptions;
+my $linkeropts;
+my $archiveropts;
+#varible to store the BSF add options
+my $bsfaddoptions = undef;
+#variable to store the compiler flags, defs and other options
+my $CCFLAGS = undef;
+my $CCDEFS = undef;
+my $CCUREL = undef;
+my $CCUDEB = undef;
+
+
+#GCCE specific OPIONS
+
+my $GCCE_CompilerOption = '-march=armv5t -mthumb-interwork -mapcs';
+$GCCE_CompilerOption .= " -msoft-float -fexceptions -pipe -nostdinc -Wall -Wno-ctor-dtor-privacy -Wno-unknown-pragmas";
+#Flag to check for the customized GCCE platform
+my $CustGCCE=0;
+#Variable to fetch the Customized platform
+my %CustPlat=&main::PlatRec;
+#Flags to read the options
+my $kernelOption=0;
+my $buildAsArmOption=0;
+my $thumbOption=0;
+
+
+my $ArmIncDir;
+my @ArmLibList;
+my $ArmRT;
+
+my %BSF_keywords = (
+		    COMMON_OPTIONS => 1,
+		    THUMB_OPTIONS => 1,
+		    ARM_OPTIONS => 1,
+		    KERNEL_OPTIONS => 1,
+		    INVARIANT_OPTIONS => 1,
+			LD_OPTIONS => 1,
+			AR_OPTIONS => 1
+		   );
+sub PMStartBldList($) 
+{
+	($Makecmd) = @_;
+	my @BldList=&main::BldList;
+	my $BasicTrgType=&main::BasicTrgType;
+	my $ABI=&main::ABI;
+	my $kernelOption=0;
+	my $buildAsArmOption=0;
+	my $thumbOption=0;
+	my @MacroList=&main::MacroList();
+	push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__ ";
+	my %plat = &main::PlatRec();
+
+	$CCFLAGS = "";
+	$CCDEFS = "";
+	$CCUREL = "";
+	$CCUDEB = "";
+	
+	$VariantFile=&main::VariantFile();	
+
+	#read the configuration make file into the hash for only the BPABI platforms
+	my $config_file = BPABIutl_Config_Path(&main::Plat);
+	if ($config_file) {
+		collect_config_data($config_file);
+	}
+		
+	Read_BSF_Options() if ($plat{'CUSTOMIZES'});
+
+	if (SysTrg()) {
+		$kernelOption=1;
+	} elsif (main::BuildAsARM() or ($ABI eq 'ARMV4')) {
+		$buildAsArmOption=1;
+	} else {
+		$thumbOption=1;
+	}
+
+	my $OtherOpts = undef;
+	my $toolchain = $configdata{COMPILER_PLAT};
+	
+	$OtherOpts = &main::CompilerOption($toolchain);
+	
+	if($kernelOption==1)
+	{
+		if(@kernelOptions) {
+# Kernel options as read from BSF file (KERNEL_OPTIONS keyword)
+			Set_BSF_Options('KERNEL_OPTIONS',\@kernelOptions);
+		}
+		$OtherOpts .= " ".fetch_config_data($configdata{KERNEL_OPTIONS});
+	}
+	elsif($buildAsArmOption==1)
+	{	
+		if(@armOptions) {
+# Arm options as read from BSF file (ARM_OPTIONS keyword)
+			Set_BSF_Options('ARM_OPTIONS',\@armOptions);
+		}
+		$OtherOpts .= " ".fetch_config_data($configdata{ARM_OPTIONS});	
+	}
+	elsif($thumbOption==1)
+	{
+		if(@thumbOptions) {
+# Thumb options as read from BSF file (THUMB_OPTIONS keyword)
+			Set_BSF_Options('THUMB_OPTIONS',\@thumbOptions);
+		}
+		$OtherOpts .= " ".fetch_config_data($configdata{THUMB_OPTIONS});
+	}
+	
+	if($thumbOption==1 || $buildAsArmOption==1)
+	{
+		if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i))
+		{
+			$OtherOpts .= "	".$configdata{VFP2MODE_OPTION};
+		}
+		else
+		{
+			$OtherOpts .= "	".$configdata{SOFTVFPMODE_OPTION};
+		}
+	}
+
+	if ($thumbOption==1)
+	{
+		$OtherOpts .= "	".$configdata{COMPILER_THUMB_DEFINES};
+	}
+	
+	$OtherOpts .= "	".$configdata{COMPILER_INTERWORK_DEFINES};
+	
+	if((&main::Plat eq "ARMV5_ABIV1") || (&main::Plat eq "ARMV5" && !$cfgMacro)
+	|| ($CustPlat{'CUSTOMIZES'} 
+	&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV1" && $cfgMacro) 
+	|| ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && !$cfgMacro)))) {
+		ComputeCompilerOpts();
+	}
+	elsif($config_file) {
+		$CCFLAGS = &Cl_bpabi::getConfigVariable('CCFLAGS');
+	}
+	$CCFLAGS .= $OtherOpts;
+
+	if(@invariantOptions)
+	{
+	# Invariant options as read from BSF file (INVARIANT_OPTIONS keyword)
+		Set_BSF_Options('INVARIANT_OPTIONS',\@invariantOptions);
+	}
+	if(@commonOptions)
+	{
+	# Common options as read from BSF file (COMMON_OPTIONS keyword)
+		Set_BSF_Options('COMMON_OPTIONS',\@commonOptions);
+	}
+	if(@linkerOptions)
+	{
+	# Invariant options as read from BSF file (LD_OPTIONS keyword)
+		Set_BSF_Options('LD_OPTIONS',\@linkerOptions);
+	}
+	if ($BasicTrgType=~/^LIB$/o) {
+		if(@archiverOptions)
+		{
+		# Invariant options as read from BSF file (AR_OPTIONS keyword)
+			Set_BSF_Options('AR_OPTIONS',\@archiverOptions);
+		}	
+	}
+
+	if($bsfaddoptions)
+	{
+		fixbsfoptions($bsfaddoptions);
+	}
+	$CCFLAGS .= $bsfaddoptions;
+	$CCDEFS = $configdata{COMPILER_DEFINES};
+	$CCDEFS .= printlist("-D", @MacroList);
+	$CCDEFS .= $configdata{PLATFORM_DEFINES};
+
+	if($kernelOption==1)
+	{
+		$CCDEFS .= -D__KERNEL_MODE__;
+	}
+	
+	if($VariantFile) { 
+		$CCDEFS .= " -D__PRODUCT_INCLUDE__="."\\\"".&main::Path_Split('File',$VariantFile)."\\\"";
+	}
+	
+	foreach (@BldList) 
+	{
+		if($kernelOption == 0)
+		{
+			if (/DEB$/o) {
+				$CCUDEB .= " ".$configdata{EXCEPTIONS};
+			}
+			else {
+				$CCUREL .= " ".$configdata{EXCEPTIONS};
+			}
+		}
+		#collect the options and macro's depending on the whether it is a UREL or UDEB		
+		my @ml = &main::MacroList($_);
+		if (/DEB$/o) {
+			$CCUDEB .= " ".$CCFLAGS;
+			$CCUDEB .= printlist("-D", @ml);
+			$CCUDEB .= " ".$CCDEFS;
+		}
+		else {
+			$CCUREL .= " ".$CCFLAGS;
+			$CCUREL .= printlist("-D", @ml);
+			$CCUREL .= " ".$CCDEFS;
+		}
+	}
+}
+
+sub ComputeCompilerOpts() {
+	my %plat = &main::PlatRec();
+	my $ABI=&main::ABI;
+	my $TrgType=&main::TrgType;
+
+	if (SysTrg()) {
+	        $contingentOptions = $kernelOptions;
+        } elsif (main::BuildAsARM() or ($ABI eq 'ARMV4')) {
+	        $contingentOptions = $armOptions.$floatingpoint.$exceptions;
+	    } else {
+			$contingentOptions = $thumbOptions.$floatingpoint.$exceptions.' -D__MARM_THUMB__';	
+	}
+	# change support for ARMV4
+	if ($ABI eq 'ARMV4') {
+		$invopts =~ s/5T/4/;
+		$invopts =~ s/inter/nointer/;
+	} else {
+		$contingentOptions .= ' -D__MARM_INTERWORK__';
+	}
+	$CCFLAGS = $commonOptions.' '.$contingentOptions.' '.$invopts.' -c '.' '.&main::CompilerOption("ARMCC");
+}
+
+sub GetMajorVersion ($)
+	{
+	my ($versionString) = @_;
+
+	if ($versionString =~ /^\d\.\d\.\d$/)
+		{
+		$versionString =~ s/\.\d$//;
+		}
+
+	return $versionString;
+	}
+
+sub GetMinorVersion ($)
+	{
+	my ($versionString) = @_;
+
+	if ($versionString =~ /^\d\.\d\.\d$/)
+		{
+		$versionString =~ s/^\d\.\d\.//;
+		}
+	else
+		{
+		$versionString = 0;
+		}
+
+	return $versionString;
+	}
+
+sub PMCheckPlatformL {
+
+	# check version of CodeWarrior for Symbian OS
+
+	my @compatibleCWInstallations;
+
+	$CW_major_version = 0;
+	$CW_minor_version = 0;
+
+	my $minimumMajorVersion = GetMajorVersion ($CW_minimum_supported_version);
+	my $minimumMinorVersion = GetMinorVersion ($CW_minimum_supported_version);
+
+	if (defined $ENV{CW_SYMBIAN_VERSION})
+		{
+		# CW_SYMBIAN_VERSION is set - either MAKMAKE is being executed by an IDE's .mmp Importer,
+		# or the user is specifying a specific CW version to target from the command line.
+		# Either way, we've been given a single version to target, so we attempt to do just that.
+
+		$CW_major_version = GetMajorVersion ($ENV{CW_SYMBIAN_VERSION});
+		$CW_minor_version = GetMinorVersion ($ENV{CW_SYMBIAN_VERSION});
+		
+		push @compatibleCWInstallations, $ENV{CW_SYMBIAN_VERSION};
+		}
+	else
+		{
+		# CW_SYMBIAN_VERSION isn't set - either MAKMAKE is being executed by a pre-OEM3.0 IDE .mmp
+		# Importer or from the command line.  Either way, we delve into the registry and attempt to
+		# target the latest CW for Symbian OS installed, recording all CW for Symbian OS installations
+		# too.
+
+		my $regKeyHandle;
+		my $topLevelKey = HKEY_LOCAL_MACHINE;
+		my $productVersionKey = 'SOFTWARE\\Metrowerks\\CodeWarrior\\Product Versions';
+
+		if (!RegOpenKeyEx($topLevelKey, $productVersionKey, 0, KEY_READ, $regKeyHandle))
+			{		    		
+			die "Can't read \"HKEY_LOCAL_MACHINE\\$productVersionKey\" : ", regLastError(), "\n";
+		    }
+
+		my $subKeyIndex = 0;
+		my $subKeySize = 0;
+		my $subKeyName;
+
+		my @installedCWForSymbianKeys;
+
+		while (RegEnumKeyEx($regKeyHandle, $subKeyIndex, $subKeyName, $subKeySize, [], [], [], []))
+			{
+			push (@installedCWForSymbianKeys, $productVersionKey."\\".$subKeyName) unless ($subKeyName !~ /Symbian/);
+			$subKeyIndex++;
+			}
+
+		RegCloseKey($regKeyHandle) || print STDERR "WARNING: Could not close registry key.";
+
+		my $versionType;
+		my $versionValue;
+
+		foreach my $installedCWForSymbianKey (@installedCWForSymbianKeys)
+			{
+			if (!RegOpenKeyEx($topLevelKey, $installedCWForSymbianKey, 0, KEY_READ, $regKeyHandle))
+				{		    		
+				die "Can't read \"HKEY_LOCAL_MACHINE\\$installedCWForSymbianKey\" : ", regLastError(), "\n";
+			    }
+
+			if (!RegQueryValueEx($regKeyHandle, "VERSION", [], $versionType, $versionValue, []))
+				{
+				die "Can't read \"HKEY_LOCAL_MACHINE\\$installedCWForSymbianKey\\VERSION\" : ", regLastError(), "\n";
+				}
+
+			my $temp_major_version = GetMajorVersion ($versionValue);
+			my $temp_minor_version = GetMinorVersion ($versionValue);
+
+			if (($temp_major_version > $CW_major_version) ||
+				(($temp_minor_version > $CW_minor_version) &&
+				   ($temp_major_version >= $CW_major_version)))
+				{
+				$CW_major_version = $temp_major_version;
+				$CW_minor_version = $temp_minor_version;
+				}
+			
+			if (($temp_major_version > $minimumMajorVersion) ||
+				(($temp_minor_version > $minimumMinorVersion) &&
+				   ($temp_major_version >= $minimumMajorVersion)))
+				{
+				push @compatibleCWInstallations, $versionValue;
+				}
+
+			RegCloseKey($regKeyHandle);
+			}
+		}
+
+	# We've determined a CW version to target, now we validate if we actually support this
+
+	if (!$CW_major_version ||
+		($CW_major_version < $minimumMajorVersion) ||
+		(($CW_major_version >= $minimumMajorVersion) && ($CW_minor_version < $minimumMinorVersion)))
+		{
+		if (defined $ENV{CW_SYMBIAN_VERSION})
+			{
+			die "Error: CW_SYMBIAN_VERSION is set to $ENV{CW_SYMBIAN_VERSION}.\n       The minimum version supported by these tools is $CW_minimum_supported_version.\n";
+			}
+		else
+			{
+			die "ERROR: Unable to identify a compatible CodeWarrior for Symbian OS installation.\n";
+			}
+		}
+
+	if (@compatibleCWInstallations > 1)
+		{
+		my $targetVersion = $CW_major_version;
+		$targetVersion .= ".$CW_minor_version" if $CW_minor_version;
+			
+		print ("Info: More than one compatible CodeWarrior for Symbian OS installation has been detected.\n");
+		print ("      The generated project will target $targetVersion - to override this, set the CW_SYMBIAN_VERSION\n");
+		print ("      environment variable to the version number you wish to target and re-run this command.\n");
+		print ("      Supported version numbers detected : @compatibleCWInstallations.\n");
+		}
+	else
+		{
+		print ("Info: Detected CodeWarrior Version Major=$CW_major_version Minor=$CW_minor_version\n");
+		}
+
+	# CW version has been validated, tailor generated projects on this basis
+
+	$CW_libpath = 'Symbian_Support\Win32-x86 Support\Libraries\Win32 SDK';
+ 	push @CW_librarypath,$CW_libpath;
+ 	# Lib path to support the Carbide runtime libraries
+ 	$CW_libpath = 'Symbian_Support\Runtime\Runtime_x86\Runtime_Win32\Libs';
+ 	push @CW_librarypath,$CW_libpath;
+		
+	if ($CW_major_version == 2.8)
+		{
+		$projectTemplate = "CW_project_template_v3.xml";
+		$linkDescriptorTemplate = "cw_link_descriptor_template.cwlink";
+		}
+	else
+		{
+		$projectTemplate = "CW_project_template_v4.xml";
+		$linkDescriptorTemplate = "cw_link_descriptor_template_v2.cwlink";		
+		}
+		
+	$xmlParser = new XML::DOM::Parser; 
+	$xmlProjectDoc = $xmlParser->parsefile ($FindBin::Bin."\\$projectTemplate");
+}
+
+# Check if a platform is a customization
+sub IsCustomization($) {
+	my ($plat) = @_;
+	return 1 if (Plat_Customizes($plat));
+	return 0;
+}
+
+sub PMPlatProcessMmp (@) {
+	
+	my $currentPlat=&main::Plat;
+
+	return if ($processedPlatforms{$currentPlat});
+	$processedPlatforms{$currentPlat}=1;
+	@ToolChainLibList = &GetLibList;
+	my $TrgType=&main::TrgType;
+	if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
+	{
+		$CustGCCE=1;
+	}
+
+	if ($currentPlat =~ /^WINSCW$/)
+		{	
+		my $includes = $ENV{MWCWinx86Includes};
+		&Winutl_DoMmp_Parse(\@_, $includes);
+		@Win32LibList=&Winutl_Win32LibList;
+		$Win32Resrc=&Winutl_Win32Resrc;
+		$Win32StdHeaders=&Winutl_Win32StdHeaders;
+		$BaseAddress=&Winutl_BaseAddress unless ($TrgType eq 'EXE');
+		}
+	elsif ($currentPlat =~ /^ARMV5/ || IsCustomization($currentPlat))
+		{	
+		&Armutl_DoMmp(@_);
+		$ArmIncDir = &Armutl_ArmIncDir;
+		&main::SetStdIncPaths($ArmIncDir);
+		@ArmLibList = &Armutl_ArmLibList;
+		$ArmRT = &Armutl_ArmRT;
+		}
+
+	my $BaseTrg=&main::BaseTrg;
+	my $MakeFilePath=&main::MakeFilePath;
+	$MmpFile=&main::MmpFile;
+	$VariantFile=&main::VariantFile();		
+
+	# Set up the list of known roots
+
+	my $epocroot=&main::Path_Drive . &main::EPOCPath;
+	$epocroot =~ s/EPOC32\\$//i;
+
+	if ($currentPlat eq "GCCE" || $CustGCCE)
+	{
+		$PrefixFile=$epocroot.'epoc32\\include\\gcce\\gcce.h';
+	}
+	else
+	{
+		$PrefixFile=$epocroot.'epoc32\\include\\rvct'.$RVCTVersion.'\\rvct'.$RVCTVersion.'.h';
+	}
+	my $mmproot = &main::Path_Drive . &main::Path_Split('Path',$MmpFile);
+	my $mmprootname = "MMPDir";
+	my $mmpisglobal = 0;
+
+	if (defined $ENV{CW_ROOT_NAME})
+		{
+		# generate KnownRoots suitable for the IDE MMP importer
+		# This has a global source tree for EPOCROOT, and puts the
+		# project next to the MMP file
+
+		addKnownRoot($ENV{CW_ROOT_NAME}, 1, $epocroot, "");
+		$mmprootname = "Project";
+		$mmpisglobal = 1;
+		}
+	else
+		{
+		# generate KnownRoots suitable for command-line generated XML files
+		# We will add a user source tree for MMPDir and EPOCROOT, but can't use
+		# EPOCROOT for the OutputDirectory
+
+		addKnownRoot("EPOCROOT", 0, $epocroot, "");
+		}
+	addKnownRoot($mmprootname, $mmpisglobal, $mmproot, "");
+
+	# Allow for MMP files in component subdirectories by matching multiple levels
+	# up to get {MMPDir}..\whatever paths. Stop one level down from the root,
+	# since "everything on this drive" seems a bit extreme
+	#
+	my $tmppath = $mmproot;
+	my $dotdots = '';
+	while ($tmppath =~ /^(.:.+\\)[^\\]+\\$/i)
+		{
+		$tmppath = $1;
+		$dotdots .= "..\\";
+		addKnownRoot($mmprootname, $mmpisglobal, $tmppath, $dotdots);
+		}
+}
+
+sub findTarget($$$) {
+	my ($name,$platbld,$abibld) = @_;
+
+	my @targets = $xmlProjectDoc->getElementsByTagName("TARGET",1); 
+
+	foreach my $target (@targets)
+		{
+		
+		my $element = $target->getElementsByTagName("NAME",0)->item(0);
+		$element = $element->getFirstChild;
+		
+	#   here we want to get the plat build that is specified in the cw project tempalte
+	#   and not the abi build - there are more platbuilds than abibuilds so other targets
+	#   (e.g. GCCE) can get the wrong tempalte "NAME" (i.e. it will be ARMV5 rather than GCCE, which is not want we want)
+		if ($element->getData() =~ /$platbld$/)
+			{
+			
+			my $newtarget=$target->cloneNode(1);
+			$target->getParentNode()->appendChild($newtarget);
+			$element = $newtarget->getElementsByTagName("NAME",0)->item(0);
+			$element = $element->getFirstChild;
+			$element->setData("$platbld");
+			
+			# remember name as an attribute: this is removed before
+			# writing out the project.
+			$newtarget->setAttribute("NAME", "$platbld");
+			return $newtarget;
+			}
+			else
+			{
+				my $newtarget=$target->cloneNode(1);
+				my $newplat=&main::Plat." ".&main::Bld;
+				$target->getParentNode()->appendChild($newtarget);
+				$element = $newtarget->getElementsByTagName("NAME",0)->item(0);
+				$element = $element->getFirstChild;
+				$element->setData("$newplat");
+	 			
+				# remember name as an attribute: this is removed before
+				# writing out the project.
+				$newtarget->setAttribute("NAME", "$newplat");
+				return $newtarget;
+			}
+		}
+	return undef;
+}
+
+sub newList($$$) {
+	my ($target, $tag, $replace) = @_;
+
+	my $newlist = new XML::DOM::Element($xmlProjectDoc,$tag);
+	if ($replace==1)
+		{
+		my $elements = $target->getElementsByTagName($tag,0);
+		my $element = $elements->item(0);
+		$target->replaceChild($newlist, $element);
+		}
+	else
+		{
+		$target->appendChild($newlist);
+		}
+	return $newlist;
+}
+
+sub changeValue($$) {
+	my ($setting, $replacement) = @_;
+	my $value = $setting->getElementsByTagName("VALUE",0)->item(0);
+
+	if (defined $value)
+		{
+		if ($value->hasChildNodes)
+			{
+			$value->getFirstChild->setData($replacement);
+			}
+		else
+			{
+			$value->addText($replacement);
+			}
+		}
+}
+
+sub textSetting($$$$) {
+	my ($element,$name,$value,$insertionpoint)=@_;
+
+	my $setting = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+	&textElement($setting, "NAME", $name);
+	&textElement($setting, "VALUE", $value);
+	$element->insertBefore($setting, $insertionpoint);
+	$element->addText("\n");
+}
+
+sub addKnownRoot($$$$) {
+	my ($rootname, $global, $rootpath, $pathprefix) = @_;
+	$rootpath=&main::Path_Chop($rootpath);
+	push @KnownRoots, [$rootname, $global, quotemeta($rootpath), $pathprefix];
+}
+
+sub addRootedPath($$$) {
+	my ($setting,$needglobal,$path) = @_;
+	my $root = "Absolute";
+
+	if ($path =~ /^\\/)
+		{
+		$path = &main::Path_Drive . $path;	# ensure it has a drive letter
+		}
+
+	foreach (@KnownRoots)
+		{
+		my ($rootname, $global, $rootpath, $pathprefix) = @{$_};
+
+		next if ($needglobal && !$global);
+		if ($path =~ /^$rootpath\\/i)
+			{			
+			$path =~ s/^$rootpath\\/$pathprefix/i;
+			$root = $rootname;
+			last;
+			}
+		}
+	$path=&main::Path_Chop($path);
+	if ($root eq "Absolute" && $path =~ /^(.:)$/)
+		{
+		$path .= "\\";
+		}
+
+	&textSetting($setting, "Path", $path);
+	&textSetting($setting, "PathFormat", "Windows");
+	&textSetting($setting, "PathRoot", $root);
+}
+
+sub changePathSetting($$$) {	
+	my ($setting,$global,$value) = @_;
+
+	my @oldstuff = $setting->getElementsByTagName("SETTING",0);
+	foreach my $old (@oldstuff)
+		{
+		&removeNode($old);
+		}
+
+	&addRootedPath($setting,$global,$value);
+}
+
+sub addSourceTrees($) {
+	my ($node) = @_;
+
+	my $element = $node->getElementsByTagName("VALUE",0)->item(0);
+	&removeNode($element) if (defined $element);
+
+	if (defined $ENV{CW_ROOT_NAME})
+		{
+		return;	# paths were converted to be relative to global source trees
+		}
+
+	my $sourcepath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+	$sourcepath->addText("\n");
+	&textSetting($sourcepath, "Name", "EPOCROOT");
+	&textSetting($sourcepath, "Kind", "AbsolutePath");
+
+	my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+	&textElement($pathdata, "NAME", "Path"); 
+	$pathdata->addText("\n");
+
+	my $epocroot=&main::EPOCPath;
+	$epocroot =~ s/\\EPOC32\\$/\\/i;
+
+	&addRootedPath($pathdata, 1, $epocroot);
+
+	$sourcepath->appendChild($pathdata);
+	$node->appendChild($sourcepath);
+
+	my $mmproot = &main::Path_Split('Path',$MmpFile);
+	my $sourcepath2 = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+	$sourcepath2->addText("\n");
+	&textSetting($sourcepath2, "Name", "MMPDir");
+	&textSetting($sourcepath2, "Kind", "AbsolutePath");
+
+	my $pathdata2 = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+	&textElement($pathdata2, "NAME", "Path"); 
+	$pathdata2->addText("\n");
+	&addRootedPath($pathdata2, 1, $mmproot);
+
+	$sourcepath2->appendChild($pathdata2);
+	$node->appendChild($sourcepath2);
+
+}
+
+sub addUserSearchPaths($) {
+	my ($node) = @_;
+
+	my @elements = $node->getElementsByTagName("SETTING",0);
+	foreach (@elements)
+		{
+		&removeNode($_);
+		}
+
+	my %ordereddirs;
+	my @ordereddirlist=();
+	foreach my $dir (&main::UserIncPaths)
+		{
+		next if (!defined $dir);
+		$dir = &main::Path_Chop($dir)."\\";
+		my $key = uc $dir;
+		if (! defined($ordereddirs{$key}))
+			{
+			$ordereddirs{$key}=1;
+			push @ordereddirlist, $dir;
+			}
+		}
+
+	# now add the directories used to find source files
+	
+	my %dirs;
+	my $SourceStructRef=&main::SourceStructRef;
+	foreach my $SourceRef (@$SourceStructRef)
+		{
+		 $dirs{$$SourceRef{SrcPath}}=1;
+		}
+	my $DefFile = &main::DefFile;
+	if ($DefFile)
+		{			
+		$DefFile = &main::Path_Split('Path',$DefFile);
+		$dirs{$DefFile}=1;
+		}
+
+	my $MmpFilePath = &main::Path_Split('Path',$MmpFile);
+	$dirs{$MmpFilePath}=1;
+		
+	$dirs{$ExtraFilesPath}=1;
+		
+
+	foreach my $srcdir (sort keys %dirs)
+		{
+		if (!defined($ordereddirs{uc $srcdir}))
+			{
+			push @ordereddirlist, $srcdir;
+			}
+		}
+		
+	foreach my $srcdir (@ordereddirlist)
+		{
+		my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		$accesspath->addText("\n");
+		my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		&textElement($pathdata, "NAME", "SearchPath"); 
+		$pathdata->addText("\n");
+		&addRootedPath($pathdata, 0, $srcdir);
+
+		$accesspath->appendChild($pathdata);
+		&textSetting($accesspath, "Recursive", "false");
+		&textSetting($accesspath, "FrameworkPath", "false");
+		&textSetting($accesspath, "HostFlags", "All");
+		$node->appendChild($accesspath);
+		}
+}
+
+sub addSystemSearchPaths($) {
+	my ($node) = @_;
+
+	my @elements = $node->getElementsByTagName("SETTING",0);
+	foreach (@elements)
+		{
+		&removeNode($_);
+		}
+
+	my $ASSPLinkPath;
+	$ASSPLinkPath = &main::ASSPLinkPath if (&main::ASSPLibList);
+
+	my @extraIncPaths=();
+	push @extraIncPaths, $ArmIncDir if $ArmIncDir;
+
+	my %ordereddirs;
+	my @ordereddirlist=();
+	
+	foreach my $dir (&main::SysIncPaths, @extraIncPaths, &main::StatLinkPath, $ASSPLinkPath, &main::LinkPath)
+		{
+		next if (!defined $dir);
+		$dir = &main::Path_Chop($dir)."\\";
+		my $key = uc $dir;
+		if (! defined($ordereddirs{$key}))
+			{
+			$ordereddirs{$key}=1;
+			push @ordereddirlist, $dir;
+			}
+		}
+
+	my %dirs;
+
+	if ($VariantFile)
+		{
+		my $VariantFilePath = &main::Path_Split('Path',$VariantFile);
+		$dirs{$VariantFilePath}=1;
+		}
+
+	if (((&main::Plat =~ /^ARMV5/) || (&main::Plat =~ /^GCCE$/) ||(IsCustomization(&main::Plat))) && $PrefixFile) 
+		{
+		my $PrefixFilePath = &main::Path_Split('Path',$PrefixFile);
+		$dirs{$PrefixFilePath}=1;
+		}
+
+	foreach my $srcdir (sort keys %dirs)
+		{
+		if (!defined($ordereddirs{uc $srcdir}))
+			{
+			push @ordereddirlist, $srcdir;
+			}
+		}
+		
+	foreach my $srcdir (@ordereddirlist)
+		{
+		my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		$accesspath->addText("\n");
+		my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		&textElement($pathdata, "NAME", "SearchPath"); 
+		$pathdata->addText("\n");
+		&addRootedPath($pathdata, 0, $srcdir);
+
+		$accesspath->appendChild($pathdata);
+		&textSetting($accesspath, "Recursive", "false");
+		&textSetting($accesspath, "FrameworkPath", "false");
+		&textSetting($accesspath, "HostFlags", "All");
+		$node->appendChild($accesspath);
+		}
+	
+	if (&main::Plat =~ /^WINSCW$/)
+	{
+ 		my $lpath;
+ 		foreach $lpath (@CW_librarypath)
+ 		{
+ 			# only add Win32 SDK for WINSCW system access paths	
+ 			my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+ 			$accesspath->addText("\n");
+ 			my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+ 			&textElement($pathdata, "NAME", "SearchPath"); 
+ 			$pathdata->addText("\n");
+ 			
+ 			&textSetting($pathdata, "Path", $lpath);
+ 			&textSetting($pathdata, "PathFormat", "Windows");
+ 			&textSetting($pathdata, "PathRoot", "CodeWarrior");
+ 			$accesspath->appendChild($pathdata);
+ 			&textSetting($accesspath, "Recursive", "false");
+ 			&textSetting($accesspath, "FrameworkPath", "false");
+ 			&textSetting($accesspath, "HostFlags", "All");
+ 			$node->appendChild($accesspath);
+ 		}
+	}
+	if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
+	{
+		$CustGCCE=1;
+	}
+	if (&main::Plat =~ /^GCCE$/ || $CustGCCE)
+	{
+		my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		$accesspath->addText("\n");
+		my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		&textElement($pathdata, "NAME", "SearchPath"); 
+		$pathdata->addText("\n");
+		
+		my $GCCE_IncludePath = GetGCCELibPath("-print-libgcc-file-name");
+		$GCCE_IncludePath .= '\\include';
+		&textSetting($pathdata, "Path", $GCCE_IncludePath);
+		
+		&textSetting($pathdata, "PathFormat", "Windows");
+		&textSetting($pathdata, "PathRoot", "Absolute");
+		$accesspath->appendChild($pathdata);
+		&textSetting($accesspath, "Recursive", "false");
+		&textSetting($accesspath, "FrameworkPath", "false");
+		&textSetting($accesspath, "HostFlags", "All");
+		$node->appendChild($accesspath);
+	}
+	
+}
+
+sub addDownloadFileList($) {
+	my ($node, @DownloadList) = @_;
+	
+	my @elements = $node->getElementsByTagName("SETTING",0);
+	foreach (@elements)
+		{
+		&removeNode($_);
+		}
+
+	my $epocdata = &main::EPOCPath . "data\\";
+	foreach my $srcfile (@DownloadList)
+		{
+		my $targetpath = $srcfile;
+		$targetpath =~ s/^Z\\/C:\\/i;
+		
+		my $download = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		$download->addText("\n");
+		my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
+		&textElement($pathdata, "NAME", "HostFilePath"); 
+		$pathdata->addText("\n");
+		&addRootedPath($pathdata, 0, "$epocdata$srcfile");
+
+		$download->appendChild($pathdata);
+		&textSetting($download, "TargetFilePath", $targetpath);
+		$node->appendChild($download);
+		}
+	}
+
+sub kitRelativePath ($) {
+	my ($kitRootBasedPath) = @_;
+		
+	my $kitRoot = &main::EPOCPath;
+	$kitRoot =~ s/EPOC32\\$//i;
+	$kitRoot = quotemeta (&main::Path_Chop($kitRoot));
+
+	$kitRootBasedPath =~ s/^$kitRoot//i;
+
+	$kitRootBasedPath;
+}
+	
+sub PMBld() {
+
+	my %changedsettings;
+
+	my $ABI=&main::ABI;
+	my $Bld=&main::Bld;
+	my $Plat=&main::Plat;
+	my $BaseName=&main::BaseMak;
+	my @SrcList=&main::SrcList;
+	my $BaseTrg=&main::BaseTrg;
+	my @BldList=&main::BldList;
+	my $DefFile=&main::DefFile;
+	my $FirstLib=&main::FirstLib;
+	# IsCustomDllUseCase() subroutine is called to check if the given executable 
+	# is a custom dll or not.
+	my $IsCustomDll = Cl_bpabi::IsCustomDllUseCase();
+	# ABI flags set depending on the ENABLE_ABIV2_MODE macro set in the variant file.
+	my $ABIV1 = 0;
+	my $ABIV2 = 0;
+	if (($Plat eq "ARMV5_ABIV1" && $cfgMacro) || ($Plat eq "ARMV5" && !$cfgMacro)
+	|| ($CustPlat{'CUSTOMIZES'} 
+	&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV1" && $cfgMacro) || ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && !$cfgMacro))))
+	{
+		$ABIV1=1;
+	}
+	elsif (($Plat eq "ARMV5_ABIV2" && !$cfgMacro) || ($Plat eq "ARMV5" && $cfgMacro)
+	|| ($CustPlat{'CUSTOMIZES'} 
+	&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV2" && !$cfgMacro) || ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && $cfgMacro))))
+	{
+		$ABIV2=1;
+	}
+	
+	if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
+	{
+		$CustGCCE=1;
+	}
+
+ 	if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
+	        # Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
+		# Rename FirstLib.lib static lib used with RVCT2.1 as FirstLib2_1.lib
+		if ($FirstLib=~/^\s*(\S+)(\.lib)$/io) {
+		        if ($1!~/$RVCTVersion/i) {
+				$FirstLib=$1.$RVCTVersion.".lib";
+			}
+		}
+	}	
+
+	my $BasicTrgType=&main::BasicTrgType;
+	my @LibList;
+	my @StatLibList=&main::StatLibList;
+	if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
+	        # Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
+		# Rename all the static libs used with RVCT2.1 as libname2_1.lib
+		for (my $i =0; $i < scalar(@StatLibList); $i++) {
+		        if ($StatLibList[$i]=~/^\s*(\S+)(\.lib)$/io) {
+			        if ($1!~/$RVCTVersion/i) {
+				        $StatLibList[$i]=$1.$RVCTVersion.".lib";
+				}
+			}
+		}
+	}
+	
+
+	my @ASSPLibList = &main::ASSPLibList;
+	my $Trg=&main::Trg;
+	if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
+		if ($BasicTrgType=~/^LIB$/o) {
+			# Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
+			# Rename all the static libs produced with RVCT2.1 as {libname}2_1.lib
+		        if ($Trg=~/^\s*(\S+)(\.lib)$/io) {
+			        if ($1!~/$RVCTVersion/i) {
+				        $Trg=$1.$RVCTVersion.".lib";
+				}
+			}
+			if ($BaseTrg!~/$RVCTVersion/i) {
+			        $BaseTrg .= $RVCTVersion;
+			}
+		}
+	}
+
+	my $TrgPath=&main::TrgPath;
+	my $TrgType=&main::TrgType;
+	my $epocroot=&main::Path_Drive . &main::EPOCPath;
+	$epocroot =~ s/EPOC32\\$//i;
+	my $UIDFile;
+
+	$ExtraFilesPath = &main::MakeFilePath;
+
+	if ($Bld =~ /DEB/) {
+		@LibList=&main::DebugLibList;
+	} else {
+		@LibList=&main::LibList;
+	}
+	my $xmlTarget;
+	if ($ABI =~ /BPABI/)
+	{
+		$ABI = "GCCE";
+	}
+	
+	if ($Plat eq "GCCE" || $CustGCCE || $ABIV2) {
+	
+		if ($CW_major_version < 3.1) {
+			die "FATAL ERROR: Target $Plat requires CodeWarrior for Symbian release 3.1 at minimum.\n";
+		}
+	}
+	
+	if ($ABIV2 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2))
+	{
+		die "FATAL ERROR: Target ARMV5_ABIV2 requires RVCT version 2.2 and greater. Detected RVCT $RVCTMajorVersion.$RVCTMinorVersion.\n";
+	}
+	
+	if (($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) && $CW_major_version < 3.1 && $ABIV2)
+	{
+		die "FATAL ERROR: Detected RVCT Version $RVCTMajorVersion.$RVCTMinorVersion and CodeWarrior version $CW_major_version. RVCT 2.2 and greater requies CodeWarrior version 3.1 at minimum.\n";
+	}
+	
+    $xmlTarget = findTarget($BaseName, "$Plat $Bld", "$ABI $Bld");
+		
+	return if (!defined($xmlTarget));
+	
+	my $targetname = $xmlTarget->getAttribute("NAME");
+
+	my $UnderlyingABI=PMUnderlyingABI($ABI);
+	my @ChopRTWSysIncPaths=&main::Path_Chop(&main::Path_RltToWork(&main::SysIncPaths));
+	my @ChopRTWUserIncPaths=&main::Path_Chop(&main::Path_RltToWork(&main::UserIncPaths));
+	my $EPOCPath=&main::EPOCPath;
+	my $LinkAs=&main::LinkAs;
+	my $LibPath=&main::LibPath;
+	my @UidList=&main::UidList;	
+	my $WarningLevelGCC=&main::CompilerOption("GCC");
+	my $ExportLibrary=&main::ExportLibrary;
+	my $NoExportLibrary=&main::NoExportLibrary;
+	my $SystemTrg = SystemTarget();
+	my %Version = &main::Version();
+	my $ExtraExportLibrary;
+	my $PrimaryExportLibrary = $ExportLibrary;
+	unless ($Version{explicit}) {
+		$ExtraExportLibrary = $ExportLibrary;
+		$ExtraExportLibrary =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
+		$PrimaryExportLibrary = $ExtraExportLibrary;
+	}
+
+	my $ChopBldPath=&main::Path_Chop(&main::BldPath);
+	my $EPOCIncPath=&main::EPOCIncPath;
+	my $ChopRelPath=&main::Path_Chop(&main::RelPath);
+	my $RelPath=&main::RelPath;
+	my $StatLinkPath=&main::StatLinkPath;
+	my $ParentPlat;
+	
+# 	Check if a platform is customization, if yes find the parent platform.
+	my $IsPlatCustomization=IsCustomization($Plat);
+	if ($IsPlatCustomization) {
+		$ParentPlat = Plat_Customizes($Plat);
+	}
+	
+	my @RTLibList;
+	if ($ABIV1) {
+	    @RTLibList = ('dfpaeabi.lib', "dfprvct${RVCTVersion}.lib", 'drtaeabi.lib', 'drtaeabi.lib(VtblExports.o)');
+	    if ($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) {
+		# The scppnwdl.lib should come before drtrvct2_2.lib
+		push @RTLibList, "scppnwdl.lib";
+		push @RTLibList, "drtrvct${RVCTVersion}.lib";
+	    }
+	    else
+	    {
+		push @RTLibList, "dfprvct${RVCTVersion}-thunk.lib";
+		push @RTLibList, "drtrvct${RVCTVersion}.lib";
+	    }    
+	}
+	elsif ($ABIV2)
+	{
+		@RTLibList = ('drtaeabi.dso', 'dfpaeabi.dso', "dfprvct${RVCTVersion}.dso");
+	    if ($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) {
+		# The scppnwdl.lib should come before drtrvct2_2.lib
+		push @RTLibList, "scppnwdl.dso";
+		push @RTLibList, "drtrvct${RVCTVersion}.dso";
+	    }
+	}
+	
+	my @compatibleDOCUMENTExtensions = ("cfg", "h", "hrh", "iby", "inf", "ini", "loc", "mmpi", "policy", "ra", "rh", "rls", "rss", "script", "txt");
+	my @DocList = &main::DocList;
+	@addedFiles=();
+
+
+#	set up LinkAs
+	$UidList[2]=~/^0x(.*)$/o;
+	if ($1 ne '00000000') { # have to make sure than series of noughts in brackets doesn't appear in name for null uids
+		$LinkAs=join '', &main::Path_Split('Base',$LinkAs),"[$1]",&main::Path_Split('Ext',$LinkAs);
+	}
+
+#	set up dlltool flag hash
+	my %ABIDlltool=(
+		ARMI=>'-m arm_interwork',
+		ARM4=>'-m arm',
+		THUMB=>'-m thumb'
+	);
+
+#	work out the flags for various platforms
+	if ($ABI eq 'ARMI') {
+		$PlatOpt{Gcc}='-march=armv4t -mthumb-interwork';
+		$PlatOpt{Dlltool}=$ABIDlltool{ARMI};
+	}
+	elsif ($ABI eq 'ARM4T') {
+		if (&main::BuildAsARM) {
+			$PlatOpt{Gcc}='-march=armv4t -mthumb-interwork';
+			$PlatOpt{Dlltool}=$ABIDlltool{ARMI};
+		}
+		elsif ($SystemTrg) {
+			$PlatOpt{Gcc}='-march=armv4';
+#			allow thumb for ARM4 ABI where necessary
+			unless (&main::PlatABI eq 'ARM4') {
+				$PlatOpt{Gcc}.='t';
+			}
+			$PlatOpt{Dlltool}=$ABIDlltool{ARM4};
+		}
+		else {
+			$PlatOpt{Gcc}='-mthumb-interwork -D__MARM_THUMB__';
+			$PlatOpt{Dlltool}=$ABIDlltool{THUMB};
+		}
+	}
+	elsif ($ABI eq 'ARM4') {
+		$PlatOpt{Gcc}='-march=armv4';
+#		allow thumb for ARM4 ABI where necessary
+		unless (&main::PlatABI eq 'ARM4') {
+			$PlatOpt{Gcc}.='t';
+		}
+		$PlatOpt{Dlltool}=$ABIDlltool{ARM4};
+	}
+	elsif ($ABI eq 'THUMB') {
+		$PlatOpt{Gcc}='-mthumb-interwork';
+		$PlatOpt{Dlltool}=$ABIDlltool{THUMB};
+	}
+	
+	elsif ($Plat ne 'WINSCW' && $Plat ne 'ARMV5' && !$IsPlatCustomization && $Plat ne 'GCCE' && $Plat ne 'ARMV5_ABIV2' && $Plat ne 'ARMV5_ABIV1') { 
+		&main::FatalError("Platform module - ABI \"$ABI\" unrecognised");
+	}
+	
+	if ($Plat ne 'WINSCW') {
+		@CompatibleABIs=@{$CompatibleABIs{$UnderlyingABI}};
+	}
+
+#	set up CompatibleABI lib path hash
+	foreach (@CompatibleABIs) {
+		$ABILibPath{$_}=&main::Path_Strip("$LibPath..\\..\\$_\\");
+	}
+
+	$Dlltool=$ToolPrefix.'dlltool.exe';
+	$Archive=$ToolPrefix.'ar.exe';
+	$Link=$ToolPrefix.'ld.exe';
+	$Objcopy=$ToolPrefix.'objcopy.exe';
+
+	my $WarningLevelCW=&main::CompilerOption("CW");
+
+	$xmlFileList = newList($xmlTarget,"FILELIST",1);
+	$xmlFileList->addText("\n");
+
+	$xmlLinkOrder = newList($xmlTarget,"LINKORDER",1);
+	$xmlLinkOrder->addText("\n");
+
+	# Create temporary sublists, which will be
+	# removed during finaliseProject
+
+	$xmlSourceGroup = newList($xmlTarget,"SOURCEGROUP",0);
+	$xmlSourceGroup->setAttribute("TARGET", $targetname);
+	$xmlSourceGroup->addText("\n");
+
+	$xmlHeadersGroup = newList($xmlTarget,"HEADERSGROUP",0);
+	$xmlHeadersGroup->setAttribute("TARGET", $targetname);
+	$xmlHeadersGroup->addText("\n");
+
+	$xmlRootGroup = newList($xmlTarget,"ROOTGROUP",0);
+	$xmlRootGroup->setAttribute("TARGET", $targetname);
+	$xmlRootGroup->addText("\n");
+		
+	$xmlLinkGroup = newList($xmlTarget,"LINKGROUP",0);
+	$xmlLinkGroup->setAttribute("TARGET", $targetname);
+	$xmlLinkGroup->addText("\n");
+
+	$xmlLibGroup = newList($xmlTarget,"LIBGROUP",0);
+	$xmlLibGroup->setAttribute("TARGET", $targetname);
+	$xmlLibGroup->setAttribute("PLAT", $Plat);
+	$xmlLibGroup->addText("\n");
+
+	$xmlResourcesGroup = newList($xmlTarget,"RESOURCESGROUP",0);
+	$xmlResourcesGroup->setAttribute("TARGET", $targetname);
+	$xmlResourcesGroup->addText("\n");
+
+	$xmlDocumentsGroup = newList($xmlTarget,"DOCUMENTSGROUP",0);
+	$xmlDocumentsGroup->setAttribute("TARGET", $targetname);
+	$xmlDocumentsGroup->addText("\n");
+
+	my $debug="";
+	$debug="Debug" if ($Bld =~ /DEB$/);
+
+	my @RuntimeLibs = ();	# add platform-specific runtime libraries here
+	if (&main::PlatCompiler eq "GCC32")
+		{
+		if ($BasicTrgType=~/^DLL$/o) 
+			{ # Add the DLL stub library
+			push @RuntimeLibs, "EDLLSTUB.LIB";
+			}
+		if ($BasicTrgType=~/^(DLL|EXE)/o) 
+			{ # Add the GCC helper fns
+			push @RuntimeLibs, "EGCC.LIB";
+			}
+		}
+	
+	if ($Plat eq "GCCE" || $CustGCCE)
+		{
+			push @RuntimeLibs, "usrt2_2.lib";    # UDEB/UREL Specific
+			push @RuntimeLibs, "dfpaeabi.dso";
+			push @RuntimeLibs, "dfprvct2_2.dso";
+			push @RuntimeLibs, "drtaeabi.dso"; 
+			push @RuntimeLibs, "scppnwdl.dso"; 
+			push @RuntimeLibs, "drtrvct2_2.dso";
+			if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
+				push @RuntimeLibs, "EDLLSTUB.LIB";   # UDEB/UREL Specific
+				}
+		}
+
+	addFile(&main::Path_Split('File',$MmpFile), "Text", "", "", "Root");
+
+	# Create the uid.cpp file	
+	if ($Plat eq "WINSCW" && $BasicTrgType=~/^(EXE|DLL)$/oi)
+		{
+		my @UidList=&main::UidList;
+		
+		# create the UID source file
+		my $priority = "EPriorityForeground";
+		if (&main::ProcessPriority) {
+			$priority="EPriority".&main::ProcessPriority;
+		}
+
+		my $UidText=join(
+			"\n",
+			'// Makmake-generated uid source file',
+			'#include <e32cmn.h>',
+			'#pragma data_seg(".SYMBIAN")',
+			'__EMULATOR_IMAGE_HEADER2('
+		);
+		foreach (@UidList) {
+			$UidText.="$_,";
+		}
+		my $vstr = "0x".&Genutl_VersionToHexString(&main::Version);
+		my $vid = &main::VendorId;
+		if(!$vid) { $vid="0"; }
+		$UidText.="$priority,".(&main::CapabilityFlags)[0]."u,".(&main::CapabilityFlags)[1]."u,".&main::SecureId.",".$vid.",$vstr,";	# second capability word always 0 for now
+		if (&main::AllowDllData) {
+			$UidText.="1,";
+		} else {
+			$UidText.="0,";
+		}
+		chop $UidText;
+		$UidText.=")\n";
+		$UidText.="#pragma data_seg()\n";
+
+		$UIDFile = $BaseTrg.'_UID_.cpp';
+		&main::CreateExtraFile("${ExtraFilesPath}$UIDFile", $UidText);
+		}
+
+
+	if (-e $DefFile)
+		{
+		addFile(&main::Path_Split('File',$DefFile), "Text", "", &main::DefFileType."\\");
+		}
+
+	# Add resources: rsc files, mbm files and aif files
+
+	my $mmpdir = &main::Path_Split('Path',$MmpFile);
+	$changedsettings{"SymbianResourcesMMPFileLocation"} = "{0}$mmpdir";
+	my $ResourcesText="";
+	my @ResourceDownloadList=();
+	
+	# --- MBM files
+	
+	my $BitMapStructRef = &main::BitMapStructRef();
+	my $BitMapRef;
+	
+	foreach my $BitMapRef (@$BitMapStructRef) {
+		my $trgfile = $$BitMapRef{Trg};
+# change - only use colour resource files
+		next if ($trgfile =~ /\.MBW$/i);	# ignore greyscale MBM files
+		$trgfile =~ s/\.MCL$/.MBM/;			# convert MCL to MBM for immediate use
+		my $entry = "  <mbm targetfile = \"$trgfile\"";
+		$entry .= " targetpath = \"".&main::Path_Chop($$BitMapRef{TrgPath})."\"";
+		push @ResourceDownloadList, $$BitMapRef{TrgPath}.$trgfile;
+		if (defined $$BitMapRef{Hdr})
+			{
+			$entry .= " header = \"true\"";
+			}
+		else
+			{
+			$entry .= " header = \"false\"";
+			}
+		$entry .= ">\n";
+		foreach my $SrcRef (@{$$BitMapRef{Source}}) {
+			$entry .= "    <bmp bpp = \"$$SrcRef{ClDepth}\"";
+			my $bmpfile = &main::Path_Split('File',$$SrcRef{Src});
+			my $bmppath = &main::Path_Split('Path',$$SrcRef{Src});
+			my $sourcepath = &main::Path_Chop(&main::Path_MakeRltToBase($mmpdir,$bmppath));
+			$entry .= " sourcepath = \"$sourcepath\"";
+			$entry .= " sourcefile = \"$bmpfile\"/>\n";
+		}
+		$ResourcesText .= $entry . "  </mbm>\n";
+	}
+	
+	# --- AIF files
+
+	my $AifStructRef = &main::AifStructRef();
+	my $AifRef;
+
+	foreach $AifRef (@$AifStructRef) {
+# regression change - workaround lack of AIF directory
+		my $trgpath=&main::TrgPath;
+		my $trgfile=&main::Path_Split('File',$$AifRef{Trg});
+		my $path=&main::Path_Split('Path',"$trgpath$$AifRef{Trg}");
+		$path=&main::Path_Chop($path);  
+# change - only use colour resource files
+		next if ($trgfile =~ /\.ABW$/i);	# ignore greyscale AIF files
+		$trgfile =~ s/\.ACL$/.AIF/;			# convert ACL to AIF for immediate use
+ 		my $rssfile = &main::Path_Split('File',$$AifRef{Source});
+ 		my $rsspath = &main::Path_Split('Path',$$AifRef{Source});
+ 		my $sourcepath=&main::Path_Chop(&main::Path_MakeRltToBase($mmpdir,$rsspath));
+ 		my $entry = "  <aif sourcefile = \"$rssfile\"";
+   		$entry .= " sourcepath = \"$sourcepath\"";
+   		$entry .= " targetfile = \"$trgfile\" targetpath = \"$path\">\n";
+   		push @ResourceDownloadList, "$path\\$trgfile";
+ 		foreach my $BitmapRef (@{$$AifRef{BitMaps}}) {
+ 			$entry .= "    <bmp bpp = \"$$BitmapRef{ClDepth}\"";
+ 			my $bmpfile = &main::Path_Split('File',$$BitmapRef{Src});
+ 			my $bmppath = &main::Path_Split('Path',$$BitmapRef{Src});
+ 			$sourcepath = &main::Path_Chop(&main::Path_MakeRltToBase($mmpdir,$bmppath));
+ 			$entry .= " sourcepath = \"$sourcepath\"";
+ 			$entry .= " sourcefile = \"$bmpfile\"/>\n";
+		}
+   		$ResourcesText .= $entry . "  </aif>\n";
+
+   	}
+
+	
+	# --- RSC files, which must come after .MBM files since they may use the .MBG header files
+	
+	my $ResourceStructRef=&main::ResourceStructRef;
+	my @resourcefiles;
+	my %resourcetargets;
+
+	# NOTE: An <rsc/> block is now created for each START RESOURCE blocks LANG entries.  This
+	# shouldn't be necessary as <rsc/> blocks support multiple <language/> tags, and the generation
+	# of separate localised binaries should be dealt with by the Symbian Resources IDE plugin.
+	# However, a defect in the plugin's processing of <rsc/> "targetfile" attributes means that is
+	# doesn't correctly generate separate localised binaries with per-LANG extensions.
+
+	my %headerProcessed;
+
+	foreach my $ResourceRef (@$ResourceStructRef) {
+		my $fullsource=$$ResourceRef{Source};
+		my $rssfile=&main::Path_Split('File', $fullsource);
+		my $rsspath=&main::Path_Split('Path', $fullsource);
+		my $entry = "  <rsc sourcefile = \"$rssfile\"";
+		$entry .= " targetpath = \"".&main::Path_Chop($$ResourceRef{TrgPath})."\"";
+		
+		#############################################################
+		# if CW version is 3.1 or greater, add TARGET file if present
+		# tkelly 4-May-05
+		if ($CW_major_version >= 3.1)
+		{
+			my $trgfile=&main::Path_Split('File',$$ResourceRef{Trg}); 
+			$entry .= " targetfile = \"$trgfile\"\n"; #tk
+		}
+		##############################################################
+		if ((defined $$ResourceRef{Hdr}) && (!$headerProcessed{$fullsource}))
+			{
+			$entry .= " header = \"true\"";
+			$headerProcessed{$fullsource} = 1;
+			}
+		else
+			{
+			$entry .= " header = \"false\"";
+			}
+		my $sourcepath=&main::Path_Chop(&main::Path_MakeRltToBase($mmpdir,$rsspath));
+		$entry .= " sourcepath = \"$sourcepath\">\n";
+		# ignore the UidList for now..
+		$resourcetargets{$fullsource} = $$ResourceRef{TrgPath}.&main::Path_Split('Base', $rssfile);
+
+		$entry .= "    <language id = \"$$ResourceRef{Lang}\"/>\n";
+		push @resourcefiles, $entry;
+		push @ResourceDownloadList, $resourcetargets{$fullsource}.".R".$$ResourceRef{Lang};
+	}
+
+ 	foreach my $resourceEntry (@resourcefiles) {	
+ 			$ResourcesText .= $resourceEntry . "  </rsc>\n";
+ 			}
+
+	# --- If required, generate .resources file per platform
+	
+	if ($ResourcesText ne "")
+		{
+		my $resourcesfile = "$BaseTrg$Plat.resources";
+		&main::CreateExtraFile("${ExtraFilesPath}$resourcesfile", "<resources>\n$ResourcesText</resources>\n");
+		addFile($resourcesfile, "Text", "", "", "Resources");
+		}
+		
+	# Build the rest of the file list
+
+	if ($BasicTrgType!~/^LIB$/o)
+		{
+		addFile($FirstLib, "Library", $debug, "$Bld\\");	# static library, build-specific
+		}
+	
+	my $file;
+	foreach $file (@SrcList)
+		{
+		# ensure the case of the extension is what GCC expects
+		$file =~ s/\.CPP$/.cpp/i;
+		$file =~ s/\.C$/.c/i;
+		$file =~ s/\.s$/.S/i;
+		my $srcfile=&main::Path_Split('File',$file);
+		addFile($srcfile, "Text", $debug, "");
+		}
+
+	# If required, add the uid.cpp file so that it appears after all other source files in the link order
+	if (defined $UIDFile)
+		{
+		addFile($UIDFile, "Text", "", "");
+		}
+	
+	if ($Plat ne "GCCE" && !$CustGCCE)
+	{
+	# linking with GCCE, Runtime libs need to be at the end to match with make, otherwise evalid can fail.
+	foreach $file (@RuntimeLibs)
+		{
+		next if ( $file eq $FirstLib );		#skip if file equals FirstLib.
+		addFile($file, "Library", $debug, "$Bld\\"); # static library, build specific
+		}
+	}
+				
+	foreach $file (@StatLibList)
+		{
+		next if ( $file eq $FirstLib );		#skip if file equals FirstLib.
+		addFile($file, "Library", $debug, "$Bld\\"); # static library, build specific
+		}
+	foreach $file (@ASSPLibList, @LibList)
+		{
+		next if ( $file eq $FirstLib );		#skip if file equals FirstLib.
+		if ($Plat eq "GCCE" or $ABIV2 or $CustGCCE) {
+			$file =~ s/\.LIB$/.DSO/;
+			$file =~ s/\.lib$/.dso/;
+			}
+		addFile($file, "Library", $debug, "");
+		}
+		
+	if ($Plat eq "GCCE" || $CustGCCE)
+	{
+		foreach $file (@RuntimeLibs)
+		{
+			next if ( $file eq $FirstLib );		#skip if file equals FirstLib.
+			
+			#change to prevent multiple libs being listed when they are shared between targets.
+			if ($file eq "usrt2_2.lib" || $file eq "EDLLSTUB.LIB") {
+				addFile($file, "Library", $debug, "$Bld\\"); # static library, build specific
+			}
+			else {
+				addFile($file, "Library", $debug, ""); # static library, build non-specific
+			}
+		}
+	}
+		
+	if ($Plat eq "WINSCW")
+		{
+		my $defaults = $ENV{'MWSym2LibraryFiles'};
+		# look out for paths?
+		foreach $file (@Win32LibList)
+			{
+			# skip default libs and FirstLib
+			next if ( ($defaults =~ /;$file/) || ($file eq $FirstLib) );
+			addFile($file, "Library", $debug, "");
+			}
+		}
+
+	
+	# Update the project settings
+
+	$changedsettings{"UserSourceTrees"} = "{}";
+	$changedsettings{"UserSearchPaths"} = "{}";
+	$changedsettings{"SystemSearchPaths"} = "{}";
+	$changedsettings{"Targetname"} = $targetname;
+
+	my $outputdir = $RelPath;
+	if ($Plat eq "WINSCW")
+		{
+		my $trgpath = &main::TrgPath;
+		&Winutl_AdjustTargetPath(\$trgpath);
+		$outputdir .= $trgpath;
+		}
+	$changedsettings{"OutputDirectory"} = "{1}".&main::Path_Chop($outputdir);
+	$changedsettings{"SymbianInstallationContentSearchLocation"} = "{0}".&main::Path_Chop($RelPath);
+
+	$changedsettings{"SymbianResourcesHeaderFileOutputLocation"} = "{0}".&main::Path_Chop(&main::EPOCIncPath());
+	if ($Plat eq "WINSCW")
+		{
+		$changedsettings{"SymbianResourcesBinaryOutputLocation"} = "{0}".&main::Path_Chop($RelPath);
+		}
+	else
+		{
+		$changedsettings{"SymbianResourcesBinaryOutputLocation"} = "{0}".&main::Path_Chop(&main::EPOCDataPath());
+		}
+		
+	if ($Plat eq "WINSCW")
+		{
+		if ($TrgType eq "EXE")
+			{	
+			# IDE would do the right thing, but we might as well make sure...
+			$changedsettings{"MWRuntimeSettings_HostApplication"} = "{0}$outputdir$Trg";
+			}
+		else
+			{
+			$changedsettings{"MWRuntimeSettings_HostApplication"} = "{0}${RelPath}epoc.exe";
+			}
+		}
+
+
+	$changedsettings{"SymbianEpocToolsPath"} = "{0}${epocroot}";
+
+	if ($Plat ne "WINSCW")
+		{
+		my $downloadpath = &main::TrgPath;
+		if (&main::EPOCSecurePlatform && $downloadpath !~ /^Z\\sys\\bin\\/)
+			{
+			my @hrhMacros = &Variant_GetMacroList;
+			if (grep /^SYMBIAN_IGNORE_BIN_TARGETPATH\s*$/, @hrhMacros)
+				{
+				$downloadpath = "Z\\sys\\bin\\";
+				}
+			}
+		$downloadpath =~ s/^Z\\/C:\\/i;
+		$changedsettings{"DownloadPath"} = $downloadpath;
+		$changedsettings{"FileList"} = "{}";
+		}
+
+	my @MacroList;
+
+	@MacroList = &main::MacroList();			
+		
+	push @MacroList, "__${Plat}__" if ($Plat ne $ABI);
+	push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__" if ($Plat eq "WINSCW");
+	push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__" if (($Plat eq "ARMV5") || ($Plat eq "ARMV5_ABIV2") || ($Plat eq "ARMV5_ABIV1") || ($Plat eq "GCCE") || $IsPlatCustomization);
+
+	# Symbian Compiler Panel
+			
+	my $compiler="";
+	my $compilerargs="";
+	my $macros="";
+
+	if ((($Plat eq "ARMV5") || ($Plat eq "ARMV5_ABIV2") || ($Plat eq "ARMV5_ABIV1") || ($Plat eq "GCCE") || $IsPlatCustomization) && $VariantFile)
+		{
+		push @MacroList, '__PRODUCT_INCLUDE__=\\"'.&main::Path_Split('File',$VariantFile).'\\"' if $VariantFile;
+		}
+
+	foreach (@MacroList)
+		{
+		$_ =~ s/\s+$//;
+		$_ =~ s/^\s+//;
+		$macros .= "$_,";
+		}
+
+###############################
+# WINSCW compilation settings #
+###############################
+
+	if ($Plat eq "WINSCW")
+		{
+		$compiler = "WINSCW";
+		$compilerargs .= "-wchar_t off -align 4 -warnings on -w nohidevirtual, nounusedexpr -msgstyle gcc -enum int -str pool ";
+		$compilerargs .= "-exc ms ";
+		$compilerargs .= "-trigraphs on ";
+
+		if ($Bld =~ /DEB/)
+			{
+			$compilerargs .= "-O0 ";
+
+			# euser change to apply inlining on the _NAKED functions
+			if ($BaseTrg !~ /^EUSER$/oi)
+				{
+				$compilerargs .= "-inline off ";
+				}
+			}
+		else
+			{
+			$compilerargs .= "-O4,s ";
+			}
+			
+		if ($Win32StdHeaders || $Win32Resrc ) 
+			{
+			$macros .= "WIN32,_WINDOWS,";
+			# Callisto defect workaround
+			# NOTE: persisting with this for consistency
+			$compilerargs .= "-stdinc ";
+			}
+		else
+			{
+			$compilerargs .= "-nostdinc ";
+			}
+				
+		$compilerargs .= &main::CompilerOption("CW");
+		$changedsettings{"Macros"} = $macros;
+		if ($VariantFile)
+			{
+			$changedsettings{"PrefixFile"} = &main::Path_Split('File',$VariantFile);
+			}			
+		}
+
+#############################
+# RVCT compilation settings #
+#############################
+		
+	elsif ((($Plat eq "ARMV5") || ($Plat eq "ARMV5_ABIV2") || ($Plat eq "ARMV5_ABIV1") || $ABIV1 || $ABIV2) && ($CW_major_version >= 3)) #|| $IsPlatCustomization
+		{
+		
+		if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
+			$changedsettings{"CompilerXMLDescriptor"} = "ARM RVCT";
+		}
+		else {
+			if(($CW_major_version == 3))
+			{ 
+				$changedsettings{"CompilerXMLDescriptor"} = "ARM RVCT";
+			}
+			else
+			{
+				# RVCT 2.2
+				$changedsettings{"CompilerXMLDescriptor"} = "ARM RVCT2_2";
+			}
+		}	
+		if ($Bld =~ /REL$/)
+			{
+				$compilerargs .= $configdata{"REL_OPTIMISATION"}." ".$configdata{"RUNTIME_SYMBOL_VISIBILITY_OPTION"}.$CCUREL;		
+			}
+		else
+			{
+			unless (&main::SrcDbg)
+				{
+					$compilerargs .= $configdata{"DEBUG_OPTIMISATION"}." ".$configdata{"RUNTIME_SYMBOL_VISIBILITY_OPTION"}.$CCUDEB;		
+				}
+			}
+		$changedsettings{"PrefixFile"} = &main::Path_Split('File',$PrefixFile);
+		}
+
+############################
+# GCC compilation settings #
+############################
+		
+	elsif ($Plat eq "ARM4")
+		{
+		$compiler = "ARM";
+			
+		if ($Bld =~ /REL$/)
+			{
+			$compilerargs .= "-s -fomit-frame-pointer -O "
+			}
+		else
+			{
+			unless (&main::SrcDbg)
+				{
+				$compilerargs .= "-O ";
+				}
+			}
+		
+		if ($ABI eq "ARMI")
+			{
+			$compilerargs .= "-march=armv4t -mthumb-interwork";
+			}
+		elsif ($ABI eq "ARM4T")
+			{
+			if (&main::BuildAsARM)
+				{
+				$compilerargs .= "-march=armv4t -mthumb-interwork";
+				}
+			elsif ($SystemTrg)
+				{
+				$compilerargs .= "-march=armv4";
+
+				unless (&main::PlatABI eq "ARM4")
+					{
+					$compilerargs .= "t";
+					}
+				}
+			else
+				{
+				$compiler = "THUMB";
+				$compilerargs .= "-mthumb-interwork";
+				$macros .= "__MARM_THUMB__,";
+				}
+			}
+		elsif ($ABI eq "ARM4")
+			{
+			$compilerargs .= "-march=armv4";
+
+			unless (&main::PlatABI eq "ARM4")
+				{
+				$compilerargs .= "t";
+				}
+			}
+		elsif ($ABI eq "THUMB")
+			{
+			$compiler = "THUMB";
+			$compilerargs .= "-mthumb-interwork";
+			}
+	
+		if ($VariantFile)
+			{
+			$changedsettings{"PrefixFile"} = &main::Path_Split('File',$VariantFile);
+			}
+		}
+
+############################
+# GCCE BPABI compilation settings #
+############################
+
+		
+	elsif ((($Plat eq "GCCE") || $CustGCCE)) # || $IsPlatCustomization) && ($CW_major_version >= 3)) 
+		{
+		$compiler = "ARM GCCE";
+		#Change setting CompilerXMLDescriptor is only good for CW 3.0 and greater.
+		$changedsettings{"CompilerXMLDescriptor"} = "ARM GCCE";	
+		
+		if ($Bld =~ /REL$/)
+		{
+			$compilerargs .= $configdata{"REL_OPTIMISATION"}." ".$configdata{"RUNTIME_SYMBOL_VISIBILITY_OPTION"}.$CCUREL;
+		}
+		else
+		{
+			unless (&main::SrcDbg)
+			{
+				$compilerargs .= $configdata{"DEBUG_OPTIMISATION"}." ".$configdata{"RUNTIME_SYMBOL_VISIBILITY_OPTION"}.$CCUDEB
+			}
+		}
+		$changedsettings{"PrefixFile"} = &main::Path_Split('File',$PrefixFile);
+		}
+####################
+# General settings #
+####################
+
+	$macros =~ s/,$//;
+	$compilerargs =~ s/ $//;
+
+	$changedsettings{"Compiler"} = $compiler; # in CW 3.0, "Compiler" no longer exists. This line has no effect on those versions
+	$changedsettings{"Arguments"} = $compilerargs;
+
+	# Symbian Linker Panel
+	$changedsettings{"LinkOutputFile"} = $Trg;
+	
+	if ($Plat eq "GCCE" || $CustGCCE || $ABIV2) {
+		$changedsettings{"SymbianImportLibrary"} = $ExportLibrary.'.dso';
+	}
+	else {
+		$changedsettings{"SymbianImportLibrary"} = $ExportLibrary.'.lib';
+	}
+	
+	# Template defaults for canDebug/canRun are both "true"
+	if ($Bld =~ /REL/)
+		{
+		$changedsettings{"canDebug"} = "false";
+		}
+
+	if ($Plat eq "WINSCW")
+		{
+		if ($TrgType ne "APP" && $TrgType ne "EXE" && $TrgType ne "EXEDLL" && $TrgType ne "EPOCEXE")
+			{
+			$changedsettings{"canDebug"} = "false";
+			$changedsettings{"canRun"} = "false";
+			}
+		}
+	else
+		{
+		$changedsettings{"canRun"} = "false";
+
+		if ($TrgType eq "LIB" || $TrgType eq "KLIB")
+			{
+			$changedsettings{"canDebug"} = "false";
+			}
+		}
+		
+		
+	$xmlLinkDescriptorDoc = $xmlParser->parsefile ($FindBin::Bin."\\$linkDescriptorTemplate");
+	$xmlLinkDescriptorCommandParent = $xmlLinkDescriptorDoc->getElementsByTagName("array",1)->item(0);
+
+	if ($CW_major_version >= 3)
+		{
+		$xmlLinkDescriptorSymbolParent = $xmlLinkDescriptorDoc->getElementsByTagName("array",1)->item(1);
+		$xmlLinkDescriptorDumpFileParent = $xmlLinkDescriptorDoc->getElementsByTagName("array",1)->item(2);
+		}
+	
+	my $linkDescriptorFile = "$BaseTrg$Plat$Bld.cwlink";
+
+	my $copyCommand = 'perl.exe -S ecopyfile.pl ';
+	my $deleteCommand = 'cmd.exe /C del ';
+
+	my $tempFilenameRoot = '${var:IMPORT_LIBRARY_NO_EXT}';
+
+	if ($CW_major_version < 3)
+		{
+		$tempFilenameRoot = $ExportLibrary;
+		}	
+
+	my $exportUnfrozenWarningMessage = 'Created "${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}" '.
+										'from "${target.data}\\'.$tempFilenameRoot.'.def" as EXPORTUNFROZEN specified.';
+
+
+
+############################################
+# WINSCW library generation and link stage #
+############################################
+
+	if ($Plat eq "WINSCW")
+		{
+		# Generate library
+		if ($DefFile and !$NoExportLibrary)
+			{
+			unless (&main::ExportUnfrozen)
+				{
+					my $LibLinkAs = ($BasicTrgType=~/^IMPLIB$/io) ? $LinkAs : $Trg;
+
+					$linkCommand = 'perl.exe -S prepdef.pl "${var:DEF_FILE}" "${target.data}\\'.$tempFilenameRoot.'.prep.def"';
+					addLinkDescriptorCommand ($linkCommand);
+
+					$linkCommand = 'mwldsym2.exe "${target.data}\\'.$tempFilenameRoot.'.prep.def" -importlib -o "'.
+									'${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}" -addcommand "out:'.$LibLinkAs.'" -warnings off';
+					addLinkDescriptorCommand ($linkCommand);
+				}
+			}
+
+		if ((2.8 == $CW_major_version) && (0 == $CW_minor_version))
+			{
+			# For OEM2.8, create a file containing all objects required in the link.  This is used in all
+			# calls to mwldsym2 in order to avoid exceeding the Windows command line
+			# length in projects containing a large amount of source files
+			$linkCommand ='cmd.exe /C echo ${var:LINK_OBJS}>"${target.data}\${output.file.root}.lst"';
+			addLinkDescriptorCommand ($linkCommand);
+			}
+			
+		my $stage1linkflags = "";
+		my $linkflags = "";
+		my $commonLinkFlags = '-msgstyle gcc -stdlib';
+		my $libPath = "epoc32\\release\\winscw\\".lc $Bld;
+		if ($SystemTrg){
+			$commonLinkFlags .=" ${libPath}\\scppnwdl_kern.lib";
+		}
+		else{
+			$commonLinkFlags .=" ${libPath}\\scppnwdl.lib";
+		}
+		if ($BasicTrgType=~/^(EXE|DLL)$/o) {
+					$commonLinkFlags .= ' ${var:FIRST_LIB} '
+			}
+
+		foreach my $lib (@Win32LibList)
+			{
+			my $win32lib = $lib;
+			$win32lib = "-l$win32lib" unless ($win32lib =~ /\\/);
+			$commonLinkFlags .= " ". lc $win32lib;
+			}
+
+		if ($BasicTrgType =~ /^DLL$/o || $TrgType =~ /^EXEXP$/o)
+			{
+			if ($BaseAddress ne "")
+				{
+				$commonLinkFlags .= " -imagebase $BaseAddress";
+				}
+			
+			$commonLinkFlags .= ' -noentry -shared';
+			}
+		elsif ($BasicTrgType =~ /^EXE$/o)
+			{
+			$commonLinkFlags .= ' -m "?_E32Bootstrap@@YGXXZ"';
+			}
+
+		$commonLinkFlags .= ' -subsystem windows';
+
+		if (&main::HeapSize)
+			{
+			my %HeapSize = &main::HeapSize;
+			$commonLinkFlags .= ' -heapreserve='.RoundUp1k($HeapSize{Max}).' -heapcommit='.RoundUp1k($HeapSize{Min}); 
+			}
+
+		if ($BasicTrgType =~ /^(DLL|EXE)$/o)
+			{
+			if ($Bld =~ /DEB$/o)
+				{
+				$commonLinkFlags .= ' -g';
+				}
+			}
+			
+		my $EntrySymbol='';
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o)
+			{
+			my $Include="";
+			if ($BasicTrgType=~/^DLL$/o)
+				{
+				$Include="-m __E32Dll";
+				$EntrySymbol='__E32Dll';
+				}
+			else
+				{
+				$Include="-m __E32Startup";
+				$EntrySymbol='__E32Startup';
+				}
+				
+			$stage1linkflags = $commonLinkFlags.' ${var:LIBS}'.
+				' -o "${target.data}\\${output.file.name}"'. 
+				' -export dllexport '.
+				$Include.
+				' -nocompactimportlib'. 
+				' -implib "${target.data}\\${var:IMPORT_LIBRARY}"'.
+				' -addcommand "out:${output.file.name}"'.
+				' -warnings off';
+			}
+				
+		my $AbsentSubst = "";
+		if ($EntrySymbol)
+			{
+			$AbsentSubst = " -absent $EntrySymbol";
+			}
+
+		$linkflags = $commonLinkFlags.' ${var:LIBS}'.
+			' -o "${output}\\${output.file.name}"';
+			
+		if ($Bld=~/REL$/o && $BasicTrgType!~/^LIB$/o)
+			{
+			# Generate map file for release build executables
+			$linkflags .= ' -map "${output}\\${output.file.name}.map"';
+			}
+		
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o)
+			{
+			$linkflags .= ' -f "${target.data}\\'.$tempFilenameRoot.'.def"';
+			
+			if (&main::ExportUnfrozen)
+				{
+				$linkflags .= ' -implib "${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}"'.
+					' -addcommand "out:${output.file.name}" -warnings off';
+				}
+			else
+				{
+				$linkflags .= ' -noimplib ';
+				}
+			}
+			else
+			{
+			$linkflags .= ' -noimplib ';
+			}
+
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o)
+			{
+			if (($CW_major_version >= 3) ||
+				((2.8 == $CW_major_version) && ($CW_minor_version >= 1)))
+				{
+				# For OEM2.8.1 onwards, make use of ${var:LINK_OBJS_NO_PATH} in order to reduce link
+				# command line lengths
+				$linkCommand = 'mwldsym2.exe '.$stage1linkflags.' ${var:COMMON_LINK_FLAGS} -l "${target.data}\\ObjectCode" -search ${var:LINK_OBJS_NO_PATH}';				
+				}
+			else
+				{
+				$linkCommand = 'mwldsym2.exe '.$stage1linkflags.' ${var:COMMON_LINK_FLAGS} @"${target.data}\${output.file.root}.lst"';
+				}
+
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+				
+			$linkCommand = $deleteCommand.'"${target.data}\\${output.file.name}"';
+			addLinkDescriptorCommand ($linkCommand);
+
+			my $show_options = 'names,unmangled,verbose';
+			$linkCommand = 'mwldsym2.exe -S -show only,'.$show_options.' -o "${target.data}\\'.$tempFilenameRoot.'.inf" "${target.data}\\${var:IMPORT_LIBRARY}"';
+			addLinkDescriptorCommand ($linkCommand);
+
+			$linkCommand = 'perl.exe -w -S makedef.pl '.$AbsentSubst.' -Inffile "${target.data}\\'.$tempFilenameRoot.'.inf"';
+			if (-e $DefFile)
+				{
+				$linkCommand .= ' -Frzfile "'.$DefFile.'"';
+				}
+				
+			my $Export;
+			my $Ordinal=1;
+			foreach $Export (&main::Exports)
+				{
+				$linkCommand .= " -$Ordinal $Export";
+				$Ordinal++;
+				}					
+
+			$linkCommand .= ' "${target.data}\\'.$tempFilenameRoot.'.def"';					
+			addLinkDescriptorCommand ($linkCommand);
+			
+			$linkCommand = $deleteCommand.'"${target.data}\\'.$tempFilenameRoot.'.inf"';
+			addLinkDescriptorCommand ($linkCommand);
+			
+			$linkCommand = $deleteCommand.'"${target.data}\\${var:IMPORT_LIBRARY}"';
+			addLinkDescriptorCommand ($linkCommand);
+			}
+
+		$linkCommand = "mwldsym2.exe ";
+
+		if ($BasicTrgType =~/^LIB$/o)
+			{
+			$linkCommand .= '-library ';
+			}
+
+		if (($CW_major_version >= 3) ||
+			((2.8 == $CW_major_version) && ($CW_minor_version >= 1)))
+			{
+			# For OEM2.8.1 onwards, make use of ${var:LINK_OBJS_NO_PATH} in order to reduce link
+			# command line lengths
+			$linkCommand .= $linkflags.' ${var:COMMON_LINK_FLAGS} -l "${target.data}\\ObjectCode" -search ${var:LINK_OBJS_NO_PATH}';	
+			}
+		else
+			{
+			$linkCommand .= $linkflags.'${var:COMMON_LINK_FLAGS} @"${target.data}\${output.file.root}.lst"';				
+			}
+
+		my $warningMessage;
+		
+		if (&main::ExportUnfrozen)
+			{
+			$warningMessage = $exportUnfrozenWarningMessage;
+			}
+
+		if ($BasicTrgType =~/^LIB$/o)
+			{				
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef, $warningMessage);
+			}
+		else
+			{
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib, $warningMessage);
+			}
+
+		if (&Winutl_CopyForStaticLinkage)
+			{
+			$linkCommand = $copyCommand.
+							'"${output}\\${output.file.name}" '.
+							'"${var:KIT_EPOCROOT}'.kitRelativePath($RelPath).'${output.file.name}"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+			}
+		}
+
+##########################################
+# RVCT library generation and link stage #
+##########################################
+
+	elsif ($ABIV1 && ($CW_major_version >= 3)) 
+		{
+		my $InterWorking = ($ABI eq 'ARMV4') ? "" : "--inter";
+			
+		# Generate library
+
+		if ($DefFile and !$NoExportLibrary)
+			{
+			unless (&main::ExportUnfrozen)
+				{
+				$linkCommand = 'perl.exe -S prepdef.pl "${var:DEF_FILE}" "${target.data}\\'.$tempFilenameRoot.'.prep.def"';
+				addLinkDescriptorCommand ($linkCommand);
+
+				$linkCommand = 'def2dll.bat --path="${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'\\" --bldpath="${target.data}" --import='.$tempFilenameRoot.' '.
+					'--deffile="${target.data}\\'.$tempFilenameRoot.'.prep.def" --linkAs='.$LinkAs.' '.$InterWorking;
+				addLinkDescriptorCommand ($linkCommand);
+
+				if ($ExtraExportLibrary)
+					{
+					$linkCommand = $copyCommand.'"${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}" '.
+									'"${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).$ExtraExportLibrary.'.lib"';
+					addLinkDescriptorCommand ($linkCommand,"false", "false");
+					}
+				}
+			}
+
+		return if ($BasicTrgType=~/^IMPLIB$/io);
+		
+
+		# Create custom symbols only required in RVCT builds
+		my $implibs_no_path_vtblexport = "";
+
+		foreach my $lib (@LibList)
+			{
+			$implibs_no_path_vtblexport.="$lib(VtblExports.o) ";
+			}
+
+		addLinkDescriptorSymbol ('${var:IMPLIBS_NO_PATH_VTBLEXPORT}', $implibs_no_path_vtblexport);
+
+		my $AbsentSubst = '';
+		my $EntrySymbol;
+		my $Link = '';
+
+		if ($BasicTrgType=~/^DLL$/o) {
+			$EntrySymbol = '_E32Dll';
+		}
+		elsif ($BasicTrgType=~/^EXE$/o) {
+			$EntrySymbol = '_E32Startup';
+		}
+		if ($EntrySymbol) {
+			$AbsentSubst = " -absent $EntrySymbol";
+		}
+
+		$Link = 'armlink '.$oP.'diag_suppress 6331,6780'.$linkeropts.' ';
+
+		if ($Bld =~ /DEB$/o)
+			{
+			$Link .= ' '.$oP.'debug';
+			}
+
+
+	    # TARGET *.IN
+	    #------------
+
+		# Create "via" file containing all link objects in order to reduce link
+		# command line length
+		addLinkDescriptorDumpFile ('${var:LINK_OBJS}', '${target.data}\\${output.file.root}_'.$Bld.'_objects.via');
+		
+		if ($BasicTrgType!~/^LIB$/o) {
+			$linkCommand = $Link .' '.$oP.'partial -o ${var:COMMON_LINK_FLAGS} "${target.data}\\${output.file.root}.in" '.$oP.'via "${target.data}\\${output.file.root}_'.$Bld.'_objects.via"';
+			addLinkDescriptorCommand ($linkCommand);
+		}
+
+		# Perform link
+
+	    if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+	#		reorder the .DEF file taking frozen exports into account if there are any
+
+			$linkCommand = 'perl -S elf2inf.pl -o "${target.data}\\'.$tempFilenameRoot.'.inf" "${target.data}\\${output.file.root}.in"';
+			addLinkDescriptorCommand ($linkCommand);
+
+			$linkCommand = 'perl -S makedef.pl '.$AbsentSubst.' -Inf "${target.data}\\'.$tempFilenameRoot.'.inf"';
+
+	    	if (!$DefFile || $NoExportLibrary) {    			
+	    		$linkCommand .= ' -ignore_unfrozen_noncallable ';
+	    	}
+		if (SysTrg()) {
+	    		$linkCommand .= ' -SystemTargetType ';
+	    	}		
+		
+		    if (-e $DefFile) {	# effectively "if project frozen ..."
+		        $linkCommand .= " -Frzfile \"".'${var:DEF_FILE}'."\"";
+		    }
+		    # freeze ordinals, a maximum of 2, for polymorphic dlls
+		    my $Ordinal;
+		    my $Num=1;
+		    foreach $Ordinal (&main::Exports) {
+		    	$linkCommand .= " -$Num $Ordinal";
+			    $Num++;
+		    }
+
+		    $linkCommand.= ' "${target.data}\\'.$tempFilenameRoot.'.def"';
+		    addLinkDescriptorCommand ($linkCommand);
+    
+		    my $theDefFile = '"${target.data}\\'.$tempFilenameRoot.'.def"';
+		    $theDefFile = '"${var:DEF_FILE}"' if (-e $DefFile && !&main::ExportUnfrozen);
+
+			$linkCommand = 'def2dll.bat'.$AbsentSubst.' --path="${target.data}" --bldpath="${target.data}" --export='.$tempFilenameRoot.' --deffile='.$theDefFile.' --linkAs='.$LinkAs.' '.$InterWorking;
+			addLinkDescriptorCommand ($linkCommand);
+	    }
+
+        if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+#		generate an export object from the ordered .DEF file
+		if (&main::ExportUnfrozen) {
+			$linkCommand = 'def2dll.bat --path="${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'\\" --bldpath="${target.data}" --import='.$tempFilenameRoot.
+				' --deffile="${target.data}\\'.$tempFilenameRoot.'.def" --linkAs='.$LinkAs.' '.$InterWorking;
+		    addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef, $exportUnfrozenWarningMessage);
+			}
+        }
+
+#       get rid of any -symbols produced .map file
+        if ($BasicTrgType=~/^(DLL|EXE)/o) {
+			$linkCommand = $deleteCommand.'"${output}\\${output.file.name}.map"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false", undef, undef, undef, undef, (0,1));
+		}
+
+        if ($BasicTrgType=~/^(DLL|EXE)/o) {
+	        my $datalinkbase = "0x400000";
+	        $datalinkbase = &main::DataLinkAddress if (&main::DataLinkAddress);
+		
+	        $linkCommand = "$Link ".$oP.'shl '.$oP.'reloc '.$oP.'split '.$oP."rw-base $datalinkbase ".$oP.'noscanlib '."$PlatOpt{Ld}";
+	        
+	        if ($BasicTrgType=~/^DLL$/o) {
+	            # get the right object file for the entry point
+	            my $ObjFile = "UC_DLL_.o";
+	            if ($FirstLib =~ /EDEV/i) {
+		            $ObjFile = "D_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EKLL/i) {
+		            $ObjFile = "L_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EEXT/i) {
+		            $ObjFile = "X_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EVAR/i) {
+		            $ObjFile = "V_ENTRY_.o";
+	            }
+
+#		    If platform is a customization, take libs from parent directory.		   
+			$linkCommand .= $oP.'entry _E32Dll "'.$FirstLib.'('.$ObjFile.')"';
+		    if($IsCustomDll)
+		    {
+				$linkCommand .=	' "${target.data}\\'.$tempFilenameRoot.'.exp"';
+			}
+		    
+	        } elsif ($BasicTrgType=~/^EXE$/o || $TrgType=~/^EXEXP$/o) {
+			    # get the right object file for the entry point
+			    my $ObjFile = "UC_EXE_.o" ;
+			    if ($FirstLib =~ /KC_EXE/i) {
+					$ObjFile = "K_ENTRY_.o";
+			    }
+
+			if($IsPlatCustomization) 
+			{
+				$linkCommand .= $oP.'entry _E32Startup "'.$FirstLib.'('.$ObjFile.')"';
+			} 
+			else
+			{
+			    	$linkCommand .= $oP.'entry _E32Startup "'.$FirstLib.'('.$ObjFile.')"';
+			}
+		    
+			    if ($TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+					$linkCommand .= ' "${target.data}\\'.$tempFilenameRoot.'.exp"';
+				}
+			}
+
+			$linkCommand .= ' -o "${target.data}\\${output.file.name}"';
+
+			$linkCommand .= ' '.$oP.'symbols '.$oP.'list "${output}\\${output.file.name}.map"';
+			$linkCommand .= ' "${target.data}\\${output.file.root}.in"';
+
+
+			if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
+				if($IsPlatCustomization) 
+				{
+				if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB'.$RVCTVersion.'.LIB"';
+				}
+				else {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB.LIB"';
+				}
+				}
+				else
+				{
+				if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB'.$RVCTVersion.'.LIB"';
+				}
+				else {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB.LIB"';
+				}
+				}
+			}
+
+			$linkCommand .= ' ${var:LIBS}';
+			
+			
+			my $runtimeLibs = "";
+			my $StaticRTLib = "usrt".$RVCTVersion;
+			
+			# use ksrt for system code and for user ARM code
+			$StaticRTLib = "ksrt".$RVCTVersion if ($SystemTrg);
+			$runtimeLibs .= $StaticRTLib.".lib" unless ($Trg =~ /(U|K)SRT/i || ($BasicTrgType=~/^LIB$/o));
+		
+			unless ($ArmRT || ($BasicTrgType=~/^LIB$/o)) {
+				my $TargLib = "$ExportLibrary.lib";
+				$TargLib =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
+				unless ($SystemTrg) {
+					foreach (@RTLibList) {
+						$runtimeLibs .= " ".$_ unless ($_ =~ /$TargLib/i);
+					}
+			    }
+			}
+
+			foreach (@ArmLibList)
+				{
+				$runtimeLibs.= " ".$_;
+				}
+			
+			addLinkDescriptorSymbol ('${var:RUNTIME_LIBS}', $runtimeLibs);
+				
+			if($IsPlatCustomization) 
+			{
+			     $linkCommand .= ' --userlibpath "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\\'.$ParentPlat.'\\'.$Bld.'","${var:KIT_EPOCROOT}\\EPOC32\RELEASE\\'.$ParentPlat.'\LIB" ${var:RUNTIME_LIBS} ${var:IMPLIBS_NO_PATH_VTBLEXPORT}';
+			}
+			else
+				{
+				addLinkDescriptorSymbol ('${var:RUNTIME_LIBS}', 'usrt'.$RVCTVersion.'.lib dfpaeabi.lib dfprvct'.$RVCTVersion.'.lib dfprvct'.$RVCTVersion.'-thunk.lib drtaeabi.lib drtaeabi.lib(VtblExports.o) drtrvct'.$RVCTVersion.'.lib');
+				}
+				
+			$linkCommand .= ' --userlibpath "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'","${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\LIB" ${var:RUNTIME_LIBS} ${var:IMPLIBS_NO_PATH_VTBLEXPORT}';
+			
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+
+	    	if ($Bld=~/^U?DEB$/o) {
+			$linkCommand = $copyCommand. ' "${target.data}\\${output.file.name}" "${output}\\${output.file.root}.sym"'; 
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+	    	}
+	
+			$linkCommand = 'elftran -version '. &Genutl_VersionToUserString(%Version).' -sid '. &main::SecureId(); 
+			if (&main::CompressTarget) {
+				$linkCommand .= ' -nocompress ';
+			}
+			# change - exexps are allowed data, but they look like dlls to elftran....
+			if (&main::AllowDllData || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+				$linkCommand.=' -allow';
+			}
+			if (not &main::CallDllEntryPoints ) {
+				$linkCommand.=' -nocall';
+			}
+			if (&main::DataLinkAddress) {
+				$linkCommand.=' -datalinkaddress '.&main::DataLinkAddress;
+			}
+			if (&main::FixedProcess) {
+				$linkCommand.=' -fixed';
+			}
+			if (&main::HeapSize) {
+				my %HeapSize=&main::HeapSize;
+				$linkCommand.=' -heap '.$HeapSize{Min}.' '.$HeapSize{Max};
+			}
+			if (&main::ProcessPriority) {
+				$linkCommand.=' -priority '.&main::ProcessPriority;
+			}
+			if (&main::StackSize) {
+				$linkCommand.=' -stack '.&main::StackSize;
+			}
+
+			my $i=1;
+			foreach (@UidList) {
+				$linkCommand.=" -uid$i $_";
+				$i++;
+			}
+			if(&main::VendorId) {
+				$linkCommand.=' -vid '.&main::VendorId;
+			}
+
+			$linkCommand.=' -fpu '.$floatingpointmodel;
+
+			$linkCommand.=' -capability '.&main::Capability. ' "${target.data}\\${output.file.name}" "${output}\\${output.file.name}"';
+		
+			addLinkDescriptorCommand ($linkCommand, "false");
+        	}
+        elsif ($BasicTrgType=~/^LIB$/o) {
+			$linkCommand = 'armar '.$oP.'create "${output}\\${output.file.name}" '.$oP.'via "${target.data}\\${output.file.root}_'.$Bld.'_objects.via"'.' '.$archiveropts;
+			addLinkDescriptorCommand ($linkCommand);
+			}
+		}
+
+##############################################
+# BPABI library generation and link stage    #
+# Assumes use of RVCT 2.2					 #
+##############################################
+
+	elsif ($ABIV2 && ($CW_major_version >= 3.1)) {
+		
+		# prolly don't need this...
+		my $InterWorking = ($ABI eq 'ARMV4') ? "" : "--inter";
+			
+		return if ($BasicTrgType=~/^IMPLIB$/io);
+		
+		if ($BasicTrgType=~/^LIB$/o) {
+			$linkCommand = 'armar --create ${output}\\${output.file.name} ${var:LINK_OBJS} ${var:LIBS}'.' '.$archiveropts;
+	        addLinkDescriptorCommand ($linkCommand);
+         }
+		else
+		{
+		my $AbsentSubst = '';
+		my $EntrySymbol;
+		my $Link = '';
+
+		if ($BasicTrgType=~/^DLL$/o) {
+			$EntrySymbol = '_E32Dll';
+		}
+		elsif ($BasicTrgType=~/^EXE$/o) {
+			$EntrySymbol = '_E32Startup';
+		}
+		if ($EntrySymbol) {
+			$AbsentSubst = " -absent $EntrySymbol";
+		}
+
+		$Link = 'armlink '.$oP.'diag_suppress 6331,6780'.$linkeropts.' ';
+
+		if ($Bld =~ /DEB$/o)
+			{
+			$Link .= ' '.$oP.'debug';
+			}
+
+
+	    # TARGET *.IN
+	    #------------
+
+		# Create "via" file containing all link objects in order to reduce link
+		# command line length
+		addLinkDescriptorDumpFile ('${var:LINK_OBJS}', '${target.data}\\${output.file.root}_'.$Bld.'_objects.via');
+		
+		if ($BasicTrgType!~/^LIB$/o) {
+			$linkCommand = $Link .' '.$oP.'partial -o ${var:COMMON_LINK_FLAGS} "${target.data}\\${output.file.root}.in" '.$oP.'via "${target.data}\\${output.file.root}_'.$Bld.'_objects.via"';
+
+		}
+
+
+#       get rid of any -symbols produced .map file
+        if ($BasicTrgType=~/^(DLL|EXE)/o) {
+			$linkCommand = $deleteCommand.'"${output}\\${output.file.name}.map"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false", undef, undef, undef, undef, (0,1));
+		}
+
+        if ($BasicTrgType=~/^(DLL|EXE)/o) {
+	        my $datalinkbase = "0x400000";
+			my $librarylist;
+			my $expr;
+			@ToolChainLibList = &GetLibList;
+
+			foreach $expr (@ToolChainLibList) {
+				$librarylist .= $expr.' ';
+			}
+	        
+  	        $datalinkbase = &main::DataLinkAddress if (&main::DataLinkAddress);
+	        $linkCommand = "$Link ".$oP.'bpabi '.$oP.'reloc '.$oP.'split '.$oP.'no_scanlib '.$oP.'datacompressor=off '.$oP."rw-base $datalinkbase "."$PlatOpt{Ld}";
+			$linkCommand .= ' --dll --symver_soname --soname '.$LinkAs.' ';
+			
+			
+	        if ($BasicTrgType=~/^DLL$/o) {
+	            # get the right object file for the entry point
+	            my $ObjFile = "UC_DLL_.o";
+	            if ($FirstLib =~ /EDEV/i) {
+		            $ObjFile = "D_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EKLL/i) {
+		            $ObjFile = "L_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EEXT/i) {
+		            $ObjFile = "X_ENTRY_.o";
+	            }
+	            if ($FirstLib =~ /EVAR/i) {
+		            $ObjFile = "V_ENTRY_.o";
+	            }
+
+#		    If platform is a customization, take libs from parent directory.		   
+		    if($IsCustomDll)
+		    {
+		    
+			$linkCommand .= $oP.'entry _E32Dll "'.$FirstLib.'('.$ObjFile.')"'.
+					' "${target.data}\\'.$tempFilenameRoot.'.exp"';
+			    
+		    }
+		    else
+		    {
+		    # ARMV5 hardcoded here...
+		    $linkCommand .= $oP.'entry _E32Dll "'.$FirstLib.'('.$ObjFile.')"';
+		    }
+
+	        } elsif ($BasicTrgType=~/^EXE$/o || $TrgType=~/^EXEXP$/o) {
+			    # get the right object file for the entry point
+			    my $ObjFile = "UC_EXE_.o" ;
+			    if ($FirstLib =~ /KC_EXE/i) {
+					$ObjFile = "K_ENTRY_.o";
+			    }
+
+		    # Should this use $ParentPlat rather than hardcoded ARMV5 dir?
+		   $linkCommand .= $oP.'entry _E32Startup "'.$FirstLib.'('.$ObjFile.')"';
+		
+			}
+
+			$linkCommand .= ' -o "${target.data}\\${output.file.name}"';
+
+			if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
+				if($IsPlatCustomization) 
+				{
+				if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\\'.$ParentPlat.'\\'.$Bld.'\EDLLSTUB'.$RVCTVersion.'.LIB"';
+				}
+				else {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\\'.$ParentPlat.'\\'.$Bld.'\EDLLSTUB.LIB"';
+				}
+				}
+				else
+				{
+				if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB'.$RVCTVersion.'.LIB"';
+				}
+				else {
+				   $linkCommand .= ' "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'\EDLLSTUB.LIB"';
+				}
+				}
+			}
+
+			$linkCommand .= ' ${var:LIBS}';
+			
+			
+			my $runtimeLibs = "";
+			my $StaticRTLib = "usrt".$RVCTVersion;
+			
+			# use ksrt for system code and for user ARM code
+			$StaticRTLib = "ksrt".$RVCTVersion if ($SystemTrg);
+			$runtimeLibs .= $StaticRTLib.".lib" unless ($Trg =~ /(U|K)SRT/i || ($BasicTrgType=~/^LIB$/o));
+		
+			unless ($ArmRT || ($BasicTrgType=~/^LIB$/o)) {
+				my $TargLib = "$ExportLibrary.lib";
+				$TargLib =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
+				unless ($SystemTrg) {
+					foreach (@RTLibList) {
+						$runtimeLibs .= " ".$_ unless ($_ =~ /$TargLib/i);
+					}
+			    }
+			}
+
+			foreach (@ArmLibList)
+				{
+				$runtimeLibs.= " ".$_;
+				}
+			
+			addLinkDescriptorSymbol ('${var:RUNTIME_LIBS}', $runtimeLibs);
+				
+			$linkCommand .= ' --userlibpath "${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\\'.$Bld.'","${var:KIT_EPOCROOT}\\EPOC32\RELEASE\ARMV5\LIB" '.$oP.'via "${target.data}\\${output.file.root}_'.$Bld.'_objects.via" ${var:RUNTIME_LIBS} '.$librarylist.' ';
+			
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+
+		}
+		
+		#### Create the .sym file
+		$linkCommand = 'cmd.exe /C copy "${target.data}\\${output.file.name}" "${output}\\${output.file.root}.sym"';
+		addLinkDescriptorCommand ($linkCommand);
+		
+		#### copy the project .def file for prep
+		if ($DefFile and !$NoExportLibrary)
+		{
+			unless (&main::ExportUnfrozen)
+			{
+        	$linkCommand = 'cmd.exe /C copy "${var:DEF_FILE}" "${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.prep.def"';
+			addLinkDescriptorCommand ($linkCommand);
+			}
+		}
+		
+		
+		#### ELF2E32 POST-LINK COMMAND ####
+		# Section needs to be generic for BPABI (e.g. GCCE & ARMV5_ABIV2)
+		$linkCommand  = '${var:KIT_EPOCROOT}\\epoc32\\tools\\elf2e32.exe ';		
+		
+		# Change - exexps are allowed data, but they look like dlls to elftran....
+		if (&main::AllowDllData || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			$linkCommand .= ' --dlldata';
+		}
+
+		if (&main::DataLinkAddress) {
+			$linkCommand .= ' --datalinkaddress=',&main::DataLinkAddress;
+		}
+		if (&main::FixedProcess) {
+			$linkCommand .=	' --fixedaddress';
+		}
+		
+		$linkCommand .= ' --sid='.&main::SecureId();
+		$linkCommand .= ' --version='. &Genutl_VersionToUserString(%Version);
+		
+		if (&main::HeapSize) {
+			my %HeapSize=&main::HeapSize;
+			$linkCommand.=' --heap '.$HeapSize{Min} .','.$HeapSize{Max};
+		}
+		
+		if (&main::ProcessPriority) {
+			$linkCommand .=	' --priority='.&main::ProcessPriority;
+		}
+		
+		if (&main::StackSize) {
+			$linkCommand .= ' --stack='.&main::StackSize;
+		}
+		
+		my $i=1;
+		foreach (@UidList) {
+			$linkCommand .= " --uid$i=$_";
+			$i++;
+		}
+		if (&main::VendorId) {
+			$linkCommand .= ' --vid='.&main::VendorId;
+		}
+		
+		$linkCommand .= ' --capability='.&main::Capability;
+
+		# ARMFPU only currently supported for RVCT BPABI builds
+		if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i)) {
+			$linkCommand .= ' --fpu=vfpv2'
+		}
+		else {
+			$linkCommand .= ' --fpu=softvfp'
+		}
+		
+	
+		if(($BasicTrgType=~/^DLL/ && $TrgType!~/^DLL/ ) || $TrgType=~/^EXEXP/) {
+	 		$linkCommand .= ' --targettype='.$TrgType;
+ 		}
+ 		else {
+ 			$linkCommand .= ' --targettype='.$BasicTrgType;
+ 		}
+		
+		$linkCommand .= ' --output="${output}\\${output.file.name}"';
+		
+		my $warningMessage;
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			if ($DefFile and !$NoExportLibrary) {
+				$linkCommand .= ' --definput="${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.prep.def"';
+			}
+			$linkCommand .= ' --dso=';
+			$linkCommand .= '"${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${var:IMPORT_LIBRARY}"';
+				
+			$linkCommand .= ' --defoutput=';
+			$linkCommand .= '"${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.def"';
+				
+			if (&main::ExportUnfrozen) {
+				$warningMessage = $exportUnfrozenWarningMessage;
+				$linkCommand .= ' --unfrozen';
+			}
+		}
+		
+		$linkCommand .= ' --elfinput="${target.data}\\${output.file.name}"';
+		$linkCommand .= ' --linkas='.$LinkAs;
+		#Change - LIB path is hardcoded here...
+		$linkCommand .= ' --libpath="${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB"';
+		
+        if ($BasicTrgType=~/^DLL$/o && $TrgType!~/^DLL/){
+			my $Export;
+			my $Ordinal=1;
+			foreach $Export (&main::Exports)
+				{
+				if ($Ordinal eq 1) {
+					$linkCommand .= ' --sysdef=';
+				}
+				elsif ($Ordinal ne 1) {
+					$linkCommand .= ';';
+					}
+					
+				$linkCommand .= "$Export,".$Ordinal;
+				$Ordinal++;
+				}
+		}
+		
+		addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef, $warningMessage);
+		
+		}
+		
+		# copy def file output
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			$linkCommand = 'cmd.exe /C copy  "${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.def" "${Project}\${var:IMPORT_LIBRARY_NO_EXT}.def"';
+			addLinkDescriptorCommand($linkCommand);
+		}
+		
+		# copy the import lib (dso) created
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			if ($DefFile and !$NoExportLibrary) {
+				$linkCommand = 'cmd.exe /C copy ${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${var:IMPORT_LIBRARY} ${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${output.file.root}.dso';
+			}
+			addLinkDescriptorCommand($linkCommand);
+		}
+	
+	}
+			
+#########################################
+# GCC library generation and link stage #
+#########################################
+
+	elsif ($Plat eq "ARM4")
+		{
+		# Generate library
+
+		if ($DefFile and !$NoExportLibrary)
+			{
+			unless (&main::ExportUnfrozen)
+				{
+				$linkCommand = 'perl.exe -S prepdef.pl "${var:DEF_FILE}" "${target.data}\\'.$tempFilenameRoot.'.prep.def"';
+				addLinkDescriptorCommand ($linkCommand);
+
+				$linkCommand = "$Dlltool $PlatOpt{Dlltool}".' --output-lib "${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}" --def "'.
+						'${target.data}\\'.$tempFilenameRoot.'.prep.def" --dllname "'.$LinkAs.'"';
+				addLinkDescriptorCommand ($linkCommand);
+
+				if ($ExtraExportLibrary)
+					{
+					$linkCommand = $copyCommand.'"${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}" '.
+									'"${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).$ExtraExportLibrary.'.lib"';
+					addLinkDescriptorCommand ($linkCommand,"false", "false");
+					}
+
+				foreach (@CompatibleABIs)
+					{
+					$linkCommand = "$Dlltool $ABIDlltool{$_}".' --output-lib "${var:KIT_EPOCROOT}'.kitRelativePath($ABILibPath{$_}).'UREL\\${var:IMPORT_LIBRARY}" --def "'.
+							'${target.data}\\'.$tempFilenameRoot.'.prep.def" --dllname "'.$LinkAs.'"';
+					addLinkDescriptorCommand ($linkCommand);
+
+					if ($ExtraExportLibrary)
+						{
+						$linkCommand = $copyCommand.'"${var:KIT_EPOCROOT}'.kitRelativePath($ABILibPath{$_}).'UREL\\${var:IMPORT_LIBRARY}" '.
+										'"${var:KIT_EPOCROOT}'.kitRelativePath($ABILibPath{$_}).'UREL\\'.$ExtraExportLibrary.'.lib"';
+						addLinkDescriptorCommand ($linkCommand,"false", "false");
+						}
+					}
+				}
+			}
+
+
+		# TARGET *.IN
+		#------------
+		$linkCommand = $deleteCommand.'"${target.data}\\${output.file.root}.in"';
+		addLinkDescriptorCommand ($linkCommand, "false", "false", undef, undef, undef, undef, (0,1));
+				
+		$linkCommand = 'ar.exe cr "${target.data}\\${output.file.root}.in" ${var:LINK_OBJS}';
+		addLinkDescriptorCommand ($linkCommand);
+		
+
+		# Perform Link
+
+	#	Establish the entry point symbol
+		my $EntrySymbol;
+		if ($BasicTrgType=~/^DLL$/o) {
+			$EntrySymbol = '_E32Dll';
+		}
+		elsif ($BasicTrgType=~/^EXE$/o) {
+			$EntrySymbol = '_E32Startup';
+		}
+		my $AbsentSubst = '';
+		if ($EntrySymbol) {
+			$AbsentSubst = " -absent $EntrySymbol";
+		}
+
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+
+	#		generate a .DEF file from the objects and static libraries
+			$linkCommand = "$Dlltool $PlatOpt{Dlltool} --output-def ".'"${target.data}\\'.$tempFilenameRoot.'.inf" "${target.data}\\${output.file.root}.in"';
+
+			foreach (@StatLibList) {
+				$linkCommand .= ' "${var:KIT_EPOCROOT}'.kitRelativePath($StatLinkPath).$_.'"';
+			}
+
+			addLinkDescriptorCommand ($linkCommand);
+
+	#		reorder the .DEF file taking frozen exports into account if there are any
+	#			call perl on the script here so nmake will die if there are errors - this doesn't happen if calling perl in a batch file
+			$linkCommand = 'perl.exe -S makedef.pl -Deffile "${target.data}\\'.$tempFilenameRoot.'.inf" '.$AbsentSubst;
+			if (-e $DefFile) { # effectively "if project frozen ..."
+				$linkCommand .= " -Frzfile \"".'${var:DEF_FILE}'."\"";
+			}
+			# freeze ordinals, a maximum of 2, for polymorphic dlls
+			my $Ordinal;
+			my $Num=1;
+			foreach $Ordinal (&main::Exports) {
+				$linkCommand .= " -$Num $Ordinal";
+				$Num++;
+			}
+			$linkCommand .= ' "${target.data}\\'.$tempFilenameRoot.'.def"';
+			addLinkDescriptorCommand ($linkCommand);
+
+	#		delete the unordered definition file
+			$linkCommand = $deleteCommand.'"${target.data}\\'.$tempFilenameRoot.'.inf"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+
+	#		generate an export object from the ordered .DEF file
+			$linkCommand = "$Dlltool $PlatOpt{Dlltool} --def".' "${target.data}\\'.$tempFilenameRoot.'.def"'.
+				' --output-exp "${target.data}\\'.$tempFilenameRoot.'.exp"'.
+				" --dllname \"$LinkAs\"";
+
+			my $warningMessage;
+				
+			if (&main::ExportUnfrozen) {
+				$warningMessage = $exportUnfrozenWarningMessage;
+				$linkCommand .= ' --output-lib "${var:KIT_EPOCROOT}'.kitRelativePath($LibPath).'${var:IMPORT_LIBRARY}"';
+			}
+			
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef, $warningMessage);
+		}
+
+	#	call ld to do base relocations (and dll exports)
+		if ($BasicTrgType=~/^(DLL|EXE)/o) {
+			$linkCommand = "$Link $PlatOpt{Ld} -s";	
+			if ($BasicTrgType=~/^DLL$/o) {
+				$linkCommand .= " $PlatOpt{Entry} $EntrySymbol -u $EntrySymbol ".'"${target.data}\\'.$tempFilenameRoot.'.exp" --dll ';
+			}
+			elsif ($BasicTrgType=~/^EXE$/o) {
+				$linkCommand .= " $PlatOpt{Entry} $EntrySymbol -u $EntrySymbol ";
+			}
+	#		--whole-archive is required here apparently because of a defect in the gcc toolchain
+	#		the flag can probably be removed with a later version of gcc
+
+			$linkCommand .= '--base-file "${target.data}\\${output.file.root}.bas" -o "${target.data}\\${output.file.name}" '.
+				'${var:FIRST_LIB} --whole-archive "${target.data}\\${output.file.root}.in" '.
+				"--no-whole-archive";
+			$linkCommand .= ' ${var:COMMON_LINK_FLAGS} ${var:LIBS}';
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+
+	#		delete temporary files
+			if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+				$linkCommand = $deleteCommand.'"${target.data}\\'.$tempFilenameRoot.'.exp"';
+				addLinkDescriptorCommand ($linkCommand, "false", "false", undef, undef, undef, undef, (0,1));
+			}
+			$linkCommand = $deleteCommand.'"${target.data}\\${output.file.name}"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+
+	#		call dlltool to do base relocations (and dll exports)
+			$linkCommand = "$Dlltool $PlatOpt{Dlltool} ";
+			if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+				$linkCommand .= '--def "${target.data}\\'.$tempFilenameRoot.'.def" '.
+					"--dllname \"$LinkAs\" ";
+			}
+			$linkCommand .= '--base-file "${target.data}\\${output.file.root}.bas" '.
+				'--output-exp "${target.data}\\'.$tempFilenameRoot.'.exp" ';
+			addLinkDescriptorCommand ($linkCommand);
+
+	#		delete temporary files
+			$linkCommand = $deleteCommand.'"${target.data}\\${output.file.root}.bas"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+
+	#		call ld to link the target
+			$linkCommand = "$Link $PlatOpt{Ld}";
+			if ($Bld=~/^U?REL$/o) {
+				$linkCommand .= " -s";
+			}
+			if ($BasicTrgType=~/^DLL$/o) {
+				$linkCommand .= " $PlatOpt{Entry} $EntrySymbol -u $EntrySymbol --dll ";
+			}
+			elsif ($BasicTrgType=~/^EXE$/o) {
+				$linkCommand .= " $PlatOpt{Entry} $EntrySymbol -u $EntrySymbol ";
+			}
+	#		--whole-archive is required here apparently because of a defect in the gcc toolchain
+	#		the flag can probably be removed with a later version of gcc
+			$linkCommand .= '"${target.data}\\'.$tempFilenameRoot.'.exp" '.
+				'-Map "${output}\\${output.file.name}.map" -o "${target.data}\\${output.file.name}" '.
+				'${var:FIRST_LIB} --whole-archive "${target.data}\\${output.file.root}.in" '.
+				"--no-whole-archive";
+			$linkCommand .= ' ${var:LIBS}';
+
+			if ($BasicTrgType=~/^LIB$/o) {				
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef);
+			}
+			else {
+			addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+			}
+
+	#		delete temporary files
+			$linkCommand = $deleteCommand.'"${target.data}\\'.$tempFilenameRoot.'.exp"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+
+			if ($Bld=~/DEB$/o) {
+				$linkCommand = $Objcopy.' -X "${target.data}\\${output.file.name}" "${output}\\${output.file.root}.sym"';
+				addLinkDescriptorCommand ($linkCommand);
+			}
+
+			$linkCommand = "petran.exe $PlatOpt{Petran} -version ". &Genutl_VersionToUserString(%Version). " -sid ". &main::SecureId(). ' "${target.data}\\${output.file.name}" "${output}\\${output.file.name}" ';
+
+			if (&main::CompressTarget) {
+				$linkCommand .= ' -nocompress';
+			}
+			if (&main::AllowDllData) {
+				$linkCommand .= ' -allow';
+			}
+			if (not &main::CallDllEntryPoints) {
+				$linkCommand .= ' -nocall';
+			}
+			if (&main::DataLinkAddress) {
+				$linkCommand .= ' -datalinkaddress '.&main::DataLinkAddress;
+			}
+			if (&main::FixedProcess) {
+				$linkCommand .= ' -fixed';
+			}
+			if (&main::HeapSize) {
+				my %HeapSize=&main::HeapSize;
+				$linkCommand .= ' -heap '.$HeapSize{Min}.' '.$HeapSize{Max};
+			}
+			if (&main::ProcessPriority) {
+				$linkCommand .= ' -priority '.&main::ProcessPriority;
+			}
+			if (&main::StackSize) {
+				$linkCommand .= ' -stack '.&main::StackSize;
+			}
+			my $i=1;
+			foreach (@UidList) {
+				$linkCommand .= " -uid$i $_";
+				$i++;
+			}
+				
+			$linkCommand .= ' -capability '.&main::Capability;
+			
+			if (&main::VendorId) {
+			$linkCommand .= ' -vid '.&main::VendorId;
+			}
+		
+			addLinkDescriptorCommand ($linkCommand, "false");
+			
+			$linkCommand = $deleteCommand.'"${target.data}\\${output.file.name}"';
+			addLinkDescriptorCommand ($linkCommand, "false", "false");
+		}
+		elsif ($BasicTrgType=~/^LIB$/o) {
+			$linkCommand = $copyCommand.'"${target.data}\\${output.file.root}.in" "${var:KIT_EPOCROOT}'.kitRelativePath($StatLinkPath).'${output.file.name}"';
+			addLinkDescriptorCommand ($linkCommand,"false", "false");
+		}
+	}
+	
+###############################################
+# GCCE library generation and link stage      #
+# GCCE only supported for CW 3.1 and greater #
+###############################################
+
+	elsif ($Plat eq "GCCE" || $CustGCCE)
+	{	
+	
+        if ($BasicTrgType=~/^LIB$/o) {
+	        $linkCommand = 'ar cr ${output}\\${output.file.name} ${var:LINK_OBJS} ${var:LIBS}';
+	        addLinkDescriptorCommand ($linkCommand);
+         }
+         
+		elsif ($BasicTrgType=~/^(DLL|EXE)/o) {
+        
+        $linkCommand = 'arm-none-symbianelf-ld';
+        my $GCCE_LibGCCPath = ' -L';
+        $GCCE_LibGCCPath .= '"'.GetGCCELibPath("-print-file-name=libsupc++.a").'"';
+        $GCCE_LibGCCPath .= ' -L';
+        $GCCE_LibGCCPath .= '"'.GetGCCELibPath("-print-libgcc-file-name").'"';
+		$linkCommand .= $GCCE_LibGCCPath;
+		$linkCommand .=	' ${var:COMMON_LINK_FLAGS}';
+		$linkCommand .= ' --target1-abs --no-undefined -nostdlib -Ttext 0x8000 -Tdata 0x400000';
+		$linkCommand .= ' -shared --default-symver -soname '.$LinkAs." ";
+		
+		if ($Bld=~/REL$/o) {
+			$linkCommand .= ' -Map "${output}\\${output.file.name}.map"';
+		}
+		
+		if ($BasicTrgType=~/^DLL$/o)
+			{
+			$linkCommand .= ' --entry _E32Dll -u _E32Dll';
+			}
+		elsif ($BasicTrgType=~/^EXE$/o)
+			{
+			$linkCommand .= ' --entry _E32Startup -u _E32Startup';
+			}		
+
+		$linkCommand .= ' ${var:FIRST_LIB}';
+		$linkCommand .= ' -o "${target.data}\\${output.file.name}" ${var:LINK_OBJS} ${var:LIBS}';
+		$linkCommand .= ' -lsupc++ -lgcc'.' '.$linkeropts; 
+		addLinkDescriptorCommand ($linkCommand, undef, undef, undef, $FirstLib);
+		
+		
+		$linkCommand = 'cmd.exe /C copy "${target.data}\\${output.file.name}" "${output}\\${output.file.root}.sym"';
+		addLinkDescriptorCommand ($linkCommand);
+		
+		# copy the project .def file for prep
+		if ($DefFile and !$NoExportLibrary)
+		{
+			unless (&main::ExportUnfrozen)
+			{
+        	$linkCommand = 'cmd.exe /C copy "${var:DEF_FILE}" "${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.prep.def"';
+			addLinkDescriptorCommand ($linkCommand);
+			}
+		}
+		
+		$linkCommand  = '${var:KIT_EPOCROOT}\\epoc32\\tools\\elf2e32.exe ';		
+		
+		# Change - exexps are allowed data, but they look like dlls to elftran....
+		if (&main::AllowDllData || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			$linkCommand .= ' --dlldata';
+		}
+
+		if (&main::DataLinkAddress) {
+			$linkCommand .= ' --datalinkaddress=',&main::DataLinkAddress;
+		}
+		if (&main::FixedProcess) {
+			$linkCommand .=	' --fixedaddress';
+		}
+		
+		$linkCommand .= ' --sid='.&main::SecureId();
+		
+		if (&main::HeapSize) {
+			my %HeapSize=&main::HeapSize;
+			$linkCommand.=' --heap '.$HeapSize{Min} .','.$HeapSize{Max};
+		}
+		
+		if (&main::ProcessPriority) {
+			$linkCommand .=	' --priority='.&main::ProcessPriority;
+		}
+		
+		if (&main::StackSize) {
+			$linkCommand .= ' --stack='.&main::StackSize;
+		}
+		
+		my $i=1;
+		foreach (@UidList) {
+			$linkCommand .= " --uid$i=$_";
+			$i++;
+		}
+		if (&main::VendorId) {
+			$linkCommand .= ' --vid='.&main::VendorId;
+		}
+		
+		$linkCommand .= ' --capability='.&main::Capability;
+		
+	
+		if(($BasicTrgType=~/^DLL/ && $TrgType!~/^DLL/ ) || $TrgType=~/^EXEXP/) {
+	 		$linkCommand .= ' --targettype='.$TrgType;
+ 		}
+ 		else {
+ 			$linkCommand .= ' --targettype='.$BasicTrgType;
+ 		}
+		
+		$linkCommand .= ' --output="${output}\\${output.file.name}"';
+		
+		my $warningMessage;
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			if ($DefFile and !$NoExportLibrary) {
+				$linkCommand .= ' --definput="${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.prep.def"';
+			}
+			$linkCommand .= ' --dso=';
+			$linkCommand .= '"${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${var:IMPORT_LIBRARY}"';
+				
+			$linkCommand .= ' --defoutput=';
+			$linkCommand .= '"${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.def"';
+				
+			if (&main::ExportUnfrozen) {
+				$warningMessage = $exportUnfrozenWarningMessage;
+				$linkCommand .= ' --unfrozen';
+			}
+		}
+		
+		$linkCommand .= ' --elfinput="${target.data}\\${output.file.name}"';
+		$linkCommand .= ' --linkas='.$LinkAs;
+		#Change - LIB path is hardcoded here...
+		$linkCommand .= ' --libpath="${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB"';
+		
+        if ($BasicTrgType=~/^DLL$/o && $TrgType!~/^DLL/){
+			my $Export;
+			my $Ordinal=1;
+			foreach $Export (&main::Exports)
+				{
+				if ($Ordinal eq 1) {
+					$linkCommand .= ' --sysdef=';
+				}
+				elsif ($Ordinal ne 1) {
+					$linkCommand .= ';';
+					}
+					
+				$linkCommand .= "$Export,".$Ordinal;
+				$Ordinal++;
+				}
+		}
+		
+		addLinkDescriptorCommand ($linkCommand, undef, undef, undef, undef, $warningMessage);
+				
+		} # end...elsif if ($BasicTrgType=~/^(DLL|EXE)/o)
+		
+		# copy def file output
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			$linkCommand = 'cmd.exe /C copy  "${target.data}\\${var:IMPORT_LIBRARY_NO_EXT}.def" "${Project}\${var:IMPORT_LIBRARY_NO_EXT}.def"';
+			addLinkDescriptorCommand($linkCommand);
+		}
+		
+		# copy the import lib (dso) created
+		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
+			if ($DefFile and !$NoExportLibrary) {
+				$linkCommand = 'cmd.exe /C copy ${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${var:IMPORT_LIBRARY} ${var:KIT_EPOCROOT}\\EPOC32\\RELEASE\\ARMV5\\LIB\\${output.file.root}.dso';
+			}
+			addLinkDescriptorCommand($linkCommand);
+		}
+		
+	
+	} # end  GCCE link stage... elsif ($Plat eq "GCCE")
+	
+	
+	if ($addHeaders)
+		{
+		# Ideally we would do this for all targets, both UREL and UDEB.  This would,
+		# however, be very slow - so we just do it for the first target we come to.
+		my $cpp = &PreprocessorToUseExe();
+		my $cppCommandLine = "$cpp.EXE -M -MG -nostdinc ";
+		my $preInclude = "";
+
+		if (($Plat eq "ARMV5" || $Plat eq "ARMV5_ABIV2" || $Plat eq "ARMV5_ABIV1" || $Plat eq "GCCE" || $IsPlatCustomization) && $PrefixFile)
+			{
+			$preInclude = $PrefixFile;
+			$preInclude =~ s/^.*://;
+			}
+		elsif($VariantFile)
+			{	    
+		    $preInclude = $VariantFile;
+			}
+
+		$cppCommandLine .= '-include '.Path_RltToWork($preInclude).' ' if $preInclude;
+
+		foreach (&main::UserIncPaths, &main::SysIncPaths)
+			{
+			$cppCommandLine .= '-I '.&Path_Chop(&Path_RltToWork($_)).' ';
+			}
+
+		foreach (@MacroList)
+			{
+			#ARMCC requires escaped '"', but CPP doesn't like them
+			s/\\\"/\"/g if /^__PRODUCT_INCLUDE__/; 
+			
+			$cppCommandLine .= '-D'.$_.' ';
+			}
+		
+		my $SourceStructRef=&main::SourceStructRef;
+		my %localIncludes;
+
+		foreach my $SourceRef (@$SourceStructRef)
+	   		{
+			$file = Path_RltToWork(($$SourceRef{SrcPath}.$$SourceRef{CurFile}));
+
+			# ensure the case of the extension is what GCC expects
+			$file =~ s/\.CPP$/.cpp/i;
+			$file =~ s/\.C$/.c/i;
+			$file =~ s/\.s$/.S/i;
+
+			open CPPPIPE,$cppCommandLine.$file." |" or die "ERROR: Can't invoke CPP.EXE\n";
+
+			while (<CPPPIPE>)
+				{
+				#convert any Unix slashes found in CPP output to DOS slashes
+				s/\//\\/g;	
+				while (/\.(\.\\|\\){1}\S+\.(hrh|h|inl){1}/gi)
+					{
+					my $file = $&;
+					my $filePath = &main::Path_Split('Path',$file);
+						
+					# Ignore files that are clearly not local to the project
+					next if ($filePath =~ /\\epoc32\\/i);
+
+					# Ignore files that are #included with intermediate directories -
+					# we can't guarantee these will be on an Access Path.
+					next if ($filePath =~ /\w+\\\.\./);
+
+					# Finally confirm that the file we have is definitely on an Access Path
+					my $presentOnAccessPath = 0;
+					foreach my $accessPath (&main::UserIncPaths, &main::SysIncPaths)
+						{
+						my $accessPathCompare = $accessPath;
+						$accessPathCompare =~ s/\\/_/g;
+
+						my $filePathCompare = $filePath;
+						$filePathCompare =~ s/(\.\\|\.\.\\)//g;
+						$filePathCompare =~ s/\\/_/g;
+
+						$presentOnAccessPath = 1 if ($accessPathCompare =~ /$filePathCompare$/i);
+						}
+					next if (!$presentOnAccessPath);
+
+					# Maintain availability of original case of filename using a lc keyed hash
+					my $localInclude = &main::Path_Split('Base',$file).&main::Path_Split('Ext',$file);					
+					$localIncludes{lc ($localInclude)} = $localInclude unless (!-e $file);
+					}
+				}
+			}
+
+		foreach my $localInclude (sort keys %localIncludes)
+			{
+			addFile($localIncludes{$localInclude}, "Text", 0, "", "Headers");
+			}
+
+		$addHeaders = 0;
+		}
+
+
+	# Add DOCUMENT specified files that we know we can add - we only add these for one target,
+	# as they should be identical through-out
+
+	if ($addDocuments)
+		{
+		foreach my $document (@DocList)
+			{
+			# Only add files as Documents if they haven't already been added to
+			# the target (it's not possible to have duplicate entries) and if they
+			# have an extension we know about.
+
+			next if (grep (/$document/i, @addedFiles));
+
+			my $extension = $document;
+			$extension =~ s/^.*\.//;
+
+			next if (!grep (/$extension/i, @compatibleDOCUMENTExtensions));
+			
+			addFile($document, "Text", "", "", "Documents");
+			}
+
+		$addDocuments = 0;
+		}
+
+
+	# Create the link descriptor file
+
+	$xmlLinkDescriptorCommandParent->addText("\n\t\t\t");
+
+	if ($CW_major_version >= 3)
+		{
+		$xmlLinkDescriptorDumpFileParent->addText("\n\t\t\t");
+		}
+
+	&main::CreateExtraFile("${ExtraFilesPath}$linkDescriptorFile", $xmlLinkDescriptorDoc->toString);
+	addFile($linkDescriptorFile, "Text", "", "", "Link");	
+	
+	# Apply the changed settings
+
+	my $settinglist = $xmlTarget->getElementsByTagName("SETTINGLIST",0)->item(0);
+	my @settingnodes = $settinglist->getElementsByTagName("SETTING",0);
+	foreach my $setting (@settingnodes)
+		{
+		my $element = $setting->getElementsByTagName("NAME",0)->item(0);
+		my $settingname = $element->getFirstChild->getData();
+		my $replacement = $changedsettings{$settingname};
+		if (defined $replacement) 
+			{
+			if ($replacement eq "{}")
+				{
+				if ($settingname eq "UserSearchPaths")
+					{
+					&addUserSearchPaths($setting);
+					}
+				elsif ($settingname eq "SystemSearchPaths")
+					{
+					&addSystemSearchPaths($setting);
+					}
+				elsif ($settingname eq "UserSourceTrees")
+					{
+					&addSourceTrees($setting);
+					}
+				elsif ($settingname eq "FileList")
+					{
+					&addDownloadFileList($setting, @ResourceDownloadList);
+					}
+				}
+			elsif ($replacement =~ /^{(.+)}(.+)$/)
+				{					
+				&changePathSetting($setting,$1,$2);
+				}
+			else
+				{
+				&changeValue($setting,$replacement);
+				}
+			}
+		}
+	}
+
+
+sub addLinkDescriptorCommand($$;$;$;$;$;$;$;) {		
+	my ($linkCommand, $parseStdOut, $parseStdErr, $outputParser, $firstLibProcessing,
+	    $linkWarning, $linkInformation, @successCodes) = @_;
+
+	my $structIndent = "\n\t\t\t\t";
+	my $settingIndent = "$structIndent\t";
+	my $simpleIndent = "$settingIndent\t";
+	my $successCodeArrayIndent = $simpleIndent;
+	my $successCodeSimpleIndent = "$successCodeArrayIndent\t";
+
+	my $structElement = new XML::DOM::Element($xmlLinkDescriptorDoc,"struct");
+	$xmlLinkDescriptorCommandParent->addText("$structIndent");
+	$xmlLinkDescriptorCommandParent->appendChild ($structElement);
+
+	my $settingElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"setting");
+	$settingElementTemplate->setAttribute("uuid-alias", ".");
+	my $simpleElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"simple");
+
+	my $settingElement;
+	my $simpleElement;
+
+	$settingElement = $settingElementTemplate->cloneNode(0);
+	$simpleElement = $simpleElementTemplate->cloneNode(0);
+	
+	$settingElement->setAttribute ("entry", "linkCommand");
+	$structElement->addText ($settingIndent);
+	$structElement->appendChild ($settingElement);
+
+	$simpleElement->addText ($linkCommand);
+
+	$settingElement->addText ($simpleIndent);
+	$settingElement->appendChild ($simpleElement);
+	$settingElement->addText($settingIndent);
+	
+	if (defined $parseStdOut)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "parseStdOut");
+		$simpleElement->addText($parseStdOut);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+	
+	if (defined $parseStdErr)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "parseStdErr");
+		$simpleElement->addText($parseStdErr);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+
+	if (defined $outputParser)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "outputParser");
+		$simpleElement->addText($outputParser);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+
+	if (defined $firstLibProcessing)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "firstLibProcessing");
+		$simpleElement->addText($firstLibProcessing);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+
+	if (defined $linkWarning)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "linkWarning");
+		$simpleElement->addText($linkWarning);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+
+	if (defined $linkInformation)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$simpleElement = $simpleElementTemplate->cloneNode(0);
+
+		$settingElement->setAttribute("entry", "linkInformation");
+		$simpleElement->addText($linkInformation);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+
+		$settingElement->addText ($simpleIndent);
+		$settingElement->appendChild ($simpleElement);
+		$settingElement->addText($settingIndent);
+		}
+
+	if (@successCodes)
+		{
+		$settingElement = $settingElementTemplate->cloneNode(0);
+		$settingElement->setAttribute("entry", "successCodes");
+
+		my $arrayElement = new XML::DOM::Element($xmlLinkDescriptorDoc,"array");
+		$arrayElement->setAttribute("inheritance", "none");
+		
+		foreach my $successCode (@successCodes)
+			{
+			$simpleElement = $simpleElementTemplate->cloneNode(0);
+			$simpleElement->addText($successCode);
+			$arrayElement->addText ($successCodeSimpleIndent);
+			$arrayElement->appendChild ($simpleElement);
+			}
+
+		$arrayElement->addText ($successCodeArrayIndent);
+
+		$settingElement->addText ($successCodeArrayIndent);
+		$settingElement->appendChild ($arrayElement);
+		$settingElement->addText($settingIndent);
+
+		$structElement->addText ($settingIndent);
+		$structElement->appendChild ($settingElement);
+		}
+
+	$structElement->addText($structIndent);
+}
+
+
+sub addLinkDescriptorSymbol ($$) {
+	my ($symbolName, $symbolValue) = @_;
+	
+	my $structIndent = "\n\t\t\t\t";
+	my $settingIndent = "$structIndent\t";
+	my $simpleIndent = "$settingIndent\t";
+
+	my $structElement = new XML::DOM::Element($xmlLinkDescriptorDoc,"struct");
+	$xmlLinkDescriptorSymbolParent->addText("$structIndent");
+	$xmlLinkDescriptorSymbolParent->appendChild ($structElement);
+
+	my $settingElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"setting");
+	$settingElementTemplate->setAttribute("uuid-alias", ".");
+	my $simpleElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"simple");
+
+	my $symbolNameSettingElement;
+	my $symbolNameSimpleElement;
+	my $symbolValueSettingElement;
+	my $symbolValueSimpleElement;
+
+	$symbolNameSettingElement = $settingElementTemplate->cloneNode(0);
+	$symbolNameSimpleElement = $simpleElementTemplate->cloneNode(0);
+	$symbolValueSettingElement = $settingElementTemplate->cloneNode(0);
+	$symbolValueSimpleElement = $simpleElementTemplate->cloneNode(0);
+
+	$symbolNameSettingElement->setAttribute("entry", "symbolName");
+	$symbolNameSimpleElement->addText ($symbolName);
+	$symbolValueSettingElement->setAttribute("entry", "symbolValue");
+	$symbolValueSimpleElement->addText ($symbolValue);
+
+	$symbolNameSettingElement->addText ($simpleIndent);
+	$symbolNameSettingElement->appendChild ($symbolNameSimpleElement);
+	$symbolNameSettingElement->addText($settingIndent);
+	$symbolValueSettingElement->addText ($simpleIndent);
+	$symbolValueSettingElement->appendChild ($symbolValueSimpleElement);
+	$symbolValueSettingElement->addText ($settingIndent);
+
+	$structElement->addText ($settingIndent);
+	$structElement->appendChild ($symbolNameSettingElement);
+	$structElement->addText ($settingIndent);
+	$structElement->appendChild ($symbolValueSettingElement);
+	$structElement->addText ($structIndent);
+	}
+
+
+sub addLinkDescriptorDumpFile ($$) {
+	my ($dumpFileContent, $dumpFileName) = @_;
+	
+	my $structIndent = "\n\t\t\t\t";
+	my $settingIndent = "$structIndent\t";
+	my $simpleIndent = "$settingIndent\t";
+
+	my $structElement = new XML::DOM::Element($xmlLinkDescriptorDoc,"struct");
+	$xmlLinkDescriptorDumpFileParent->addText("$structIndent");
+	$xmlLinkDescriptorDumpFileParent->appendChild ($structElement);
+
+	my $settingElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"setting");
+	$settingElementTemplate->setAttribute("uuid-alias", ".");
+	my $simpleElementTemplate = new XML::DOM::Element($xmlLinkDescriptorDoc,"simple");
+
+	my $dumpFileContentSettingElement;
+	my $dumpFileContentSimpleElement;
+	my $dumpFileNameSettingElement;
+	my $dumpFileNameSimpleElement;
+
+	$dumpFileContentSettingElement = $settingElementTemplate->cloneNode(0);
+	$dumpFileContentSimpleElement = $simpleElementTemplate->cloneNode(0);
+	$dumpFileNameSettingElement = $settingElementTemplate->cloneNode(0);
+	$dumpFileNameSimpleElement = $simpleElementTemplate->cloneNode(0);
+
+	$dumpFileContentSettingElement->setAttribute("entry", "dumpFileContent");
+	$dumpFileContentSimpleElement->addText ($dumpFileContent);
+	$dumpFileNameSettingElement->setAttribute("entry", "dumpFileName");
+	$dumpFileNameSimpleElement->addText ($dumpFileName);
+
+	$dumpFileContentSettingElement->addText ($simpleIndent);
+	$dumpFileContentSettingElement->appendChild ($dumpFileContentSimpleElement);
+	$dumpFileContentSettingElement->addText($settingIndent);
+	$dumpFileNameSettingElement->addText ($simpleIndent);
+	$dumpFileNameSettingElement->appendChild ($dumpFileNameSimpleElement);
+	$dumpFileNameSettingElement->addText ($settingIndent);
+
+	$structElement->addText ($settingIndent);
+	$structElement->appendChild ($dumpFileContentSettingElement);
+	$structElement->addText ($settingIndent);
+	$structElement->appendChild ($dumpFileNameSettingElement);
+	$structElement->addText ($structIndent);
+	}
+
+
+sub ExtraPlat($) {
+
+# Call PmBld again after reprocessing the MMP file and tweaking various main:: variables
+
+	my ($Plat) = @_;
+	
+	&main::SetVarsFromMmp($Plat);
+	&main::InitLinkPaths();
+
+	foreach (&main::BldList) {
+		&main::SetCurBld($_);
+		&PMPlatProcessMmp(&main::PlatTxt2D);
+		&PMStartBldList;
+		&PMBld;
+	}
+
+}
+
+sub disconnectNode($) {
+
+# Remove a node from its parent, also removing the following text node (if any)
+# The text node is assumed to contain whitespace for file formatting.
+ 
+	my ($node)=@_;
+
+	my $parent = $node->getParentNode;
+	my $sibling = $node->getNextSibling;
+	$parent->removeChild($node);
+	if (defined $sibling && $sibling->getNodeType == TEXT_NODE)
+		{
+		$parent->removeChild($sibling);
+		}
+	return $node;
+}
+
+sub removeNode($) {
+
+# disconnect the node and dispose of it
+
+	my ($node) = @_;
+	&disconnectNode($node);
+	$node->dispose;		# setAttribute("disposed",1);
+}
+
+sub textElement($$$$) {
+	my ($element,$name,$value,$insertionpoint)=@_;
+
+	my $subElement = new XML::DOM::Element($xmlProjectDoc,$name);
+	$subElement->appendChild($xmlProjectDoc->createTextNode($value));
+	$element->insertBefore($subElement, $insertionpoint);
+}
+
+sub addFile($$$$;$) {    
+
+	my ($src, $kind, $debug, $shared, $group) = @_;
+
+	my $linkElement = new XML::DOM::Element($xmlProjectDoc,"FILEREF");
+
+	&textElement($linkElement, "PATHTYPE",   "Name");
+	&textElement($linkElement, "PATH",       $src);
+	&textElement($linkElement, "PATHFORMAT", "Windows");
+
+	my $fileElement = $linkElement->cloneNode(1);
+	$fileElement->setTagName("FILE");
+	&textElement($fileElement, "FILEKIND",   $kind);
+	&textElement($fileElement, "FILEFLAGS",  "Debug") if ($debug);
+
+	$xmlLinkOrder->appendChild($linkElement);
+	$xmlFileList->appendChild($fileElement);
+
+	$xmlLinkOrder->addText("\n");
+	$xmlFileList->addText("\n");
+
+	# Accumulate source group information
+
+	my $groupfile = $linkElement->cloneNode(1);
+	$groupfile->setAttribute("NAME", "$shared$src");			# convenience - remove this later!
+
+	push (@addedFiles, $src) unless ($kind eq "Documents");
+
+	if ($kind eq "Library")
+		{
+		$xmlLibGroup->appendChild($groupfile);
+		$xmlLibGroup->addText("\n");
+		}
+	elsif (defined $group)
+		{
+		if ($group eq "Link")
+			{
+			$xmlLinkGroup->appendChild($groupfile);
+			$xmlLinkGroup->addText("\n");
+			}
+		elsif ($group eq "Resources")
+			{
+			$xmlResourcesGroup->appendChild($groupfile);
+			$xmlResourcesGroup->addText("\n");
+			}
+		elsif ($group eq "Root")
+			{
+			$xmlRootGroup->appendChild($groupfile);
+			$xmlRootGroup->addText("\n");
+			}
+		elsif ($group eq "Headers")
+			{
+			$xmlHeadersGroup->appendChild($groupfile);
+			$xmlHeadersGroup->addText("\n");
+			}
+		elsif ($group eq "Documents")
+			{
+			$xmlDocumentsGroup->appendChild($groupfile);
+			$xmlDocumentsGroup->addText("\n");
+			}
+		}
+	else
+		{
+		$xmlSourceGroup->appendChild($groupfile);
+		$xmlSourceGroup->addText("\n");
+		}
+}
+
+sub addGroup($$) {
+	my ($grouplist,$name)=@_;
+
+	my $group = new XML::DOM::Element($xmlProjectDoc,"GROUP");
+	$grouplist->appendChild($group);
+	$grouplist->addText("\n");
+
+	&textElement($group, "NAME", $name);
+	$group->addText("\n");
+	return $group;
+}
+
+sub addSubTarget($$) {
+	my ($subtargetlist,$name)=@_;
+
+	my $subtarget = new XML::DOM::Element($xmlProjectDoc,"SUBTARGET");
+	$subtargetlist->appendChild($subtarget);
+	$subtargetlist->addText("\n");
+
+	&textElement($subtarget, "TARGETNAME", $name);
+}
+
+sub addOrderedTarget($$) {
+	my ($targetorder,$name)=@_;
+
+	my $orderedtarget = new XML::DOM::Element($xmlProjectDoc,"ORDEREDTARGET");
+	$targetorder->appendChild($orderedtarget);
+	$targetorder->addText("\n");
+
+	&textElement($orderedtarget, "NAME", $name);
+}
+
+sub finaliseProject {
+
+	# Run through the project, removing all unused targets
+	# and build up the TARGETORDER list and the "Build All" target
+
+	my $target;
+	my $targetname;
+
+	my $xmlSubTargetList = new XML::DOM::Element($xmlProjectDoc,"SUBTARGETLIST");
+
+	my $xmlTargetOrder = new XML::DOM::Element($xmlProjectDoc,"TARGETORDER");
+	$xmlTargetOrder->addText("\n");
+
+	my @targets = $xmlProjectDoc->getElementsByTagName("TARGET",1);
+	my @emulatortargetnames;
+	my @othertargetnames;
+	
+	foreach $target (@targets)
+		{			
+		$targetname = $target->getAttribute("NAME");
+
+		if ($targetname eq "")
+			{
+			&removeNode($target);
+			}
+		else
+			{
+			$target->removeAttribute("NAME");
+
+			if ($targetname =~ /^WINSCW/)
+				{
+				push (@emulatortargetnames, $targetname);
+				}
+			else
+				{
+				push (@othertargetnames, $targetname);
+				}
+			}
+		}
+
+	foreach $targetname ((sort @emulatortargetnames), (sort @othertargetnames))
+		{
+		&addSubTarget($xmlSubTargetList, $targetname);
+		&addOrderedTarget($xmlTargetOrder, $targetname);
+		}
+
+	# Build the GROUPLIST
+	
+	my $xmlGroupList = new XML::DOM::Element($xmlProjectDoc,"GROUPLIST");
+
+	# Build the "Root" group
+
+	my %rootfiles;
+	my @rootgroups = $xmlProjectDoc->getElementsByTagName("ROOTGROUP",1);
+	foreach my $group (@rootgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			my $name = $file->getAttribute("NAME");
+			if (!defined $rootfiles{$name})
+				{
+				# first occurrence - add to list
+				$rootfiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);					
+				$xmlGroupList->appendChild($file);
+				$xmlGroupList->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+	# Build the "Source" group
+
+	my $xmlSourceGroup = &addGroup($xmlGroupList,"Source");
+	my %sourcefiles;
+	my @sourcegroups = $xmlProjectDoc->getElementsByTagName("SOURCEGROUP",1);
+	foreach my $group (@sourcegroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			my $name = $file->getAttribute("NAME");
+			if (!defined $sourcefiles{$name})
+				{
+				# first occurrence - add to list
+				$sourcefiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+				$xmlSourceGroup->appendChild($file);
+				$xmlSourceGroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+
+	# Build the "Headers" group
+			
+	my $xmlHeadersGroup;
+	my %headerfiles;
+	my @headersgroups = $xmlProjectDoc->getElementsByTagName("HEADERSGROUP",1);
+	foreach my $group (@headersgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			# Only create the "Headers" group if there are some files to add to it
+			if (!defined $xmlHeadersGroup)
+				{
+				$xmlHeadersGroup = &addGroup($xmlGroupList,"Headers");
+				}
+				
+			my $name = $file->getAttribute("NAME");
+			if (!defined $headerfiles{$name})
+				{
+				# first occurrence - add to list
+				$headerfiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+				$xmlHeadersGroup->appendChild($file);
+				$xmlHeadersGroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+
+	# Build the "Resources" group
+			
+	my $xmlResourcesGroup;
+	my %resourcesfiles;
+	my @resourcesgroups = $xmlProjectDoc->getElementsByTagName("RESOURCESGROUP",1);
+	foreach my $group (@resourcesgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			# Only create the main "Resources" groups if there are some files to add
+			# to them
+			if (!defined $xmlResourcesGroup)
+				{
+				$xmlResourcesGroup = &addGroup($xmlGroupList,"Resources");
+				}
+				
+			my $name = $file->getAttribute("NAME");
+			if (!defined $resourcesfiles{$name})
+				{
+				# first occurrence - add to list
+				$resourcesfiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+
+				$xmlResourcesGroup->appendChild($file);
+				$xmlResourcesGroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+		
+	# Build the "Link" group
+			
+	my $xmlLinkGroup = &addGroup($xmlGroupList,"Link");
+	my %linkfiles;
+	my @linkgroups = $xmlProjectDoc->getElementsByTagName("LINKGROUP",1);
+	foreach my $group (@linkgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			my $name = $file->getAttribute("NAME");
+			if (!defined $linkfiles{$name})
+				{
+				# first occurrence - add to list
+				$linkfiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+				$xmlLinkGroup->appendChild($file);
+				$xmlLinkGroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+
+	# Build the "Documents" group
+			
+	my $xmlDocumentsGroup;
+	my %documentfiles;
+	my @documentgroups = $xmlProjectDoc->getElementsByTagName("DOCUMENTSGROUP",1);
+	foreach my $group (@documentgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{				
+			# Only create the "Documents" group if there are some files to add to it
+			if (!defined $xmlDocumentsGroup)
+				{
+				$xmlDocumentsGroup = &addGroup($xmlGroupList,"Documents");
+				}
+
+			my $name = $file->getAttribute("NAME");
+
+			
+			if (!defined $documentfiles{$name})
+				{
+				# first occurrence - add to list
+				$documentfiles{$name}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+				$xmlDocumentsGroup->appendChild($file);
+				$xmlDocumentsGroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+
+	# Build the "Lib" group and its subgroups
+
+	my $xmlLibGroup = &addGroup($xmlGroupList, "Libraries");
+	my %libplats;
+	my @libgroups = $xmlProjectDoc->getElementsByTagName("LIBGROUP",1);
+	foreach my $group (@libgroups)
+		{
+		$targetname = $group->getAttribute("TARGET");
+		my $plat = $group->getAttribute("PLAT");
+		if (!defined $libplats{$plat})
+			{
+			$libplats{$plat} = &addGroup($xmlLibGroup, $plat);
+			}
+		my $platgroup = $libplats{$plat};
+		my @files = $group->getElementsByTagName("FILEREF",0);
+		foreach my $file (@files)
+			{
+			my $name = $file->getAttribute("NAME");
+			if (!defined $sourcefiles{"$plat\\$name"})
+				{
+				# first occurrence - add to list
+				$sourcefiles{"$plat\\$name"}=1;
+				&textElement($file, "TARGETNAME", $targetname, $file->getFirstChild);
+				$file->removeAttribute("NAME");
+				&disconnectNode($file);
+				$platgroup->appendChild($file);
+				$platgroup->addText("\n");
+				}
+			}
+		&removeNode($group);
+		}
+
+	# Replace the GROUPLIST & TARGETORDER in the template document
+
+	my $node = $xmlProjectDoc->getElementsByTagName("GROUPLIST",1)->item(0);
+	$node->getParentNode->replaceChild($xmlGroupList, $node);
+
+	$node = $xmlProjectDoc->getElementsByTagName("TARGETORDER",1)->item(0);
+	$node->getParentNode->replaceChild($xmlTargetOrder, $node);
+
+	# Insert the "Build All" target
+
+	my $xmlBuildAll = new XML::DOM::Element($xmlProjectDoc,"TARGET");
+	$xmlBuildAll->addText("\n");
+	&textElement($xmlBuildAll, "NAME", "Build All");
+	my $settinglist = new XML::DOM::Element($xmlProjectDoc,"SETTINGLIST");
+	&textSetting($settinglist, "Linker", "None");
+	&textSetting($settinglist, "Targetname", "Build All");
+	$xmlBuildAll->appendChild($settinglist);
+	$xmlBuildAll->addText("\n");
+	&textElement($xmlBuildAll, "FILELIST", "");
+	$xmlBuildAll->addText("\n");
+	&textElement($xmlBuildAll, "LINKORDER", "");
+	$xmlBuildAll->addText("\n");
+	$xmlBuildAll->appendChild($xmlSubTargetList);
+
+	&addOrderedTarget($xmlTargetOrder, "Build All");
+
+	$node = $xmlProjectDoc->getElementsByTagName("TARGETLIST",1)->item(0);
+	$node->appendChild($xmlBuildAll);
+
+	# Output the result
+
+	&main::Output(
+		$xmlProjectDoc->toString
+	);
+
+}
+
+sub PMEndSrcList {
+
+	my @PlatList=&main::PlatOverrideList();
+	
+	if (scalar @PlatList == 0)
+		{
+		@PlatList = ("WINSCW", "ARM4", "ARMV5");
+
+		if ($CW_major_version >= 3)
+			{
+			push @PlatList, "ARMV5_ABIV1";
+			}
+		}
+
+	shift @PlatList;	# we've already done the first one in the list
+	foreach (@PlatList)
+		{
+		ExtraPlat($_);
+		}
+
+	&finaliseProject();
+
+}
+
+sub GetGCCELibPath($) {
+	my $gnulibgccPath;
+	open PIPE, "arm-none-symbianelf-g++ $_[0] 2>&1 | ";
+	while(<PIPE>){
+		$gnulibgccPath = $_;
+		$gnulibgccPath =~ s/\//\\/g;
+	}
+	close PIPE;
+	my $SearchlibgccDir = &main::Path_Chop(&main::Path_Split('Path', $gnulibgccPath));
+
+	return $SearchlibgccDir;
+}
+
+sub Read_BSF_Options() {
+        my %plat = (main::PlatRec());
+		my @Customization_Data = split(/\n/,$plat{'CUSTOMIZATION_DATA'});
+	foreach my $option (@Customization_Data) {
+			next if ($option =~ /^$/);
+	        warn "Unrecognized BSF syntax: $option.\n"
+		        unless ($option =~ /\s*(\S+)\s+(.+)$/);
+		my $key = uc $1;
+		my $val = $2;
+	        warn "Unrecognized BSF keyword: $key.\n"
+		        unless ($BSF_keywords{$key});
+		if ($key =~ /COMMON_OPTIONS/) {
+		        push @commonOptions, $val;
+			next;
+		}
+		if ($key =~ /THUMB_OPTIONS/) {
+		        push @thumbOptions, $val;
+			next;
+		}
+		if ($key =~ /ARM_OPTIONS/) {
+		        push @armOptions, $val;
+			next;
+		}
+		if ($key =~ /KERNEL_OPTIONS/) {
+		        push @kernelOptions, $val;
+			next;
+		}
+		if ($key =~ /INVARIANT_OPTIONS/) {
+		        push @invariantOptions, $val;
+			next;
+		}
+		if ($key =~ /LD_OPTIONS/) {
+		        push @linkerOptions, $val;
+			next;
+		}
+		if ($key =~ /AR_OPTIONS/) {
+		        push @archiverOptions, $val;
+			next;
+		}
+
+	}
+}
+
+# Set the options passed from BSF file 
+# @param OptionName    - BSF Keyword using which the options would be overridden in the BSF file
+# @param Options       - List of options read from the BSF keyword
+sub Set_BSF_Options($$)
+{
+	my ($OptionName,$Options) = @_;
+	my @Fragments=();
+	
+	if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
+	{
+		$CustGCCE=1;
+	}
+	foreach my $val (@{$Options})
+	{		
+		# Check if the value of BSF option is to be set or added/removed.
+		if($val =~ /\+\[.*\]\+|\-\[.*\]\-/)
+		{
+			if (@Fragments = Cl_bpabi::Split_BSF_Options($val,'RemoveOptions'))
+			{
+				foreach my $Opt (@Fragments) 
+				{
+					# Remove trailing white spaces
+					$Opt =~ s/\s+$//;
+					# Substitute '=' with '%' which is a wild card character in makefile.
+					# This is required for cases where option to be removed contains '=' (e.g.'-march=armv5t').
+					# When such options are to be removed, "$(INVARIANT_OPTIONS:-march=armv5t=)" is written in the makefile.
+					# However, because of the occurence of '=', pattern match fails in the makefile and such options are not removed. 
+					# To resolve this, '=' is replaced with '%'  in the makefile so that the substitution pattern looks like 
+					# "$(INVARIANT_OPTIONS:-march%armv5t=)" in makefile (e.g."$(INVARIANT_OPTIONS:-march%armv5t=)").
+					$Opt =~ s/=/%/;
+					if((($OptionName =~ /COMMON_OPTIONS/)
+					|| ($OptionName =~ /THUMB_OPTIONS/)
+					|| ($OptionName =~ /ARM_OPTIONS/)
+					|| ($OptionName =~ /KERNEL_OPTIONS/)
+					|| ($OptionName =~ /INVARIANT_OPTIONS/))
+					&& ($CustGCCE))
+					{
+						$GCCE_CompilerOption = RemoveBsfOptions($Opt,$GCCE_CompilerOption);
+					}
+					elsif($OptionName =~ /COMMON_OPTIONS/)
+					{
+						$CCFLAGS = RemoveBsfOptions($Opt,$CCFLAGS);
+					}
+					elsif(($OptionName =~ /THUMB_OPTIONS/)
+					|| ($OptionName =~ /ARM_OPTIONS/)
+					|| ($OptionName =~ /KERNEL_OPTIONS/))
+					{
+						$CCFLAGS = RemoveBsfOptions($Opt,$CCFLAGS);
+					}
+					elsif($OptionName =~ /INVARIANT_OPTIONS/)
+					{
+						$CCFLAGS = RemoveBsfOptions($Opt,$CCFLAGS);
+					}
+					elsif($OptionName =~ /LD_OPTIONS/)
+					{
+						$linkeropts = RemoveBsfOptions($Opt,$Link);
+						$linkCommand = RemoveBsfOptions($Opt,$Link);
+					}
+					elsif($OptionName =~ /AR_OPTIONS/)
+					{
+						$archiveropts = RemoveBsfOptions($Opt,$linkCommand);
+					}
+				}					
+				@Fragments=();
+			}
+			
+			if (@Fragments = Cl_bpabi::Split_BSF_Options($val,'AddOptions')) 
+			{
+				my $v;
+				foreach $v (@Fragments)
+				{
+					if((($OptionName =~ /COMMON_OPTIONS/)
+					|| ($OptionName =~ /THUMB_OPTIONS/)
+					|| ($OptionName =~ /ARM_OPTIONS/)
+					|| ($OptionName =~ /KERNEL_OPTIONS/)
+					|| ($OptionName =~ /INVARIANT_OPTIONS/))
+					&& ($CustGCCE))
+					{
+						$GCCE_CompilerOption .= ' '.$v.' ';
+					}
+					elsif($OptionName =~ /COMMON_OPTIONS/)
+					{
+						$bsfaddoptions .= ' '.$v.' '; 						
+					}
+					elsif(($OptionName =~ /THUMB_OPTIONS/)
+					|| ($OptionName =~ /ARM_OPTIONS/)
+					|| ($OptionName =~ /KERNEL_OPTIONS/))
+					{
+						$bsfaddoptions .= ' '.$v.' ';	
+					}
+					elsif($OptionName =~ /INVARIANT_OPTIONS/)
+					{
+						$bsfaddoptions .= ' '.$v.' ';
+					}
+					elsif($OptionName =~ /LD_OPTIONS/)
+					{
+						$linkeropts .= ' '.$v.' ';
+					}
+					elsif($OptionName =~ /AR_OPTIONS/)
+					{
+						$archiveropts .= ' '.$v.' ';
+					}
+				}
+				@Fragments=();
+			}
+		}
+		else
+		{
+			if((($OptionName =~ /COMMON_OPTIONS/)
+			|| ($OptionName =~ /THUMB_OPTIONS/)
+			|| ($OptionName =~ /ARM_OPTIONS/)
+			|| ($OptionName =~ /KERNEL_OPTIONS/)
+			|| ($OptionName =~ /INVARIANT_OPTIONS/))
+			&& ($CustGCCE))
+			{
+				$GCCE_CompilerOption .= ' '.$val.' ';
+			}
+			elsif($OptionName =~ /COMMON_OPTIONS/)
+			{
+				$bsfaddoptions .= ' '.$val.' ';
+			}
+			elsif(($OptionName =~ /THUMB_OPTIONS/)
+			|| ($OptionName =~ /ARM_OPTIONS/)
+			|| ($OptionName =~ /KERNEL_OPTIONS/))
+			{
+				$bsfaddoptions .= ' '.$val.' ';
+			}
+			elsif($OptionName =~ /INVARIANT_OPTIONS/)
+			{
+				$bsfaddoptions .= ' '.$val.' ';
+			}
+			elsif($OptionName =~ /LD_OPTIONS/)
+			{
+				$linkeropts .= ' '.$val.' ';
+			}
+			elsif($OptionName =~ /AR_OPTIONS/)
+			{
+				$archiveropts .= ' '.$val.' ';
+			}
+		}	
+	}
+}
+
+sub RemoveBsfOptions($$)
+{
+	my ($Opt_to_replace,$Opt_replaced_in) = @_;
+	
+	$Opt_replaced_in =~ s/$Opt_to_replace//g;
+	return $Opt_replaced_in;
+}
+
+# function to expand the macro as pass with appropriate options
+sub printlist {
+	my $option =shift @_;
+	my @list = @_,
+	my $data;
+	my $finalval=undef;
+	
+	foreach $data (@list)
+	{
+		if($option =~ "-D") {
+			$finalval .= " ".$option.$data;	
+		}
+		else {
+			$finalval .= " ".$option." ".$data;
+		}
+	}
+	return $finalval;
+}
+
+#read the configuration make file into the HASH and use them for further processing
+sub collect_config_data {
+	my($configfile) = @_;
+	open(DATA, "<$configfile");
+	while(<DATA>) 
+	{	
+		my $line = $_;
+		if($line =~ /=/)
+		{
+			if ($line =~ /(.*):=(.*)/)
+			{ 
+				$configdata{$1}=$2;
+			}
+			elsif ($line =~ /(.*)=(.*=.*)/)
+			{ 
+				$configdata{$1}=$2;
+			}
+			elsif ($line =~ /(.*)=(.*)/)
+			{ 
+				$configdata{$1}=$2;
+			}
+		}
+	}
+	close(DATA)
+}
+
+#function is ti fetch the contents of the config data which is read from the configuration make file, 
+# for ex: KERNEL_OPTIONS=$(ARM_INSTRUCTION_SET) $(NO_EXCEPTIONS), this function extracts the value for ARM_INSTRUCTION_SET & NO_EXCEPTIONS
+sub fetch_config_data {
+	my($list) = @_;
+	my $op;
+	my $op1;
+	my $finaldata = undef;
+	
+	my @ip_options = split(/\s+/, $list);	
+	foreach $op (@ip_options)
+	{
+		$op =~ s/\)//g;
+		$op =~ s/\$\(//g;
+		if($op =~ /-/) {
+			$finaldata .= " ".$op;
+		}
+		else {
+			$finaldata .= " ".$configdata{$op};
+		}
+	}
+	return $finaldata;
+}
+
+# function to fix the bsf options, if the bsf option is already present in the CCFLAGS then remove from it so that it can be added from bsf,
+# this is to avoid the duplication of the options passed to the compiler.
+sub fixbsfoptions {
+	my ($options) = @_;
+	my $ccflgs = $CCFLAGS;
+	my $d;
+	my $Pattern = '-{1,2}\S+\s*(?!-)\S*';
+	my @list = $options =~ /$Pattern/g;
+	foreach $d (@list) {
+		if($ccflgs =~ /$d/) {
+				$ccflgs =~ s/$d//g;	
+		}
+		else {
+			if($d =~ /(.*)\s+(.*)/) {
+				my $a = $1;
+				if($ccflgs =~ /$a\s+\S+/) {
+					$ccflgs =~ s/$a\s+\S+//g;
+				}
+			}
+		}
+	}
+	$CCFLAGS = $ccflgs;
+}
+
+# funtion to get the list if the libraries to be linked during linking
+sub GetLibList() {
+	my @LibList;
+	my @StaticLibList;
+	my $Plat=&main::Plat;
+	unless(defined($ENV{RVCT_VER_MAJOR})){
+		my ($rvct_M, $rvct_m, $rvct_b) = RVCT_plat2set::get_version_list($Plat);
+		$ENV{RVCT_VER_MAJOR}=$rvct_M;
+	}
+	&Cl_bpabi::getVariableForNewPlat();
+	my $list = &Cl_bpabi::getConfigVariable('STATIC_LIBS_LIST') ;
+	
+	if (length($list) >0)
+	{
+		@StaticLibList = split(/\s+/, $list);
+	}
+	if($Plat eq "ARMV5" || $Plat eq "ARMV5_ABIV2" || IsCustomization($Plat)) {
+		@LibList=&Armutl_ArmLibList;
+		if(@LibList==0) {
+			my $LibDir = Armutl_ArmLibDir();
+			if (@StaticLibList) {
+				foreach my $lib (@StaticLibList) {
+					push @LibList, ("$LibDir\\$lib");
+				}
+			}
+		}
+	}
+	else
+	{
+		@LibList = ('$(STATIC_LIBS_LIST)');
+	}
+	return @LibList;
+}
+
+1;