diff -r fa9d7d89d3d6 -r 68f68128601f sbsv1/abld/platform/ide_cw.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbsv1/abld/platform/ide_cw.pm Thu Nov 25 13:59:07 2010 +0000 @@ -0,0 +1,4517 @@ +# 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 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 ', + '#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 = " \n"; + } + $ResourcesText .= $entry . " \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 = " \n"; + push @ResourceDownloadList, "$path\\$trgfile"; + foreach my $BitmapRef (@{$$AifRef{BitMaps}}) { + $entry .= " \n"; + } + $ResourcesText .= $entry . " \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 block is now created for each START RESOURCE blocks LANG entries. This + # shouldn't be necessary as blocks support multiple 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 "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 = " = 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 .= " \n"; + push @resourcefiles, $entry; + push @ResourceDownloadList, $resourcetargets{$fullsource}.".R".$$ResourceRef{Lang}; + } + + foreach my $resourceEntry (@resourcefiles) { + $ResourcesText .= $resourceEntry . " \n"; + } + + # --- If required, generate .resources file per platform + + if ($ResourcesText ne "") + { + my $resourcesfile = "$BaseTrg$Plat.resources"; + &main::CreateExtraFile("${ExtraFilesPath}$resourcesfile", "\n$ResourcesText\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 -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 () + { + #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(){ + $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() + { + 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;