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