sbsv1/abld/platform/cl_bpabi.pm
author srilekhas
Mon, 11 Oct 2010 11:16:47 +0100
changeset 646 a010554f8551
parent 599 fa7a3cc6effd
permissions -rw-r--r--
merge

# Copyright (c) 1997-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:
#

# This package contains routines to handle Base Platform ABI (BPABI) Platforms.
package Cl_bpabi;

my @commonOptions;
my @thumbOptions;
my @armOptions;
my @kernelOptions;
my @invariantOptions;
my @linkerOptions;
my @archiverOptions;
my @debugFormat;
my $ArmIncDir;
my @ArmLibList;

my %configVariables;

#Check if Function call Logger is enabled
my $Function_Call_Logger=&main::IsFunctionCallLogging();

# Get the information regarding supporting Compiler Wrapper Option
my $IsCompilerWrapperOption=&main::CompilerWrapperOption();
my $IsProxyWrapperOption=&main::ProxyWrapperOption();

# takes an 'expression'  to evaluate with $_ bound to each of the
# remaining args
sub PrintList
{
    my $expr = shift @_;
    foreach (@_) {
	my $str = eval($expr);
	&main::Output($str);
    }
}

sub DepLinkList
{
    my $expr = shift @_;
    my @arr;
    foreach (@_) {
	my $str = eval($expr);
	push @arr, $str;
    }
    return @arr;
}

require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(
	PMHelp_Mmp
	PMPlatProcessMmp
	PMStartBldList
		PMBld
	PMStartSrcList
		PMBitMapBld
		PMResrcBld
		PMStartSrc
		PMAifBld
		PMSrcDepend
			PMSrcBldDepend
			PMEndSrcBld
		PMEndSrc
	PMEndSrcList
	PMPrefixFile
	PMToolChainIncDir
	PMSupportsFeatureVariants
);

use Cwd;

# Armutl package does various ancillary things for armedg modules
use Armutl;
use BPABIutl;
use E32Plat;
use RVCT_plat2set;
use gcce_plat2set;

# This is the RVCT Version information required by Armutl package
my $RVCTMajorVersion;
my $RVCTMinorVersion;
my $RVCTVersion;

my $GCCEMajorVersion;
my $GCCEMinorVersion;
my $GCCEVersion;

# The name of the build platform, e.g. ARMV6.
my $PlatName = main::Plat();

# The name of the root platform. This is useful if the plaform is derived using a
# BSF file. If the current platform is not derived, $RootName will be the same as
# $PlatName.
my $RootName = E32Plat::Plat_Root($PlatName);


# cl_generic package contains generic routines to handle bits of makefiles which are
# common to all of the platforms. Currently it deals with AIF, MBM amd RSC files.
use cl_generic;

# E32env package contains information for makmake and associated e32tools perl programs
# within the Epoc32 Environment
use E32env;

# Genutl package contains utility subroutines for MAKMAKE and associated scripts
use Genutl;

# Modload package is the runtime module-loading routine for loading e32tools modules into
# 'main' module
use Modload;

use constant NOCOMPRESSIONMETHOD => 0;
use constant INFLATECOMPRESSIONMETHOD => 1;
use constant BYTEPAIRCOMPRESSIONMETHOD => 2;

use constant NOTPAGED => 0;
use constant UNPAGED => 1;
use constant PAGED => 2;

use constant NON_DEBUGGABLE => 0;
use constant DEBUGGABLE => 1;
use constant DEBUGGABLE_UDEBONLY => 2;

my %plat = &main::PlatRec();
my $CustomizedARMV5Plat = 0;

if (($plat{'CUSTOMIZES'}) && (($plat{'ROOTPLATNAME'} eq "ARMV5") || ($plat{'ROOTPLATNAME'} eq "ARMV5_ABIV2"))) {
# The following flag is set to handle the exceptions related to ARMV5 toolchain.
	$CustomizedARMV5Plat = 1;		
}

#this fucntion will be used for cw_ide platform to update the PlatName and reinitialize the hashtable
sub getVariableForNewPlat
{
	$PlatName = main::Plat();	
	undef(%configVariables);
}
sub PMHelp_Mmp {

# Help Text for ARM Platform, lists out the MMP keywords used incase of ARM Compiler
	if($PlatName eq "ARMV5" || $PlatName eq "ARMV5_ABIV2" || $CustomizedARMV5Plat)
	{
		return &Armutl_Help_Mmp;
	}
	else
	{
		return "";
	}
}

my $ToolChainIncDir;
my @ToolChainLibList;
my $ArmRT = 0;
my %AsmFiles = ();
my %AsmDirs = ();
my $NamedSymLkup = 0;
my $InterWorking = '';

sub PMPlatProcessMmp (@) {
	&InitToolChain(@_);
	$ToolChainIncDir = &GetToolChainIncDir;
	&main::SetStdIncPaths($ToolChainIncDir);
	@ToolChainLibList = &GetLibList;
# Variable to check if the target forms part of the run time libraries, if it is so
# shouldn't be linked against itself or other runtime libs
	$ArmRT = &IsTargetRT;
	my @AsmFileList = &GetToolChainAsmFileList;
	foreach (@AsmFileList) { $AsmFiles{ucfirst lc $_} = 1; }
}

my $preinclude;

my $Makecmd;

sub PMStartBldList($) {
	($Makecmd) = @_;
	my $ABI=&main::ABI;
	my $BaseTrg=&main::BaseTrg;
	my $BasicTrgType=&main::BasicTrgType;
	my @BldList=&main::BldList;
	my @ChopSysIncPaths=&main::Path_Chop(&main::SysIncPaths);
	my @ChopUserIncPaths=&main::Path_Chop(&main::UserIncPaths);
	my $DefFile=&main::DefFile;
	my $EPOCPath=&main::EPOCPath;
	my $LinkAs=&main::LinkAs;
	my $LibPath=&main::LibPath.'LIB\\';
	my @MacroList=&main::MacroList();
	push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__";
	push @MacroList, "__SYMBIAN_STDCPP_SUPPORT__" if ( StdCppTarget() );

  	my $Plat=&main::Plat;
  	my $Trg=&main::Trg;
  	my $TrgType=&main::TrgType;
  
  # This horrible change (presumably to allow GCCE to work with edll.lib etc.
  # produced by RVCT breaks SMP (and also breaks any optimized platform
  # builds such as ARMV6, and also Thumb2 builds).
  # Work round for now by conditioning the horrible change on the absence of
  # SMP in the platform definition.
  	my %PlatHash = &main::PlatRec();
  	unless ($PlatHash{SMP}) {
		my $myStatLinkPath;
		$myStatLinkPath = "$E32env::Data{LinkPath}";
		$myStatLinkPath .= "ARMV5";
		&main::SetStatLinkPath($myStatLinkPath);
	}

	my $VariantFile=&ChangeSlash(&main::VariantFile);

	my @UidList=&main::UidList;
    my $SystemTrg = &main::SystemTrg;
    my $ExportLibrary=&main::ExportLibrary;
    my $NoExportLibrary=&main::NoExportLibrary;
    # N.B. should get better way to detect kernel probably!!
    $SystemTrg = 1 if ($ExportLibrary =~ /EKERN/i);

    # N.B. should get better way to detect this
    $SystemTrg = 1 if ($Trg =~ /KSRT/i);

	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;
	}

#	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);
	}

	# Required for .lib generation
	$InterWorking = ($ABI eq 'ARMV4') ? "" : "--inter";

	# need to add config file for makmake invocation
	my $config_file = BPABIutl_Config_Path($PlatName);

	&main::Output("\n", "include $config_file\n", "\n");
	&Generic_Header(0,$Makecmd, 1);	# define standard things using absolute paths and request that a make function
									# is provided to provide optional conversion of absolute paths to Unix slashes

# modified start: makefile improvement 
	&main::Output(
		"CHECKVMAP : CHECKVMAPUDEB CHECKVMAPUREL",
		"\n"
	);
# modified end: makefile improvement 
	if ($Makecmd eq "nmake") {
		&main::Output(
			"\n",
  			"PATH=",&main::Path_Drive,$EPOCPath,"gcc\$(PBUILDPID)\\bin;\$(PATH)\n",
			"\n"
		);
	}
	else {
		&main::Output(
			"\n",
			"# must set both PATH and Path to make it work correctly\n",
  			"Path:=",&main::Path_Drive,$EPOCPath,"gcc\$(PBUILDPID)\\bin;\$(Path)\n",
			"PATH:=\$(Path)\n",
			"\n"
		);
	}

	if ($BasicTrgType=~/^(DLL|EXE)/o)
	{

		my $OtherLinkerOpts;
		my $toolchain = getConfigVariable('COMPILER_PLAT');
		
		# In case of GCCE releases, '--map' option was supported only from build 3.4.3 Q1C release
		# Hence this is a special case, where GCCE platform is checked to ensure that the --map option
		# is accepted in the correct relase. Even if the option is provided in the config file, it will be
		# ignored for versions before 3.4.3 Q1C 2005 release.

		# Check to be included in the Makefile, so that the map filename is provided as input only
		# when the MAP option is supplied

		&main::Output("ifdef LINKER_SYMBOLS_MAP_OPTION\n");
		foreach (@BldList)
			{
			&main::Output("\t$_"."_MAP_FILE=\"\$(EPOCTRG$_)\\".&main::Trg($_).".map\"\n");
			}
		&main::Output("else\n");
		foreach (@BldList)
			{
			&main::Output("\t$_"."_MAP_FILE=\n");
			}
		&main::Output("endif\n");

		#	In some compiler toolchains, the start address may be required to be provided using the appropriate option.
		#	Incase if the option is provided by the toolchain, then pass we need to pass in the start address.
		&main::Output(
			"\nifdef CODE_SEGMENT_START\n",
			"\tCODE_SEGMENT_START += 0x8000 \n",
			"endif\n",
		);


		# In some compiler toolchain, the symboled archives may have to be listed
		&main::Output(
			"ifdef START_GROUP_SYMBOL\n",
			"\tEEXE_OBJECT=\$(START_GROUP_SYMBOL)UC_EXE_.o\$(END_GROUP_SYMBOL)\n",
			"\tEDLL_OBJECT=\$(START_GROUP_SYMBOL)UC_DLL_.o\$(END_GROUP_SYMBOL)\n",
			"\tDENTRY_OBJECT=\$(START_GROUP_SYMBOL)D_ENTRY_.o\$(END_GROUP_SYMBOL)\n",
			"\tLENTRY_OBJECT=\$(START_GROUP_SYMBOL)L_ENTRY_.o\$(END_GROUP_SYMBOL)\n",
			"\tXENTRY_OBJECT=\$(START_GROUP_SYMBOL)X_ENTRY_.o\$(END_GROUP_SYMBOL)\n",
			"\tVENTRY_OBJECT=\$(START_GROUP_SYMBOL)V_ENTRY_.o\$(END_GROUP_SYMBOL)\n",
			"\tKENTRY_OBJECT=\$(START_GROUP_SYMBOL)K_ENTRY_.o\$(END_GROUP_SYMBOL)\n",
			"endif\n\n"
		);
		
		# put the extra linker options from MMP file into the linker flags
		$OtherLinkerOpts=&main::LinkerOption($toolchain);
		
		if($OtherLinkerOpts) {
			&main::Output(
				"\n# ADDITIONAL LINKER OPTIONS\n",
				"ifdef SYMBIAN_UREL_LINK_FLAGS\n",
				"\tSYMBIAN_UREL_LINK_FLAGS += $OtherLinkerOpts \n",
				"else\n",
				"\tSYMBIAN_UREL_LINK_FLAGS = $OtherLinkerOpts \n",
				"endif\n",
				"ifdef SYMBIAN_UDEB_LINK_FLAGS\n",
				"\tSYMBIAN_UDEB_LINK_FLAGS += $OtherLinkerOpts \n",
				"else\n",
				"\tSYMBIAN_UDEB_LINK_FLAGS = $OtherLinkerOpts \n",
				"endif\n\n"
			);
		}
	}

	&main::Output(
		"INCDIR ="
	);

	PrintList("\"  \\\$(INCLUDE_OPTION) \$_\"", @ChopUserIncPaths);
	PrintList("\" \\\$(INCLUDE_OPTION) \$_\"", @ChopSysIncPaths);

	$ToolchainIncDir = &GetToolChainIncDir;

	if($ToolchainIncDir ne '')
	{
		&main::Output(
			" \$(INCLUDE_OPTION) ","\"$ToolchainIncDir\"");
	}

	&main::Output(
		"\n",
		"\n"
	);

	#Function call logger takes -I as include option
	my $FCLogger_inc_option = getConfigVariable('FC_LOGGER_INCLUDE_OPTION'); 
	if ($Function_Call_Logger)	{
		&main::Output(
			"INCDIR_FCLOGGER  ="
		);
		PrintList("\" $FCLogger_inc_option \$_\"", @ChopUserIncPaths);
		PrintList("\" $FCLogger_inc_option \$_\"", @ChopSysIncPaths);
		$ToolchainIncDir = &GetToolChainIncDir;
		if($ToolchainIncDir ne '')	{
			&main::Output(
				" $FCLogger_inc_option \"$ToolchainIncDir\""
			);
		}
		&main::Output(
			"\n",
			"\n"
		);
	}

  	# Set control warnings and errors options for building Standard C++ application
  	if( StdCppTarget() ) {
  		&main::Output("CC_WARNINGS_CONTROL_OPTION=\$(CC_STDCPP_WARNINGS_CONTROL_OPTION)","\n");
  		&main::Output("CC_ERRORS_CONTROL_OPTION=\$(CC_STDCPP_ERRORS_CONTROL_OPTION)","\n");
  		&main::Output("\n",	"\n");
  	}
  	
	Read_BSF_Options() if ($plat{'CUSTOMIZES'});

	my $kernelOption=0;
	my $buildAsArmOption=0;
	my $thumbOption=0;

	if (SysTrg())
	{
		$kernelOption=1;
	}
	elsif (main::BuildAsARM() or ($ABI eq 'ARMV4'))
	{
		$buildAsArmOption=1;
	}
	else
	{
		$thumbOption=1;
	}

	my $OtherOpts = undef;	

	my $toolchain = getConfigVariable('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 .= " \$(KERNEL_OPTIONS) ";
	}
	elsif($buildAsArmOption==1)
	{	
		if(@armOptions) {
# Arm options as read from BSF file (ARM_OPTIONS keyword)
			Set_BSF_Options('ARM_OPTIONS',\@armOptions);
		}
		$OtherOpts .= " \$(ARM_OPTIONS) ";
	}
	elsif($thumbOption==1)
	{
		if(@thumbOptions) {
# Thumb options as read from BSF file (THUMB_OPTIONS keyword)
			Set_BSF_Options('THUMB_OPTIONS',\@thumbOptions);
		}
		$OtherOpts .= " \$(THUMB_OPTIONS) ";
	}

	if($thumbOption==1 || $buildAsArmOption==1 || $kernelOption ==1 )
	{
		if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i))
		{
			$OtherOpts .=	" \$(VFP2MODE_OPTION) ";
		}
		else
		{
			$OtherOpts .=	" \$(SOFTVFPMODE_OPTION) ";
		}
	}

	if ($thumbOption==1)
	{
		$OtherOpts .= " \$(COMPILER_THUMB_DEFINES) ";
	}

	$OtherOpts .= " \$(COMPILER_INTERWORK_DEFINES) ";

	# Options to export symbols by default, for OE
	if($TrgType=~/^STDDLL$/o || $TrgType=~/^STDEXE$/o || $TrgType=~/^STDLIB$/o) {
		$OtherOpts .= " \$(OE_OPTIONS) ";
	}

	if($OtherOpts)
	{
		&main::Output(
			"OTHEROPTIONS=$OtherOpts",
			"\n",
			"CCFLAGS += \$(OTHEROPTIONS)",
			"\n"
		);
	}

	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) {
# Linker options as read from BSF file (LD_OPTIONS keyword)
		Set_BSF_Options('LD_OPTIONS',\@linkerOptions);
	}	

	if ($BasicTrgType=~/^LIB$/o) {
		if(@archiverOptions) {
# Archiver options as read from BSF file (AR_OPTIONS keyword)
		Set_BSF_Options('AR_OPTIONS',\@archiverOptions);
		}
	}		

	if(@debugFormat) {
		Set_BSF_Options('DEBUG_FORMAT',\@debugFormat);
	}	

	&main::Output(
		"CCDEFS = \$(COMPILER_DEFINES) "
	);

	PrintList("\" -D\$_\"", @MacroList);

	&main::Output(
		" \$(PLATFORM_DEFINES) "
	);

	&main::Output(

	);

	if($kernelOption==1)
	{
		&main::Output(
			"-D__KERNEL_MODE__ "
		);
	}

	if($VariantFile){
		#Function Call Logger
		if ($Function_Call_Logger) {
			#FC Logger accepts product include file without path
			my $file=&main::Path_Split('File', &main::VariantFile);
			&main::Output(
				" -D\"__PRODUCT_INCLUDE__=\\\"${file}\\\"\""
			);
		}
		else {
			&main::Output(
				" -D__PRODUCT_INCLUDE__=\\\"${VariantFile}\\\""
			);
		}
	}

	&main::Output(
		" \$(USERDEFS)\n",
		"\n"
	);

	if ( $RootName =~ /^ARMV5$/ ) {
		# Now we know that the platform is either ARMV5 or a platform derived from
		# ARMV5 (BSF).
	
		# See if an environment variable overrides the default DWARF version for
		# this platform.
		
		my $env_dwarf_key = "ABLD_${PlatName}_DWARF";
		my $env_dwarf_val = $ENV{$env_dwarf_key};

		if ($env_dwarf_val) {
			main::FatalError("The value of $env_dwarf_key is invalid.") unless ($env_dwarf_val =~ /^[23]$/);
			main::FatalError("We don't support DWARF-2 on ARMV7.") if ($PlatName =~ /^ARMV7/ && $env_dwarf_val == 2);

			&main::Output( "DEBUG_FORMAT=\$(DEBUG_FORMAT_DWARF$env_dwarf_val)\n\n");
		}
	}


	foreach (@BldList) {
		&main::Output(
			"CC$_ = ", $IsProxyWrapperOption ? "$ENV{ABLD_COMPWRAP} ":"", "\$(CC) "
		);

		# SYMBIAN_UDEB/UREL_CCFLAGS don't have the optimisation levels.
		if(&main::DebugSwitchUsed() ){
			if(&main::SymbolicDebugEnabled() ) {
				&main::Output(
					" \$(SYMBIAN_UDEB_CCFLAGS) "
				);
			}
			else {
				&main::Output(
					" \$(SYMBIAN_UREL_CCFLAGS) "
				);
			}
		}
		elsif (/DEB$/o) {
			&main::Output(
				" \$(SYMBIAN_UDEB_CCFLAGS) "
			);
		}
		else {
			&main::Output(
				" \$(SYMBIAN_UREL_CCFLAGS) "
			);

		}
		#Set the optimisation levels depending on whether it is a UREL or a UDEB build
		if (/DEB$/o) {
			&main::Output(
				" \$(DEBUG_OPTIMISATION) "
			);
		}
		else {
		&main::Output(
				" \$(REL_OPTIMISATION) "
			);
		}

		&main::Output(
			"\$(RUNTIME_SYMBOL_VISIBILITY_OPTION) "
		);

		if($kernelOption == 0)
		{
			&main::Output(
				"\$(EXCEPTIONS) "
			);
		}
		&main::Output(
			'$(CCFLAGS) '
		);

		my @ml = &main::MacroList($_);
		PrintList("\" -D\$_\"", @ml);

		&main::Output(
			" \$(CCDEFS)\n"
		);
		my @mmpReplaceOptions = &main::ReplaceOptions($toolchain);
		
		if (@mmpReplaceOptions)
		{
			my $OptionPrefix = getConfigVariable('OPTION_PREFIX');
			my $Pattern;

			# Set the value of '$Pattern' which is required to segregate one option from another based on the option prefix.
			if($OptionPrefix) 
			{
				$Pattern = $OptionPrefix.'\S+\s*(?!'.$OptionPrefix.')\S*';
			}
			else 
			{
				# If option prefix is not set in the configuration make file, then set default
				# option prefix as '-' or '--'.
				$Pattern = '-{1,2}\S+\s*(?!-)\S*';
			}

			foreach my $options (@mmpReplaceOptions) 
			{
				my @opts = $options =~ /$Pattern/g;
				my $count = 0;

				while ($count <= $#opts) 
				{
					my $opt;
					my $rep;
					if ($opts[$count] =~ /^(\S+)\s+(\S+)$/) 
					{
						$opt = $1;
						$rep = $2;
						&main::Output(
							"CC$_ := \$(subst $opt ,@@,\$(CC$_))\n",
							"CC$_ := \$(CC$_:@@%=$opt $rep)",							
							"\n"
						);			
						$count++;
					}
					else
					{
						$opt = $opts[$count];
						$rep = $opts[$count+1];
						
						# Substitute '=' with '%' which is a wild card character in makefile.					
						$opt =~ s/=/%/;
					
						&main::Output(
							"CC$_ := \$(CC$_:$opt=$rep)",
							"\n"
						);							
						$count+=2;
					}
				}
			}
		}
		&main::Output(
			"\n"
		);
	}

	&main::Output(		
		"\n"
	);

	#Function call logger
	if ($Function_Call_Logger)	{
		#Send all the debug macros to logger
		foreach (@BldList) {
			&main::Output
			(
				"FCLOGGER$_ = ", 
				$EPOCPath, 
				"tools\\fc_logger\\edgcpfe"
			);

			my @ml = &main::MacroList($_);
			PrintList("\" -D\$_\"", @ml);
			if ($thumbOption==1) {
				&main::Output(
					" \$(COMPILER_THUMB_DEFINES)"
				);
			}
			&main::Output(" \$(COMPILER_INTERWORK_DEFINES)",
						  " \$(CCDEFS)",
						  " \$(FC_LOGGER_DEFINES)",
						  " \$(FC_LOGGER_OPTION)");
			&main::Output(
				"\n",
				"\n"
			);
		}
	}
	
	foreach (@BldList) {
		&main::Output(
			"$_ :"
		);

		if ($BasicTrgType !~ /IMPLIB/io) {
			&main::Output (
				" \\\n\t",
				&Generic_Quote("\$(EPOCTRG$_)\\".&main::Trg($_))
			);
		}

#		lib has to come after the main target so that a .DEF file will be generated if the project is not frozen
		if ($DefFile and not &main::ExportUnfrozen) {
			&main::Output(
				" \\\n",
				"\tLIBRARY\n"
			);
		}
		&main::Output(
			"\n",
			"\n"
		);
	}

	# Resource building is done entirely via cl_generic.pm
	PrintList("\"\nRESOURCE\$_ : MAKEWORK\$_\"", @BldList);
	&main::Output(
		"\n",
		"\n",
	);

	&main::Output(
		"LIBRARY : MAKEWORKLIBRARY"
	);
	if ($BasicTrgType=~/^LIB$/o) {
#		code to ensure that the static libraries for all builds are built at the library stage
			PrintList("\" \$_\"", @BldList);
	}
	elsif ($DefFile and !$NoExportLibrary) {
		unless (&main::ExportUnfrozen) {
			if (-e $DefFile) { # effectively "if project frozen ..."
				if ($PlatName =~ /^ARMV5$/) {
					&main::Output(
						" ", &Generic_Quote("\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.dso"),
						" ", &Generic_Quote("\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.lib"), "\n"
					);
				}
				else {
					&main::Output(
						" ", &Generic_Quote("\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.dso"), "\n"
					);
				}
			}
			else {
				&main::Output(
					"\n",
					"\t\@echo WARNING: Not attempting to create any import libraries.\n",
					"\t\@echo When exports are frozen in \"$DefFile\", regenerate Makefile.\n"
				);
			}
		} else {
			&main::Output(
				"\n",
				"\t\@echo Not attempting to create \"\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.dso\"\n",
				"\t\@echo from frozen .DEF file, since EXPORTUNFROZEN specified.\n"
			);
		}

		my $theDefFile = $DefFile;
		$theDefFile = "\$(EPOCBLD)\\$BaseTrg.def" unless (-e $DefFile);
		&main::Output(
			"\n",
			"\n",
			"# REAL TARGET - LIBRARY (.dso) \n",
			"\n",
			&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"), " : ",
			&Generic_Quote($DefFile), "\n",
				"\tperl -S prepdef.pl ", &Generic_Quote($DefFile), " \"\$(EPOCBLD)\\$ExportLibrary.prep.def\"\n",
				"\telf2e32 --definput=\"\$(EPOCBLD)\\$ExportLibrary.prep.def\" --dso=",
				&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"),
				" --linkas=$LinkAs\n",
			"\n"
		 );
		if ($ExtraExportLibrary) {
			&main::Output(
				"\n",
				&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.dso"), " : ",
				&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"), "\n",
				"\tcopy \"\$<\" \"\$@\"\n"
			);
		}

		# Generate .lib files which will be used for ARMV5_ABIV1 platform (ABIV1 mode toolchain)
		# Only for ARMV5 platform
		if ($PlatName =~ /^ARMV5$/)
		{
			&main::Output(
				"\n",
				"\n",
				"# REAL TARGET - LIBRARY (.lib) \n",
				"\n",
				&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.lib"), " : ",
				&Generic_Quote($DefFile), "\n",
					"\tperl -S prepdef.pl ", &Generic_Quote($DefFile), " \"\$(EPOCBLD)\\$ExportLibrary.prep.def\"\n",
					"\tdef2dll.bat --path=\$(EPOCLIB)\\LIB \\\n\t\t--bldpath=\$(EPOCBLD) \\\n\t\t--import=$ExportLibrary \\\n",
					"\t\t--deffile=\"\$(EPOCBLD)\\$ExportLibrary.prep.def\" \\\n\t\t--linkAs=$LinkAs \\\n\t\t$InterWorking\n",
					"\n",
			);
			if ($ExtraExportLibrary) {
				&main::Output(
					"\n",
					&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.lib"), " : ",
					&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.lib"), "\n",
					"\tcopy \"\$<\" \"\$@\"\n"
				);
			}
		}
	}

	my $freezeDir = &main::Path_Split('Path', $DefFile);
	chop($freezeDir);

	# dummy rule for def files to cope with filename case differences
	unless (&main::ExportUnfrozen) {
		if (-e $DefFile) { # effectively "if project frozen ..."
			&main::Output(
				"\n",
				"\n",
				&Generic_Quote($DefFile), " : ", "\n",
				"\t\@rem Do nothing\n",
			);
		}
	}

	&main::Output(
		"\n",
		"\n",
		&Generic_Quote($freezeDir), " : ", "\n",
		"\tperl -S emkdir.pl \$\@\n",
	);

	&main::Output(
		"\n",
		"\n",
		"FREEZE : ",
		&Generic_Quote($freezeDir), "\n",
	);
	if ($DefFile and $BasicTrgType!~/^IMPLIB$/io) {
#		call perl on the script here so make will die if there are errors
#           - this doesn't happen if calling perl in a batch file
		&main::Output( "\tperl -S efreeze.pl \$(EFREEZE_ALLOW_REMOVE) \"$DefFile\" \"\$(EPOCBLD)\\$ExportLibrary.def\" \n" );
	}
	else {
		&main::Output( "\tperl -e \"print \\\"warning: freeze could not be supported or \\
		         you need to declare an explicitly specified def file using the keyword \\
			 DEFFILE in the MMP file!\\n\\\"\""); 
	}
	&main::Output(
		"\n",
		"CLEANLIBRARY :\n"
	);
	if ($DefFile and !$NoExportLibrary) {
		&main::Output(
			"\t-\$(ERASE) \"\$(EPOCLIB)\\LIB\\$ExportLibrary.dso\"\n"
		);
		if ($ExtraExportLibrary) {
			&main::Output(
				"\t-\$(ERASE) \"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.dso\"\n"
			);
		}
	}
	&main::Output(
		"\n",
		"\n"
	);
	&Generic_MakeWorkDir('MAKEWORKLIBRARY',"${LibPath}");

	&Generic_Releaseables;
}


sub PMBld {

    my $ABI=&main::ABI;
    my @ASSPLibList=&main::ASSPLibList;
    my @SrcList=&main::SrcList;
    my $FeatureVariantBaseTrg=&main::FeatureVariantBaseTrg;
    my $Bld=&main::Bld;
    my $ChopBldPath=&main::Path_Chop(&main::BldPath);
    my $DefFile=&main::DefFile;
    my $EPOCIncPath=&main::EPOCIncPath;
    my $FirstLib=&main::FirstLib;
    my $BasicTrgType=&main::BasicTrgType;
    my @LibList;
    my @RTLibList = &GetRTLibList();
    my $SystemTrg = &main::SystemTrg;
    my $LibPath= &main::LibPath;
    my $LinkAs=&main::LinkAs;
    my $ExportLibrary=&main::ExportLibrary;
    my $NoExportLibrary=&main::NoExportLibrary;
    # N.B. should get better way to detect kernel probably!!
    $SystemTrg = 1 if ($ExportLibrary =~ /EKERN/i);
    my $ChopRelPath=&main::Path_Chop(&main::RelPath);
    my $RelPath=&main::RelPath;
    my @StatLibList=&main::StatLibList;
    my $StatLinkPath=&main::StatLinkPath;
    my $Trg=&main::Trg;
    my $TrgType=&main::TrgType;
    my @UidList=&main::UidList;
	my %Version = &main::Version();
	my $ExtraExportLibrary;
	unless ($Version{explicit}) {
		$ExtraExportLibrary = $ExportLibrary;
		$ExtraExportLibrary =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
	}
	my $objectFiles;

    if ($Bld =~ /DEB/) {
	@LibList = &main::DebugLibList;
    } else {
	@LibList = &main::LibList;
    }

#	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);
    }


    # REAL TARGETS
    #-------------
    &main::Output(
		  "# REAL TARGET - BUILD VARIANT $Bld\n",
		  "\n"
		  );

#	releasables
	my @releaseables;

	push @releaseables, "$RelPath$Trg" if ($BasicTrgType!~/^IMPLIB$/io);
	if ($BasicTrgType=~/^(DLL|EXE)$/o) {
		push @releaseables, "$RelPath$Trg.map";
	}
	if (-e $DefFile and !$NoExportLibrary) { # effectively "if project frozen ..."
		push @releaseables, "$LibPath$ExportLibrary.dso";
		push @releaseables, "$LibPath$ExtraExportLibrary.dso" if ($ExtraExportLibrary);
		if ($PlatName =~ /^ARMV5$/)	{
			push @releaseables, "$LibPath$ExportLibrary.lib";
			push @releaseables, "$LibPath$ExtraExportLibrary.lib" if ($ExtraExportLibrary);
		}
	}

	push @releaseables, &main::FeatureVariantVMapFile() if &main::FeatureVariantVMapFile();

	&main::Output(
		"WHAT$Bld : WHATGENERIC\n",
		"\n",
		"CLEAN$Bld : CLEANBUILD$Bld CLEANRELEASE$Bld\n",
		"\n",
		"CLEANBUILD$Bld : \n",
		"\t\@perl -S ermdir.pl \"\$(EPOCBLD$Bld)\"\n",
		"\n",
		"CLEANRELEASE$Bld : CLEANGENERIC\n",
		"\n"
	);
	
	&Generic_WhatTargets($Bld, "WHAT$Bld", @releaseables);
	my @cleantargets = (@releaseables, "$RelPath$ExtraExportLibrary.sym");
	
	if (-e $DefFile and !$NoExportLibrary) { # effectively "if project frozen ..."
		&Generic_CleanTargets($Bld, "CLEANRELEASE$Bld", @cleantargets);
	}
	else {
		push @cleantargets, "$LibPath$ExportLibrary.dso";
			push @cleantargets, "$LibPath$ExtraExportLibrary.dso" if ($ExtraExportLibrary);
		if ($PlatName =~ /^ARMV5$/) {
            push @cleantargets, "$LibPath$ExportLibrary.lib";
            push @cleantargets, "$LibPath$ExtraExportLibrary.lib" if ($ExtraExportLibrary);
		}
			&Generic_CleanTargets($Bld, "CLEANRELEASE$Bld", @cleantargets);
	}
	
	&Generic_MakeWorkDir("MAKEWORK$Bld",$ChopBldPath);
	&Generic_MakeWorkDir("MAKEWORK$Bld",$ChopRelPath);

	return if ($BasicTrgType=~/^IMPLIB$/io);

	&main::Output(
		"LISTING$Bld : MAKEWORK$Bld"
	);
	foreach (@SrcList) {
			my $BaseSrc = &main::Path_Split('Base', $_);
			my $Ext = &main::Path_Split('Ext', $_);
		if ($Ext =~ /cia/i && ($PlatName ne "GCCE")) {
			$BaseSrc = "$BaseSrc\_";
		}
		&main::Output(
			" \\\n\tLISTING$Bld$BaseSrc"
		);
	}
	&main::Output(
		"\n",
		"\n"
	);
	#Compiler wrapper support starts
	if($IsCompilerWrapperOption)
	{
		my $Platcmpwrap=&main::Plat;
		
		&main::Output(
			"COMPWRAP$Bld : OUTPUT_NAME = ",
			"$Platcmpwrap\_$Bld",
			"\n"
		);
		
		&main::Output(
			"COMPWRAP$Bld : MAKEWORK$Bld"
		);

		foreach (@SrcList) {
			my $BaseSrc = &main::Path_Split('Base', $_);
			&main::Output(
				" \\\n\tCOMPWRAP$Bld$BaseSrc"
			);
		}

		&main::Output(
			"\n",
			"\n"
		);
	}
	#--Compiler wrapper support ends

	# Flag that tells us wheter to run checklib.exe on user-added static libraries.
	my $run_checklib = 0;

  	if (@StatLibList && $BasicTrgType =~ /^(EXE|DLL)$/o && !$SystemTrg && main::StdCppSupport()) {
		# There are user-added static libraries. They should be checked for
		# consistent use of operator new.
		$run_checklib = 1;

		#Create a make variable for the libraries.
		main::Output("\nUSER_ADDED_ARCHIVES_$Bld=");
		PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCSTATLINK$Bld\)\\\\\$_\"\)", @StatLibList);
		main::Output("\n\n");
	}

	&main::Output(
		"LIBS$Bld="
	);
        
	my @depLibs;
	if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
		&main::Output(
			" \\\n\t",
			&Generic_Quote("\$(EPOCSTATLINK$Bld)\\EDLLSTUB.lib")
		);
		push @depLibs, &Generic_Quote("\$(EPOCSTATLINK$Bld)\\EDLLSTUB.lib");
	}
        
	my $StaticRTLib = "";


	if ($SystemTrg) {
		$StaticRTLib = "ksrt";
	}
	else {
		$StaticRTLib = "usrt";
	}

	if ($RVCTVersion) {
		$StaticRTLib .= $RVCTVersion;
	}
	elsif ($GCCEVersion) {
		if ($GCCEMajorVersion < 4) {
			$StaticRTLib .= "2_2";
		}
		else {
			$StaticRTLib .= "3_1";
		}
	}
	else {
		$StaticRTLib .= "2_2";
	}

	&main::Output(" \\\n\$(EPOCSTATLINK$Bld)\\$StaticRTLib\.lib");

	&main::Output(" \\\n\t",getConfigVariable('VIA_FILE_PREFIX'));
	PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCBSFSTATLINK$Bld\)\\\\\$_\"\)", @StatLibList);
	&main::Output(" \\\n\t",getConfigVariable('VIA_FILE_SUFFIX'));
	
	@depLibs = (@depLibs, DepLinkList("\&Generic_Quote\(\"\\\$\(EPOCBSFSTATLINK$Bld\)\\\\\$_\"\)", @StatLibList));
	
	
	my @ImportLibList = ImportLibraryList(@LibList);
	PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @ImportLibList);
	@depLibs = (@depLibs, DepLinkList("\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @ImportLibList));
        
	if ($TrgType=~/^STDEXE$/o || $TrgType=~/^STDDLL$/o) {
		$NamedSymLkup = 1;
		my @OEImportLibraryList = &GetOEImportLibList();
		@OEImportLibraryList = ImportLibraryList(@OEImportLibraryList);
		if(not (grep /^libc.dso$/i, @LibList)) {
				push @OEImportLibraryList, "libc.dso";
		}
		PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @OEImportLibraryList);
		@depLibs = (@depLibs, DepLinkList("\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @OEImportLibraryList));
	}

	unless ($ArmRT || ($BasicTrgType=~/^LIB$/o)) {
		my $TargLib = "$ExportLibrary.dso";
		$TargLib =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
		unless ($SystemTrg) {
			foreach (@RTLibList) {
  				# Ignore the empty file name      Modified by Kun Xu for DEF126030 on 06/08/2008
  				if(!$_) 
  				{
  					next;		
  				}
				&main::Output(
					" \\\n\t",
					&Generic_Quote("\$(EPOCLIB)\\LIB\\$_")
				) unless ($_ =~ /$TargLib/i);
				push @depLibs, &Generic_Quote("\$(EPOCLIB)\\LIB\\$_") unless ($_ =~ /$TargLib/i);
			}
		}
	}
    #OE Glue Code 
	if ($TrgType=~/^STDEXE$/o) {
		my @OELibList = &GetOELibList();
		foreach (@OELibList) {
			&main::Output(
				" \\\n\t",
				&Generic_Quote("\$(EPOCSTATLINK$Bld)\\$_"),
			);
			push @depLibs, &Generic_Quote("\$(EPOCSTATLINK$Bld)\\$_");
		}
	}
	PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\$_\"\)", @ToolChainLibList);
                
	&main::Output(
		"\n",
		"\n"
	);
        
	main::Output(
                "LIBS$Bld" . "DEPS="
	);
        
	my @tmp;
	for my $lib (@depLibs)
	{
            $lib =~ s/\(.*\.o\)//;
            $lib =~ s/\\$//;
            push @tmp, $lib unless ($lib =~ /-\(/ || $lib =~ /-\)/);
	}
                
	PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\$_\"\)", @tmp);
        
	&main::Output(
			"\n",
			"\n"
	);

	&main::Output(
		"VTBLEXPORTS$Bld="
	);
        my $vtobj = quotemeta("(VtblExports.o)");
	&main::Output(
		"\n",
		"\n"
	);

        &main::Output(
			"OBJECTS$Bld="
		);
        foreach (@SrcList) {
			my $BaseSrc = &main::Path_Split('Base', $_);
			my $Ext = &main::Path_Split('Ext', $_);
		if ($Ext =~ /cia/i && ($PlatName ne "GCCE")) {
			$BaseSrc = "$BaseSrc\_";
		}

			&main::Output(
				" \\\n\t",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o")
			  );

			$objectFiles .= &main::BldPath.$BaseSrc.".o ";
	}
        &main::Output(
			"\n",
		"\n"
	);

	# IsCustomDllUseCase() subroutine is called to check if the given executable 
	# is a custom dll or not.
	my $IsCustomDll = IsCustomDllUseCase();

	if ($IsCustomDll) 
	{
		# Generate ".bin" file(assembly listing file) only if frozen deffile is present and EXPORTUNFROZEN is not specified
		# in the Mmp file.
		if((-e $DefFile) && (!&main::ExportUnfrozen))
		{
			&main::Output(
				"EXPFILE$Bld = \$(EPOCBLD$Bld)\\$ExportLibrary.bin \n",			
				"\n"
			);
		}
		else 
		{
			&main::Output(
				"EXPFILE$Bld = \n",
				"\n"
			);
		}		
	}
	
	# Create "via" file containing all object files in order to reduce
	# command line lengths in pertinent calls
	my $objectsViaFile = &main::CommandFile();
	my $viaoption = getConfigVariable('COMMANDFILE_OPTION');
	
    if ($BasicTrgType=~/^LIB$/o && StdCppTarget() ) {

        # Add the magic object that identifies the library as a STDLIB.
        $objectFiles .= "$ENV{EPOCROOT}epoc32/tools/tag/tag_elf";
	}

	$objectFiles =~ s/\\/\//g ;

	&main::CreateExtraFile($objectsViaFile, $objectFiles);
		 
		   &main::Output(
			 &Generic_Quote("\$(EPOCTRG$Bld)\\$Trg"),
			 " : \$(OBJECTS$Bld) \$(LIBS". $Bld . "DEPS)"
            );

	if (-e $DefFile) { # effectively "if project frozen ..."
		&main::Output(
			" ", &Generic_Quote($DefFile)
		);
	}

	if($IsCustomDll eq 1)
	{
		&main::Output( " \$(EXPFILE$Bld) " );	
	}

    &main::Output("\n");


#       get rid of any -symbols produced .map file
        if ($BasicTrgType=~/^(DLL|EXE)/o) {
			&main::Output(
			"\t-\$(ERASE) \"\$(EPOCTRG$Bld)\\$Trg.map\" \n"
		);
		}

		my $AbsentSubst = '';
		if ($BasicTrgType=~/^(DLL|EXE)/o) {

			if ($run_checklib) {
				my $checklib = "checklib";

				if ( StdCppTarget() ) {
					$checklib .= " stdc++ --elf";
				}
				else {
					$checklib .= " symc++ --elf";
				}

				&main::Output( "\t$checklib ","\$(USER_ADDED_ARCHIVES_$Bld)\n" );
			}

			my $WrapLD = $IsProxyWrapperOption ? "$ENV{ABLD_COMPWRAP} " : "";
			if ($Bld =~ /DEB/)
			{
				if($PlatName ne "GCCE"){
					# if the compiler is RVCT then append SYMBIAN_UDEB_LINK_FLAGS to option string 
					# in order to override the default ones. 
					&main::Output(
						"\t", $WrapLD, "\$(LD) ","\$(STATIC_LIBS) ", "\$(SHARED_OBJECT_OPTION) ",
						"\$(CODE_SEGMENT_START) ", "\$(DATA_SEGMENT_START) 0x400000 ", "\$(SYMVER_OPTION) ", "\$(SYMBIAN_UDEB_LINK_FLAGS) ", "\$(SO_NAME_OPTION) ","$LinkAs"
					); 
				} else {
					&main::Output(
						"\t", $WrapLD, "\$(LD) ","\$(STATIC_LIBS) ","\$(SYMBIAN_UDEB_LINK_FLAGS) ", "\$(SHARED_OBJECT_OPTION) ",
						"\$(CODE_SEGMENT_START) ", "\$(DATA_SEGMENT_START) 0x400000 ", "\$(SYMVER_OPTION) ","\$(SO_NAME_OPTION) ","$LinkAs"
					);
				}
			}
			else
			{
				if($PlatName ne "GCCE"){
					# if the compiler is RVCT then append SYMBIAN_UREL_LINK_FLAGS to option string 
					# in order to override the default ones. 
					&main::Output(
						"\t", $WrapLD, "\$(LD) ","\$(STATIC_LIBS) ","\$(SHARED_OBJECT_OPTION) ",
						"\$(CODE_SEGMENT_START) ", "\$(DATA_SEGMENT_START) 0x400000 ", "\$(SYMVER_OPTION) ", "\$(SYMBIAN_UREL_LINK_FLAGS) ", "\$(SO_NAME_OPTION) ", "$LinkAs"
					);
				} else {
					&main::Output(
						"\t", $WrapLD, "\$(LD) ","\$(STATIC_LIBS) ","\$(SYMBIAN_UREL_LINK_FLAGS) ","\$(SHARED_OBJECT_OPTION) ",
						"\$(CODE_SEGMENT_START) ", "\$(DATA_SEGMENT_START) 0x400000 ", "\$(SYMVER_OPTION) ","\$(SO_NAME_OPTION) ","$LinkAs"
					);
				}
			}

			if(&main::DebugSwitchUsed()){
				if(&main::SymbolicDebugEnabled() ) {
					&main::Output(
						" \$(LINKER_DEBUG_OPTION) "
					);
				}
				else {
					&main::Output(
						" \$(LINKER_NODEBUG_OPTION) "
					);
				}
			}
			elsif($Bld =~/DEB/){
				&main::Output(
					" \$(LINKER_DEBUG_OPTION) "
				);
			}
			else {
				&main::Output(
					" \$(LINKER_NODEBUG_OPTION) "
				);
			}

			my $EntrySymbol;
			if ($BasicTrgType=~/^DLL$/o) {
				$EntrySymbol = '_E32Dll';
			}
			elsif ($BasicTrgType=~/^EXE$/o) {
				$EntrySymbol = '_E32Startup';
			}
			if ($EntrySymbol) {
				$AbsentSubst = " --absent $EntrySymbol";
			}

			if (($BasicTrgType=~/^DLL$/o) || ($BasicTrgType=~/^EXE$/o)) {
				&main::Output(
					" \$(LINKER_ENTRY_OPTION)",
					" $EntrySymbol "
					);
				my $undefined_option = getConfigVariable('UNDEFINED_SYMBOL_REF_OPTION');
				if ($undefined_option)
				{
					&main::Output(
						" \$(UNDEFINED_SYMBOL_REF_OPTION)",
						" $EntrySymbol "
					);
				}
			}

			if ($BasicTrgType=~/^DLL$/o) {
				# get the right object file for the entry point
				my $ObjFile="\$(EDLL_OBJECT)";
				if ($FirstLib =~ /EDEV/i) {
					$ObjFile="\$(DENTRY_OBJECT)";
				}
				if ($FirstLib =~ /EKLL/i) {
					$ObjFile="\$(LENTRY_OBJECT)";
				}
				if ($FirstLib =~ /EEXT/i) {
					$ObjFile="\$(XENTRY_OBJECT)";
				}
				if ($FirstLib =~ /EVAR/i) {
					$ObjFile="\$(VENTRY_OBJECT)";
				}

				&main::Output(
					" \$(EPOCSTATLINK$Bld)\\$FirstLib", "$ObjFile",
					" \$(EPOCSTATLINK$Bld)\\$FirstLib", " \\", "\n"
				);
			} elsif ($BasicTrgType=~/^EXE$/o || $TrgType=~/^EXEXP$/o) {
				# get the right object file for the entry point
				my $ObjFile="\$(EEXE_OBJECT)";
				if ($FirstLib =~ /KC_EXE/i) {
					$ObjFile="\$(KENTRY_OBJECT)";
				}

				&main::Output(
					" \$(EPOCSTATLINK$Bld)\\$FirstLib", "$ObjFile",
					" \$(EPOCSTATLINK$Bld)\\$FirstLib", " \\", "\n"
				);
			}

			&main::Output(
				"\t\t\$(LINKER_OUTPUT_OPTION) \"\$(EPOCBLD$Bld)\\$Trg\" \\\n",
#				"\t\t\$(OBJECTS$Bld) \\\n"
			);

		&main::Output(
			"\t\t\$(LINKER_SYMBOLS_MAP_OPTION) ",
			"\$(","$Bld","_MAP_FILE) \\\n"
		);

		# Pass in the command file if the command file option is passed in
		if($viaoption) {
                        #'@' is for GCCE whos version is not 3.4.3
			if($viaoption eq '@'){
				main::Output(
					"\t\t$viaoption$objectsViaFile \\\n"
				);
			}
                        #'-via' is for RVCT 
			else{
				main::Output(
					"\t\t$viaoption $objectsViaFile \\\n"
				);
			}
		}
		else {
			&main::Output(
				"\t\t\$(OBJECTS$Bld) \\\n"
			);
		}

		if($IsCustomDll eq 1) {
			&main::Output( "\t\t\$(EXPFILE$Bld) \\\n" );
		}

			&main::Output(
				"\t\t\$(LIBS$Bld) \\\n",
				"\t\t\$(VTBLEXPORTS$Bld) \$(USERLDFLAGS) \n"
			);

			if(&main::DebugSwitchUsed() ){
				if(&main::SymbolicDebugEnabled() ) {
				&main::Output(
					"\tcopy \"\$(EPOCBLD$Bld)\\$Trg\" \"\$(EPOCTRG$Bld)\\$FeatureVariantBaseTrg.sym\"\n"
					);
				}
			}
			elsif ($Bld=~/^U?DEB$/o) {
				   &main::Output(
				   "\tcopy \"\$(EPOCBLD$Bld)\\$Trg\" \"\$(EPOCTRG$Bld)\\$FeatureVariantBaseTrg.sym\"\n"
			   );
			}
		if (-e $DefFile) {
			&main::Output(
				"\tcopy ", &Generic_Quote(("\"$DefFile\"")), " \"\$(EPOCBLD)\\$ExportLibrary.prep.def\"\n",
			);
		}

		&main::Output(
			"\telf2e32 --sid=", &main::SecureId(), " "
		);

		if (&main::IsDebuggable eq DEBUGGABLE) {
			&main::Output(
				' --debuggable '
			);
		}

		if (&main::IsDebuggable eq DEBUGGABLE_UDEBONLY) {
			if ($Bld=~/^UDEB$/o) {
				&main::Output(
				' --debuggable '
				);
			}
		}
		
		# Do not export Arm Static Library Symbols
		if (&Armutl_ArmLibList) {
			&main::Output(
				' --excludeunwantedexports'
			);
		}

		if ($IsCustomDll eq 1) {
			&main::Output(
				' --customdlltarget'
			);
		}
		if (keys(%Version)) {
			&main::Output(
				' --version=', &Genutl_VersionToUserString(%Version)
			);
		}
		# exexps are allowed data, but they look like dlls to elftran....
		if (&main::AllowDllData || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
			&main::Output(
				' --dlldata'
			);
		}
		if (&main::DataLinkAddress) {
			&main::Output(
				' --datalinkaddress=',&main::DataLinkAddress
			);
		}
		if (&main::FixedProcess) {
			&main::Output(
				' --fixedaddress'
			);
		}
		if (&main::HeapSize) {
			my %HeapSize=&main::HeapSize;
			&main::Output(
				' --heap=',$HeapSize{Min},',',$HeapSize{Max}
			);
		}
		if (&main::ProcessPriority) {
			&main::Output(
				' --priority=',&main::ProcessPriority
			);
		}
		if (&main::StackSize) {
			&main::Output(
				' --stack=',&main::StackSize
			);
		}
		&main::Output(
			"\\\n\t\t"
		);

		my $i=1;
		foreach (@UidList) {
			&main::Output(
				" --uid$i=$_"
			);
			$i++;
		}
		if(&main::VendorId) {
			&main::Output(
				' --vid=',&main::VendorId
			);
		}
		&main::Output(
			"\\\n\t\t"
		);

		&main::Output(
			' --capability=',&main::Capability
		);

		my $vfpv2_support = getConfigVariable('VFP2MODE_OPTION');
		if ($vfpv2_support && &main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i))
		{
			&main::Output(
				' --fpu=vfpv2'
			);
		}
		else
		{
			&main::Output(
				' --fpu=softvfp'
			);
		}

		if (&main::SmpSafe)
		{
			&main::Output(
				' --smpsafe'
			);
		}


		if(($BasicTrgType=~/^DLL/ && $TrgType!~/^DLL/ ) || $TrgType=~/^EXEXP/ || $TrgType=~/^STDEXE/){
			&main::Output(
				' --targettype=',$TrgType
				);
		}
		else{
			&main::Output(
				' --targettype=',$BasicTrgType
				);
		}

		&main::Output(
			' --output=',"\"\$\@\""
			);
		if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
			if (-e $DefFile) {
				&main::Output(
					' --definput=',"\"\$(EPOCBLD)\\$ExportLibrary.prep.def\""
					);
			}
			# Non-callable exports will be ignored if the MMP file does not contain the DEFFILE keyword or contains the NOEXPORTLIBRARY keyword			 
			if (!($DefFile) || $NoExportLibrary) {				
				&main::Output( " --ignorenoncallable" );
			}
			&main::Output(
				' --dso=',
				&Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.dso")
				);
			&main::Output(
				' --defoutput=',
				&Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.def")
				);
				if(&main::ExportUnfrozen) {
					&main::Output( ' --unfrozen ');
				}
			}
		#the input elf file - as the last arg
		&main::Output(
			" --elfinput=","\"\$(EPOCBLD$Bld)\\$Trg\"",
			" --linkas=$LinkAs"
			);
		if (&main::CompressTarget)
			{
			&main::Output(
			" --uncompressed"
			);
			}
		else
			{
			if(&main::CompressTargetMode == NOCOMPRESSIONMETHOD)
			{
				# Do nothing
			}
			elsif(&main::CompressTargetMode == INFLATECOMPRESSIONMETHOD)
			{
			&main::Output(
				" --compressionmethod inflate"
			);
			}
			elsif(&main::CompressTargetMode == BYTEPAIRCOMPRESSIONMETHOD)
			{
			&main::Output(
				" --compressionmethod bytepair"
			);
			}

			}
		
		if($NamedSymLkup){
			&main::Output(" --namedlookup"
		);
		}

		&main::Output(
		" --libpath=", "\"\$(EPOCLIB)\\LIB\""
		);

		if($BasicTrgType=~/^DLL/ && $TrgType!~/^DLL/){
			my $Export;
			my $Ordinal=1;
			foreach $Export (&main::Exports) {
				if($Ordinal == 1) {
				&main::Output(" --sysdef=");
				}
				&main::Output(
					"$Export,$Ordinal; "
				);
				$Ordinal++;
			}
		}

		if (&main::CodePagingTargetMode == UNPAGED) {
			&main::Output(
				' --codepaging=unpaged'
			);
		}
		elsif (&main::CodePagingTargetMode == PAGED) {
			&main::Output(
				' --codepaging=paged'
			);
		}

		if (&main::DataPagingTargetMode == UNPAGED) {
			&main::Output(
				' --datapaging=unpaged'
			);
		}
		elsif (&main::DataPagingTargetMode == PAGED) {
			&main::Output(
				' --datapaging=paged'
			);
		}

		&main::Output(
			"\n"
		);

		}
         elsif ($BasicTrgType=~/^LIB$/o) {
			&main::Output(
			"\t\$(AR) ",
				" \$(ARCHIVER_CREATE_OPTION) ",
				" \$(EPOCBSFSTATLINK$Bld)\\$Trg \\\n"
			);
		# Pass in the command file if the command file option is passed in
		if($viaoption) {
                        #'@' is for GCCE whos version is not 3.4.3
			if($viaoption eq '@'){
				&main::Output(
					"\t\t$viaoption$objectsViaFile\n"
				);
			}
                        #'-via' is for RVCT  
			else{
				&main::Output(
					"\t\t$viaoption $objectsViaFile\n"
				);
			}
		}
		else {
			&main::Output(
				"\t\t\$(OBJECTS$Bld) \n"
			);
		}
		# Pass the archiver options which can be customized form BSF file
		&main::Output(
			"\t\t\$(AR_OPTIONS) \n"
		);
         }

         &main::Output(
		 "\n"
	 );

	if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
		&main::Output(
			"\tcopy ", " \"\$(EPOCBLD$Bld)\\$ExportLibrary.def\" ", "\"\$(EPOCBLD)\\$ExportLibrary.def\"\n"
			);
		if  (&main::ExportUnfrozen) {
			if ($PlatName =~ /^ARMV5$/)
			{
				&main::Output(
				"\tdef2dll.bat --path=\$(EPOCBLD$Bld) \\\n\t\t--bldpath=\$(EPOCBLD$Bld) \\\n\t\t--export=$ExportLibrary \\\n\t\t--import=$ExportLibrary \\\n",
				"\t\t--deffile=\$(EPOCBLD)\\$ExportLibrary.def \\\n\t\t--linkAs=$LinkAs \\\n\t\t$InterWorking \\\n\t\t--absent=undef \n"
				);
				&main::Output(
					"\n",
					"\tcopy ", " \"\$(EPOCBLD$Bld)\\$ExportLibrary.lib\" ",
					"\"\$(EPOCLIB)\\LIB\\$ExportLibrary.lib\"",
					"\n"
				);
				if ($ExtraExportLibrary) {
				&main::Output(
					"\n",
					"\tcopy ", " \"\$(EPOCLIB)\\LIB\\$ExportLibrary.lib\" ",
					"\"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.lib\"",
					"\n"
				);
				}
			}

			&main::Output(
					  "\n",
				  "\tcopy ", " \"\$(EPOCBLD$Bld)\\$ExportLibrary.dso\" ",
				  "\"\$(EPOCLIB)\\LIB\\$ExportLibrary.dso\"",
				  "\n"
				 );

			&main::Output(
					  "\n",
				  "\tcopy ", " \"\$(EPOCBLD$Bld)\\$ExportLibrary.dso\" ",
				  "\"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.dso\"",
				  "\n"
				 ) if ($ExtraExportLibrary);

		}
	}

	if($IsCustomDll eq 1)
	{
		&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.bin"), ": $DefFile\n");

	    my $theDefFile = "\$(EPOCBLD)\\$ExportLibrary.def";
	    $theDefFile = $DefFile if (-e $DefFile && !&main::ExportUnfrozen);
	    my $theAssembler = " \$(ASM) ";
	    &main::Output(
		"\telf2e32  \\\n\t\t--definput=$theDefFile \\\n\t\t--dump=a \\\n\t\t--output=\$(EPOCBLD$Bld)\\$ExportLibrary.s \n",
  		"\t$theAssembler \$(AAPCS_OPTION) \\\n\t\t \$(ASM_OUTPUT_OPTION) \$(EPOCBLD$Bld)\\$ExportLibrary.bin  \$(EPOCBLD$Bld)\\$ExportLibrary.s\n\n"
	    );
		&main::Output(
			"\t-\$(ERASE) \"\$(EPOCBLD$Bld)\\$ExportLibrary.s\"\n\n"
		);
	}

    &main::Output( "\n" );
}

# Set to 1 if multifile compilation wanted
my $domultifile = 0;

sub DoMultiFile () {
        return $ENV{RVCTMultiFile} if (defined $ENV{RVCTMultiFile});
	return $domultifile;
}

my %CompilationGroups = ();

sub InitMultiFileCompilation() {
#	Do preparatory work for multifile compilation
	my $SourceStructRef=&main::SourceStructRef;

#	We sort the source files by path and extension. These form natural groups to compile together.
	my %PathToSourceMap = ();
	foreach my $SourceRef (@$SourceStructRef) {
		my $SrcFile = $$SourceRef{CurFile};
		my $Ext = &main::Path_Split('Ext', $SrcFile);
			push @{$PathToSourceMap{$$SourceRef{SrcPath}}{$Ext}}, $SrcFile;
	}

#	Now we split each group into sets of 10.
	foreach my $SrcPath (keys %PathToSourceMap) {
		foreach my $Ext (keys %{$PathToSourceMap{$SrcPath}}) {
			my @FileList;
			my @ObjectList;
			my @SourceList;
			my $NumToGo = 10;
			foreach my $File (@{$PathToSourceMap{$SrcPath}{$Ext}}) {
				my $base = &main::Path_Split('Base', $File);
				my $cia = ($Ext =~ /cia/i);
				$base .= "_" if $cia && ($PlatName ne "GCCE");
				push @FileList, $File;
				push @ObjectList, "$base.o";
#				this gives us our source files xxx
				push @SourceList, ($cia && ($PlatName ne "GCCE")) ? "$base.cpp" : "$SrcPath$base$Ext";
				$NumToGo--;
				unless ($NumToGo) {
#					   Use the last file as the key. This means e.g that all the dependency
#					   info will have been generated for the earlier files in the list
					   push @{$CompilationGroups{$FileList[$#FileList]}{Sources}}, @SourceList;
						   push @{$CompilationGroups{$FileList[$#FileList]}{Objects}}, @ObjectList;
					   $NumToGo = 10;
					   undef @FileList;
					   undef @ObjectList;
					   undef @SourceList;
				}
			}
			push @{$CompilationGroups{$FileList[$#FileList]}{Sources}}, @SourceList;
			push @{$CompilationGroups{$FileList[$#FileList]}{Objects}}, @ObjectList;
		}
	}

#	debug print out
	if (0) {
	foreach my $keyfile (keys %CompilationGroups) {
		print "$keyfile :\n";
		foreach my $class (keys %{$CompilationGroups{$keyfile}}) {
			print "\t$class:\n\t\t";
			print join " ", @{$CompilationGroups{$keyfile}{$class}}, "\n";
		}
	}
	}

}

sub PMStartSrcList {

	&main::Output(
		"# SOURCES\n",
		"\n"
	);

	InitMultiFileCompilation() if DoMultiFile();

}

sub PMBitMapBld {

	&Generic_BitMapBld;

}

sub PMResrcBld {

	&Generic_ResrcBld;

}

sub PMAifBld {
	&Generic_AifBld;
}


sub PMStartSrc {
	my $Src=&main::Src;

	&main::Output(
		"# Source $Src\n",
		"\n"
	);
}

sub PMSrcDepend {
	my @DepList=&main::DepList;
	return if (@DepList == 0);

	my @BldList=&main::BldList;
	my $BaseSrc=&main::BaseSrc;
	my $ExtSrc=&main::ExtSrc;

	my $BaseObj=$BaseSrc;
	my $cia = 0;
	if ($ExtSrc =~ /cia/i ) {
		$cia = 1;
		$BaseObj .= '_' if ($PlatName ne "GCCE");
	}

  	foreach my $Bld (@BldList) {
		my $tranasm = getConfigVariable('TRANASM');
		if ($tranasm)
		{
			&main::Output(
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " ",
			) if $cia && ($PlatName ne "GCCE");
		}

		&main::Output(
  			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.cpp"), " ",
		) if $cia && ($PlatName ne "GCCE");
		&main::Output(
  			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " ",
  			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.o"), " \\\n",
		);
	}
	&main::Output(
		":"
	);

	my $prefix_file=getConfigVariable('PREFIXFILE');

	my @tempdeplist = &main::DepList;

	my $totalcount = $#tempdeplist;
	my $count = 0;
	while( $totalcount >= $count )
	{
		my $dependencyfile = shift(@tempdeplist);
		if($dependencyfile eq $prefix_file )
		{
			$DepList[$count]="\$(PREFIXFILE)";
		}
		$count += 1;
	}

        PrintList("\' \\\n\t\'\.\&Generic_Quote\(\$_\)", @DepList);
	&main::Output(
		"\n",
		"\n"
	);
}

sub PMSrcBldDepend {
	my @DepList=&main::DepList;
	return if (@DepList == 0);

	my $Bld=&main::Bld;
	my $BaseSrc=&main::BaseSrc;
	my $ExtSrc=&main::ExtSrc;

	my $BaseObj=$BaseSrc;
	my $cia = 0;
	if ($ExtSrc =~ /cia/i ) {
		$cia = 1;
		$BaseObj .= '_' if ($PlatName ne "GCCE");
	}

	my $tranasm = getConfigVariable('TRANASM');
	if ($tranasm)
	{
		&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " ",
		) if $cia && ($PlatName ne "GCCE");
	}

	&main::Output(
		&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.cpp"), " ",
	) if $cia && ($PlatName ne "GCCE");

	&main::Output(
		&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " ",
		&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.o"), " :",
	);

	my $prefix_file=getConfigVariable('PREFIXFILE');

	my @tempdeplist = &main::DepList;

	my $totalcount = $#tempdeplist;
	my $count = 0;
	while( $totalcount >= $count )
	{
		my $dependencyfile = shift(@tempdeplist);
		if($dependencyfile eq $prefix_file )
		{
			$DepList[$count]="\$(PREFIXFILE)";
		}
		$count += 1;
	}

        PrintList("\' \\\n\t\'\.\&Generic_Quote\(\$_\)", @DepList);
	&main::Output(
		"\n",
		"\n"
	);
}

sub quoted_path
{
    my $curdrive="";
    my ($arg) = @_;
    return "\"$arg\"" if ($arg !~ /^\\[^\\]/);	# not an absolute path

		$curdrive=$1 if (cwd =~ /^(.:)/);
    return "\"$curdrive$arg\"";
}

sub PMPrefixFile
{
# Prefix Header File passed to the preprocessor

	my $prefix_file=getConfigVariable('PREFIXFILE');
	return quoted_path($prefix_file) if defined $prefix_file;
}

sub PMToolChainIncDir
	{
	# Extra system include directories dictated by the toolchain
	return $ToolChainIncDir;
	}

sub PMEndSrcBld {
#       Generate multifile compilation stuff if needed.
        if (DoMultiFile()) {
		   MultiFileEndSrcBld();
		   return;
	}

	my $ABI=&main::ABI;
	my $Plat=&main::Plat;
	my $BaseSrc=&main::BaseSrc;
	my $Bld=&main::Bld;
	my $Src=lc &main::Src;
	my $SrcPath=&main::SrcPath;
	my $BaseTrg=&main::BaseTrg;
	my $BldPath = &main::BldPath;
	my $Ext = &main::Path_Split('Ext', $Src);
	$Src = ucfirst $Src if ($Ext !~ /\.(cpp|c)$/);
	my $LangOptions = &SelectLangOptions($Ext);
	# support for auto 'translated' ASM
	my $AsmFilep = $AsmFiles{$Src};

	$preinclude = &GetToolChainPreInclude();
	
	#Function call logger takes -I as include option
	my $FCLogger_inc_option = getConfigVariable('FC_LOGGER_INCLUDE_OPTION'); 
	my $logger_preinclude = getConfigVariable('PREINCLUDE_OPTION_FCLOGGER'); 
	my $Dictionary_File_Name = getConfigVariable('FC_LOGGER_DICTIONARY_FILE_NAME');
	my $Generated_C_File_Name = getConfigVariable('FC_LOGGER_GENERATED_C_FILE_NAME');
	
	my $ChopSrcPath=&main::Path_Chop($SrcPath);
	my $lfboption = LinkerFeedBackOption();
	my $LstExt ;
	if($Plat =~ /^(ARMV[6-9])/i){
		$LstExt = $1 ;	
	}
	else{
		$LstExt = $ABI;
	}
	if ($AsmFilep || ($Ext =~ /cia/i && ($PlatName ne "GCCE"))) {
		&main::Output(
# compile the translated, preprocessed source
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.o"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
			"\t\@echo $Src\n",
			"\t\$(CC$Bld) $lfboption $LangOptions ", "\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp)\n",
			"\n"
			);
# rule to translate the preprocessed source
			my $tranasm = getConfigVariable('TRANASM');
			if ($tranasm)
			{
		&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), "\n",

				"\t\$(TRANASM) \$(TRANASM_FLAGS) \$(TRANASM_OUTPUT_OPTION)\$\@ \$(TRANASM_INPUT_OPTION)\$(EPOCBLD$Bld)\\$BaseSrc.pre\n",
			"\n"
			);
# rule to preprocess the source
		&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\$(CC$Bld) \$(PREPROCESSOR_OPTION) $preinclude $LangOptions ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) $ChopSrcPath\\$Src \$(OUTPUT_OPTION) \$\@) \n",
# generate an assembly listing target too
			"LISTING$Bld$BaseSrc\_ : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), "\n",
			"\t", &Generic_CopyAction("$SrcPath$BaseSrc\_.$LstExt.lst"),
			"\n",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
			"\t\$(CC$Bld) $LangOptions ", "\$(ASSEMBLER_LISTING_OPTION) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp)\n",
			"\n"
			);
			}
			else
			{
			&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\$(CC$Bld) \$(PREPROCESSOR_OPTION) $preinclude $LangOptions ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) $ChopSrcPath\\$Src \$(OUTPUT_OPTION) \$\@) \n",
# generate an assembly listing target too
			"LISTING$Bld$BaseSrc\_ : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), "\n",
			"\t", &Generic_CopyAction("$SrcPath$BaseSrc\_.$LstExt.lst"),
			"\n",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
			"\t\$(CC$Bld) $LangOptions ", "\$(ASSEMBLER_LISTING_OPTION) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp)\n",
			"\n"
			);
			}
	} 
	else {
		#If Function call logging is enabled, add call to function call logger
		if ($Function_Call_Logger)	{
			&main::Output(
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o"), 
				" : ",
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.int.cpp"), 
				"\n",
				"\t\@echo $BaseSrc.int.cpp\n",
				"\t\$(CC$Bld) $lfboption$LangOptions ", 
				" \$(INCLUDE_OPTION) ",
				"\$(call absolutePaths, $ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ \$(EPOCBLD$Bld)\\$BaseSrc.int.cpp)\n",
				"\n",
# generate an assembly listing target too
				"LISTING$Bld$BaseSrc : ", 
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), 
				"\n",
				"\t",
				&Generic_CopyAction("$SrcPath$BaseSrc.$LstExt.lst"),
				"\n",
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), 
				" : ",
				&Generic_Quote("$SrcPath$Src"), 
				"\n",
				"\t\$(CC$Bld) $LangOptions ",
				"\$(ASSEMBLER_LISTING_OPTION) ",
				"\$(INCLUDE_OPTION)",
				" \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ $ChopSrcPath\\$Src) \n",
				"\n"
			);
			
			#Call to Function Call Logger
			&main::Output(
				&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.int.cpp"),
				" : ",
				&Generic_Quote("$SrcPath\\$Src"),
				"\n",
				"\t\@echo $BaseSrc.int.cpp\n",
				"\t\$(FCLOGGER$Bld) $lfboption \\\n" ,
				"\t$FCLogger_inc_option $ChopSrcPath \\\n",
				"\t$logger_preinclude \\\n ",
				"\t\$(INCDIR_FCLOGGER) \\\n" ,
				"\t$Dictionary_File_Name $BldPath$BaseTrg.txt \\\n" ,
				"\t$Generated_C_File_Name \$\@ $ChopSrcPath\\$Src \n",
				"\n\n"
			);
		}
		else {
			&main::Output(
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\@echo $Src\n",
			"\t\$(CC$Bld) $lfboption $LangOptions ", "\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ $ChopSrcPath\\$Src)\n",
			"\n",
# generate an assembly listing target too
			"LISTING$Bld$BaseSrc : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), "\n",
			"\t", &Generic_CopyAction("$SrcPath$BaseSrc.$LstExt.lst"),
			"\n",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\$(CC$Bld) $LangOptions ","\$(ASSEMBLER_LISTING_OPTION) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ $ChopSrcPath\\$Src) \n",
			"\n"
			);
			# Compiler wrapper support starts...
			if($IsCompilerWrapperOption)
			{
				&main::Output(
					"COMPWRAP$Bld$BaseSrc : ",
					&Generic_Quote("$SrcPath$Src"), "\n",
					"\t\@echo Analysing $Src\n",
					"\t\$(COMPWRAP) \$(CC$Bld) $lfboption $LangOptions ", "\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR) \$(OUTPUT_OPTION) \$\@ $ChopSrcPath\\$Src)\n",
					"\n"
				);
			}
			# Compiler wrapper support ends...
		}
	}
}

my $MFVarN = 0;
sub MultiFileEndSrcBld {
	my $ABI=&main::ABI;
	my $BaseSrc=&main::BaseSrc;
	my $Bld=&main::Bld;
        my $KeyFile = &main::Src;
	my $Src=ucfirst lc $KeyFile;
	my $SrcPath=&main::SrcPath;
	my $Ext = &main::Path_Split('Ext', $Src);
	my $LangOptions = &SelectLangOptions($Ext);
	# support for auto 'translated' ASM
	my $AsmFilep = $AsmFiles{$Src};

	my $ChopSrcPath=&main::Path_Chop($SrcPath);
	my $lfboption = LinkerFeedBackOption();

	if ($AsmFilep || ($Ext =~ /cia/i && ($PlatName ne "GCCE"))) {
		if ($CompilationGroups{$KeyFile}) {
# compile the translated, preprocessed source
			   &main::Output( "OBJECTS$MFVarN = ");
			   foreach my $obj (@{$CompilationGroups{$KeyFile}{Objects}}) {
				   &main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$obj"), " ");
			   }
				   &main::Output( "\n\n");
			   &main::Output( "SOURCES$MFVarN = ");
			   foreach my $src (@{$CompilationGroups{$KeyFile}{Sources}}) {
				   &main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$src", " "));
			   }
				   &main::Output( "\n\n");
			   &main::Output( "\$(OBJECTS$MFVarN) : \$(SOURCES$MFVarN) \n");

			   &main::Output(
					 "\t\@echo Compiling \$(SOURCES$MFVarN)\n",
					 "\t\$(CC$Bld) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR)) $lfboption\\\n",
					 "\t\t$LangOptions \$(OUTPUT_OPTION) \$\@ --multifile \$(SOURCES$MFVarN)"
			  );
				   &main::Output( "\n\n");
			   $MFVarN++;
		}
		&main::Output(
# rule to translate the preprocessed source
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), "\n",
			"\ttranasm -n -s -o=\$\@ \$(EPOCBLD$Bld)\\$BaseSrc.pre\n",
			"\n",
# rule to preprocess the source
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\$(CC$Bld) \$(PREPROCESSOR_OPTION) $preinclude $LangOptions ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR)) $ChopSrcPath\\$Src \$(OUTPUT_OPTION) \$\@ \n",
# generate an assembly listing target too
			"LISTING$Bld$BaseSrc\_ : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), "\n",
			"\t", &Generic_CopyAction("$SrcPath$BaseSrc\_.$LstExt.lst"),
			"\n",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), " : ",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
			"\t\$(CC$Bld) $LangOptions ", "\$(ASSEMBLER_LISTING_OPTION) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR)) \$(OUTPUT_OPTION) \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp\n",
			"\n"
			);
	} else {

		if ($CompilationGroups{$KeyFile}) {
#                      compile the source
			   &main::Output( "OBJECTS$MFVarN = ");
			   foreach my $obj (@{$CompilationGroups{$KeyFile}{Objects}}) {
				   &main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$obj"), " ");
			   }
				   &main::Output( "\n\n");
			   &main::Output( "SOURCES$MFVarN = ");
			   foreach my $src (@{$CompilationGroups{$KeyFile}{Sources}}) {
				   &main::Output( &Generic_Quote("\\\n\t$src"), " ");
			   }
				   &main::Output( "\n\n");
			   &main::Output( "\$(OBJECTS$MFVarN) : \$(SOURCES$MFVarN) \n");

			   &main::Output(
					 "\t\@echo Compiling \$(SOURCES$MFVarN)\n",
					 "\t\$(CC$Bld) ", "\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR)) $lfboption\\\n",
					 "\t\t$LangOptions \$(OUTPUT_OPTION) \$\@ --multifile \$(SOURCES$MFVarN)"
			  );
				   &main::Output( "\n\n");
			   $MFVarN++;
		}
#		generate an assembly listing target too
		&main::Output(
			"LISTING$Bld$BaseSrc : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), "\n",
			"\t", &Generic_CopyAction("$SrcPath$BaseSrc.$LstExt.lst"),
			"\n",
			&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " : ",
			&Generic_Quote("$SrcPath$Src"), "\n",
			"\t\$(CC$Bld) $LangOptions ","\$(ASSEMBLER_LISTING_OPTION) ","\$(INCLUDE_OPTION)"," \$(call absolutePaths,$ChopSrcPath \$(INCDIR)) \$(OUTPUT_OPTION) \$\@ $ChopSrcPath\\$Src \n",
			"\n"
			);
	}
}


sub PMEndSrc {

	&main::Output(
		"\n",
		"\n"
	);
}

sub PMEndSrcList {

	# Deal with accumulated MAKEDIRS etc.

	&Generic_End;
# modified start: makefile improvement 
	&checkVMAPFiles;
# modified end: makefile improvement 
}

sub ImportLibraryList {
	my $dso;
	my $base;
	my @ImportLibList;
	foreach $dso (@_) {
		$base = &main::Path_Split('Base', $dso);
		$dso = $base.".dso";
		push @ImportLibList, $dso;
	}
	return @ImportLibList;
}

sub ChangeSlash($) {
	my $abspath = $_[0];
	$abspath =~ s/\\/\//g ;
	return $abspath;
}

# System libraries such as the standard C++ libraries or floating point libraries or any other
# static libraries are made into DLLs by linking its export table against them. Such DLLs that are
# created from a static library is known as a Custom DLL. The ARM libraries can be supplied using
# the ARMLIBS mmp keyword  A DLL is considered to be a customdll based on the presence of ARMLIBS
# keyword and also the presence of DEFFILE keyword.

sub IsCustomDllUseCase()
{
	# To check if ARMLIBS keyword is passed in the MMP file.
	# Armutl_ArmLibList() gets the list of static arm libraries, if used by an executable.
	my $armliblist = &Armutl_ArmLibList;

	# To check if DEFFILE keyword is used in the MMP file to supply the def file.
	my $deffile = &main::DefFile;

	if ($armliblist && $deffile)
	{
		return 1;
	}
	return 0;
	
}

sub GetToolChainPreInclude {
	my $preinclude_file = getConfigVariable('PREINCLUDE_OPTION');

	$preinclude_file =~ s/\\/\//g;
	return "$preinclude_file";
}

sub SelectLangOptions {
	my ($Ext) = @_;
	$preinclude = &GetToolChainPreInclude;
	if ($Ext=~/^.cpp$/ || ($Ext=~/^.cia$/ && ($PlatName eq "GCCE"))) {
		#Function Call Logger
		return " \$(CPP_LANG_OPTION) " if ($Function_Call_Logger);
		return " \$(CPP_LANG_OPTION) $preinclude ";
	}
	if ($Ext=~/^.cia$/) {
		return " \$(CIA_LANG_OPTION) ";
	}
	if ($Ext=~/^.c$/) {
		my $CompilerOption = &main::CompilerOption("ARMCC");
		if($CompilerOption =~ /--cpp/){
			#Function Call Logger
			return " \$(CPP_LANG_OPTION) " if ($Function_Call_Logger);
			return " \$(CPP_LANG_OPTION) $preinclude ";
		}
		else {
			#Function Call Logger
			return " \$(C_LANG_OPTION) " if ($Function_Call_Logger);
			return " \$(C_LANG_OPTION) $preinclude ";
		}
	}
	# To support .cc, .cxx, .c++ file extensions for Open Environment
	elsif ($Ext=~/^(.cc|.cxx|.c\+\+)$/) {
		#Function Call Logger
		return " \$(CPP_LANG_OPTION) " if ($Function_Call_Logger);
		return " \$(CPP_LANG_OPTION) $preinclude ";
	}
	return '';
}

sub IsMapOptAvail() {
	open PIPE, "arm-none-symbianelf-g++ -v 2>&1 | ";
	while(<PIPE>){

		if($_ =~ /gcc version (.*) \(release\).*/i)
		{
			if($1 lt "3.4.3")
			{
				return 0;
			}
			elsif($_ =~ /gcc version (.*) \(release\) \(CodeSourcery ARM (.*) (\d*)\)/i)
			{
				if($1 eq "3.4.3" && uc $2 ne "Q1B" && $3 ge 2005)
				{
					return 1;
				}
				elsif($1 gt "3.4.3")
				{
					return 1;
				}
				else
				{
					return 0;
				}
			}

		}

	}
	close PIPE;
}

sub StdCppTarget() {
    
    # STDCPP is supported
    return 0 if (! main::StdCppSupport());
    
  	if ( main::NoStdCpp() ) { #MMP keyword NOSTDCPP set
  	       return 0;
  	}	       
	
	if ( main::StdCpp() ) { # MMP keyword STDCPP set.
		return 1;
	}
	else {
		return ( main::TrgType() =~ /^(STDEXE|STDDLL|STDLIB)$/io );
	}
}

sub GetRTLibList() {

	my $newlib = main::NewLib(); # Could have been set in the MMP file.

	unless ($newlib) {
		if ( StdCppTarget() ) {
			$newlib = getConfigVariable('OE_NEW_LIB');
		}
		else {
			$newlib = getConfigVariable('SYM_NEW_LIB');
		}
	}

	my @RtLib;
	my $list = "$newlib " . getConfigVariable('RUNTIME_LIBS_LIST') ;
	if (length($list) >0)
	{
		@RtLib = split(/\s+/, $list);
	}
	return @RtLib;
}

sub GetOELibList() {
	my @OELib;
	my $list;
	if (&main::IsWideCharMain()) {
		$list = getConfigVariable('OE_EXE_LIBS_WCHAR');
	}
	else {
		$list = getConfigVariable('OE_EXE_LIBS');
	}

	if (length($list) >0)
	{
		@OELib = split(/\s+/, $list);
	}
	return @OELib;
}

sub GetOEImportLibList() {
	my @OEImportLib;
	my $list;
	$list = getConfigVariable('OE_IMPORT_LIBS');
	
	if (length($list) >0)
	{
		@OEImportLib = split(/\s+/, $list);
	}
	return @OEImportLib;
}

sub InitToolChain(@) {

	if($PlatName eq "ARMV5" || $PlatName eq "ARMV5_ABIV2" || $CustomizedARMV5Plat)
	{
		my $RVCTBuildNumber;

		($RVCTMajorVersion, $RVCTMinorVersion, $RVCTBuildNumber) = RVCT_plat2set::get_version_list($PlatName);

		$RVCTVersion = "${RVCTMajorVersion}_${RVCTMinorVersion}";

		my $aRVCTVersion = "${RVCTMajorVersion}.${RVCTMinorVersion}";
		if (($aRVCTVersion == 2.2) && ($RVCTBuildNumber < 559))
		{
			warn "WARNING: When building using ABIV2 mode toolchain Compiler RVCT2.2 Build 559 or later is required.\n";
		}
		&Armutl_DoMmp(@_);
	}
	elsif ($RootName eq "GCCE")
	{
		($GCCEMajorVersion, $GCCEMinorVersion) = gcce_plat2set::get_version_list($Platname);

		$GCCEVersion = "${GCCEMajorVersion}_${GCCEMinorVersion}";
	}

}

my %BSF_keywords = (
			COMMON_OPTIONS => 1,
			THUMB_OPTIONS => 1,
			ARM_OPTIONS => 1,
			KERNEL_OPTIONS => 1,
			INVARIANT_OPTIONS => 1,
			LD_OPTIONS => 1,
			AR_OPTIONS => 1,
			DEBUG_FORMAT => 1
		   );


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;
		}
		if ($key =~ /DEBUG_FORMAT/) {
				push @debugFormat, $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=();
	foreach my $val (@{$Options})
	{		
		# Check if the value of BSF option is to be set or added/removed.
		if($val =~ /\+\[.*\]\+|\-\[.*\]\-/)
		{
			if (@Fragments = 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/=/%/;
					&main::Output(
						"$OptionName := \$($OptionName:$Opt=)",					
						"\n"
					);
				}					
				@Fragments=();
			}
			if (@Fragments = Split_BSF_Options($val,'AddOptions')) 
			{
				&main::Output(
					"$OptionName += @Fragments ",
					"\n"
				);
				@Fragments=();
			}
			
			# Warn if options are not present in the form '+[...]+' or '-[...]-'
			$val =~ s/\+\[.*?\]\+|\-\[.*?\]\-//g;
			if($val !~ /^\s*$/)
			{
				print "Warning: Ignoring option(s) \"$val\" for $OptionName as option(s) should be in the form '+[...]+' or '-[...]-.\n";
			}
		}
		else
		{
			&main::Output(
				"$OptionName = $val ",
				"\n"
			);
		}		
	}
	&main::Output(					
		"\n"
	);
}

# Split BSF options to find options which are to be added/removed
# @param String      - List of options present in form '+[...]+' or '-[....]-'
# @param $Task       - Variable to decide whether to return options to be addded or options to be removed
sub Split_BSF_Options($$)
{
	my ($String,$Task) = @_;
    my @Result = ();
	my @Fragments = ();
	my $Pattern = '';
	# Get the toolchain specific option prefix to segregate the options.
	my $OptionPrefix = getConfigVariable('OPTION_PREFIX');
	
	if ($Task eq 'AddOptions')
	{
		# Get the options which are to be added (present in the form '+[...]+')
		@Fragments = $String =~ /\+\[(.*?)\]\+/g;	
	}
	elsif ($Task eq 'RemoveOptions') 
	{
		# Get the options which are to be removed (present in the form '-[...]-')
		@Fragments = $String =~ /\-\[(.*?)\]\-/g;
	}	

	# Set the value of '$Pattern' which is required to segregate one option from another based on the option prefix.
	if($OptionPrefix) 
	{
		$Pattern = $OptionPrefix.'\S+\s*(?!'.$OptionPrefix.')\S*';
	}
	else 
	{
		# If option prefix is not set in the configuration make file, then set default
		# option prefix as '-' or '--'.
		$Pattern = '-{1,2}\S+\s*(?!-)\S*';
	}

	foreach my $Val (@Fragments) 
	{
		my @Opt = $Val =~ /$Pattern/g;
		push @Result,@Opt;				
	}
	return @Result;	
}

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 GetLibList() {
	my @LibList;
	my @StaticLibList;
	my $list = getConfigVariable('STATIC_LIBS_LIST') ;

	if (length($list) >0)
	{
		@StaticLibList = split(/\s+/, $list);
	}
	if($PlatName eq "ARMV5" || $PlatName eq "ARMV5_ABIV2" || $CustomizedARMV5Plat) {
		@LibList=&Armutl_ArmLibList;
		if(@LibList==0) {
			my $LibDir = Armutl_ArmLibDir();
			# convert '/' to  '\'  if there are some '/'
			$LibDir =~ s#/#\\#g;
			if (@StaticLibList) {
				foreach my $lib (@StaticLibList) {
					push @LibList, ("$LibDir\\$lib");
				}
			}
		}
	}
	else
	{
		@LibList = ('$(STATIC_LIBS_LIST)');
	}
	return @LibList;
}

sub GetToolChainAsmFileList() {
	my @FileList;
	@FileList=&Armutl_AsmFileList;
	if(@FileList)
	{
		return @FileList;
	}
	return;
}

sub IsTargetRT() {
	my $RTtarget=&Armutl_ArmRT;
	if($RTtarget)
	{
		return $RTtarget;
	}
	return;
}

sub GetToolChainIncDir {
	if($PlatName eq "ARMV5" || $PlatName eq "ARMV5_ABIV2" || $CustomizedARMV5Plat)
	{
  		#the ToolChainIncDir's value depends on the key word ARMINC in mmp file
  		return &Armutl_ArmIncDir;
	}
	else
	{
		my $compiler_inc_path = getConfigVariable('COMPILER_INCLUDE_PATH');
		$compiler_inc_path =~ s/^\s+//g;
		return ($compiler_inc_path);
	}
}

my $useLinkerFeedBack = 0;

sub LinkerFeedBackFile() {
  return unless $useLinkerFeedBack;
  my $Trg = &main::Trg;
  return "$Trg.lfb";
}

sub LinkerFeedBackOption() {
	return "" unless $useLinkerFeedBack;
	my $BasicTrgType=&main::BasicTrgType;
	return "" unless ($BasicTrgType=~/^(DLL|EXE)/o);
	my $file = LinkerFeedBackFile();
	return "/$(FEEDBACK_FILE_OPTION) $file ";

}

sub getConfigVariable
{
    my ($variable) = @_;
    initialiseConfigVariables();
    return $configVariables{$variable};
}

sub initialiseConfigVariables()
{
    if (!keys(%configVariables))
    {
		%configVariables = BPABIutl_Get_Config_Variables($PlatName);

		if (!keys(%configVariables))
		{
			# no variables were extracted from configuration file.
			&main::FatalError("Cannot extract configuration variables for $PlatName");
		}
    }
}

sub PMSupportsFeatureVariants
{
	return 1;
}
# modified start: makefile improvement 
sub checkVMAPFiles
{
	my %srcSet = %{&main::getSrcSet};
	my %featureVariantInfo = &main::FeatureVariantInfo();
	my $vmapfile = &main::Trg.".".$featureVariantInfo{NAME}.".vmap";
	my $mmpFile = &main::MmpFile;
	if ( $vmapfile ){
		&main::Output(
			"\n",
			"\n",
			"# Rules to check out the VMAP files",
			"\n",
			"\n",
		);
		&main::Output(
			"CHECKVMAPUREL : ",
			"\$(EPOCTRG)\\urel\\",
			$vmapfile,
			" \n",
			"\$(EPOCTRG)\\urel\\",
			$vmapfile,
			" : \\\n",
			"\t",
			$mmpFile,
		);
		foreach my $srcfile (sort keys(%srcSet))
		{
			&main::Output(
				" \\\n \t",
				$srcfile,
			);
		}
		&main::Output(
			"\n",
			"\t-\$(ERASE) \$(EPOCTRG)\\urel\\",
			$vmapfile,
			"\n",
			"\n",
		);
		&main::Output(
			"CHECKVMAPUDEB : ",
			"\$(EPOCTRG)\\udeb\\",
			$vmapfile,
			" \n",
			"\$(EPOCTRG)\\udeb\\",
			$vmapfile,
			" : \\\n",
			"\t",
			$mmpFile,
		);
		foreach my $srcfile (sort keys(%srcSet))
		{
			&main::Output(
				" \\\n \t",
				$srcfile,
			);
		}
		&main::Output(
			"\n",
			"\t-\$(ERASE) \$(EPOCTRG)\\udeb\\",
			$vmapfile,
			"\n",
			"\n",
		);
	}
}
# modified by SV end: makefile improvement 
# modified end: makefile improvement 


1;