Update release information and product version.
# Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
# Makmake-module for creating XML files which can be imported as CodeWarrior IDE projects
#
#
package Ide_cw;
my $CW_minimum_supported_version = 2.8;
# declare variables global for module
my $BaseAddress="";
my %IdeBlds=();
my %PrjHdrs=();
my @Win32LibList=();
my $Win32Resrc;
my $Win32StdHeaders;
my $ExtraFilesPath="";
my @KnownRoots=();
my @addedFiles=();
my $addHeaders = 1;
my $addDocuments = 1;
my %processedPlatforms;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(
PMHelp_Mmp
PMCheckPlatformL
PMPlatProcessMmp
PMStartBldList
PMBld
PMResrcBld
PMEndSrcList
);
require Cl_bpabi;
use BPABIutl;
use E32Variant;
use E32Plat;
use Winutl;
use Armutl;
use Pathutl;
use Win32API::Registry qw( :ALL );
use Preprocessor;
use RVCT_plat2set;
sub PMHelp_Mmp {
&Winutl_Help_Mmp;
}
my $RVCTMajorVersion = Armutl_RVCTMajorVersion();
my $RVCTMinorVersion = Armutl_RVCTMinorVersion();
my $RVCTVersion = "${RVCTMajorVersion}_${RVCTMinorVersion}";
my $oP = "--";
$oP = "-" if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2);
my $cfgMacro = &Variant_GetMacro();
use FindBin;
use lib $FindBin::Bin."\\perllib";
#use the DOM xml module
use XML::DOM;
my $projectTemplate;
my $linkDescriptorTemplate;
my $xmlParser;
my $xmlProjectDoc;
my $xmlLinkDescriptorDoc;
my $xmlLinkDescriptorCommandParent;
my $xmlLinkDescriptorSymbolParent;
my $xmlLinkDescriptorDumpFileParent;
my $xmlLinkOrder; # for accumulating the link order
my $xmlFileList; # for accumulating the file list
my $xmlSourceGroup; # for accumulating the source
my $xmlHeadersGroup; # for accumulating local header files
my $xmlRootGroup; # for accumulating files to be added outside of project groups
my $xmlLinkGroup; # for accumulating the link descriptor files
my $xmlLibGroup; # for accumulating the libraries
my $xmlResourcesGroup; # for accumulating resource related files
my $xmlDocumentsGroup; # for accumulating supported files specified with DOCUMENT in the .mmp file
my $MmpFile;
my $VariantFile;
my $PrefixFile;
my $CW_major_version;
my $CW_minor_version;
my $CW_libpath;
my @CW_librarypath;
my @ToolChainLibList;
# Hash to store configuration makefile data for furthur processing
my %configdata;
sub RoundUp1k($) {
# Accept C hexadecimal number (0xNNN). Convert argument to Kb
# rounded up to the next 1kb boundary.
use integer;
return (hex($_[0]) + 1023) / 1024;
}
use Genutl;
use cl_generic;
my $ToolPrefix='';
my $HelperLib='';
my %PlatOpt=(
'Dlltool'=>'',
'Entry'=>'-e',
'Gcc'=>'',
'Ld'=>'',
'Petran'=>'',
'Optimize'=>'-O'
);
my $Dlltool;
my $Archive;
my $Link;
my $Objcopy;
my %CompatibleABIs=(
ARMI=>['ARM4', 'THUMB'],
ARM4=>['ARMI'],
THUMB=>['ARMI'],
ARMV5=>['ARMV5_ABIV1'],
GCCE=>['GCCE'],
BPABI=>['ARMV5_ABIV2']
);
my @CompatibleABIs;
my $Makecmd;
my %ABILibPath=();
sub SystemTarget() {
return 1 if &main::SystemTrg;
my $ExportLibrary=&main::ExportLibrary;
# N.B. should get better way to detect kernel probably!!
return 1 if ($ExportLibrary =~ /EKERN/i);
return 0;
}
sub SysTrg () {
return 1 if &main::SystemTrg;
my $ExportLibrary=&main::ExportLibrary;
return 1 if ($ExportLibrary =~ /EKERN/i);
my $Trg=&main::Trg;
return 1 if ($Trg =~ /KSRT/i);
return 0;
}
sub PMUnderlyingABI($) {
my ($ABI) = @_;
if ($ABI eq 'ARM4T') {
if (&main::BuildAsARM) {
return 'ARMI';
}
elsif (SystemTarget()) {
return 'ARM4';
}
else {
return 'ARMV4';
}
}
return $ABI;
}
##### ARMV5 specific options #####
my $diag_suppressions;
my $diag_warnings;
my $diag_errors;
#The options here are handcoded for ABIV1 mode.
my $contingentOptions;
my $exceptions = ' --exceptions --exceptions_unwind';
my $thumbOptions = '--thumb ';
my $armOptions = '--arm ';
my $kernelOptions = '--arm --no_exceptions --no_exceptions_unwind';
my $invariantOptions =
'--cpu 5T --enum_is_int -Ono_known_library --fpmode ieee_no_fenv --export_all_vtbl --no_vfe --apcs /inter';
$invariantOptions .= ' --dllimport_runtime' unless ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2);
# specify floating point model here
my $floatingpointmodel = "softvfp";
if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i)) {
$floatingpointmodel = "vfpv2";
}
my $floatingpoint = ' --fpu '.$floatingpointmodel.'';
# Set compiler settings
$diag_suppressions = '--diag_suppress 66,161,611,654,997,1152,1300,1464,1488,6318,6331';
$diag_warnings = '';
$diag_errors = '--diag_error 1267';
my $commonOptions = "$diag_suppressions $diag_warnings $diag_errors";
# variables added to fetch the options from the BSF files
my @commonOptions;
my @thumbOptions;
my @armOptions;
my @kernelOptions;
my @invariantOptions;
my @linkerOptions;
my @archiverOptions;
my $linkCommand = "";
# variables to process and store the default and BSF file options
my $invopts = $invariantOptions;
my $linkeropts;
my $archiveropts;
#varible to store the BSF add options
my $bsfaddoptions = undef;
#variable to store the compiler flags, defs and other options
my $CCFLAGS = undef;
my $CCDEFS = undef;
my $CCUREL = undef;
my $CCUDEB = undef;
#GCCE specific OPIONS
my $GCCE_CompilerOption = '-march=armv5t -mthumb-interwork -mapcs';
$GCCE_CompilerOption .= " -msoft-float -fexceptions -pipe -nostdinc -Wall -Wno-ctor-dtor-privacy -Wno-unknown-pragmas";
#Flag to check for the customized GCCE platform
my $CustGCCE=0;
#Variable to fetch the Customized platform
my %CustPlat=&main::PlatRec;
#Flags to read the options
my $kernelOption=0;
my $buildAsArmOption=0;
my $thumbOption=0;
my $ArmIncDir;
my @ArmLibList;
my $ArmRT;
my %BSF_keywords = (
COMMON_OPTIONS => 1,
THUMB_OPTIONS => 1,
ARM_OPTIONS => 1,
KERNEL_OPTIONS => 1,
INVARIANT_OPTIONS => 1,
LD_OPTIONS => 1,
AR_OPTIONS => 1
);
sub PMStartBldList($)
{
($Makecmd) = @_;
my @BldList=&main::BldList;
my $BasicTrgType=&main::BasicTrgType;
my $ABI=&main::ABI;
my $kernelOption=0;
my $buildAsArmOption=0;
my $thumbOption=0;
my @MacroList=&main::MacroList();
push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__ ";
my %plat = &main::PlatRec();
$CCFLAGS = "";
$CCDEFS = "";
$CCUREL = "";
$CCUDEB = "";
$VariantFile=&main::VariantFile();
#read the configuration make file into the hash for only the BPABI platforms
my $config_file = BPABIutl_Config_Path(&main::Plat);
if ($config_file) {
collect_config_data($config_file);
}
Read_BSF_Options() if ($plat{'CUSTOMIZES'});
if (SysTrg()) {
$kernelOption=1;
} elsif (main::BuildAsARM() or ($ABI eq 'ARMV4')) {
$buildAsArmOption=1;
} else {
$thumbOption=1;
}
my $OtherOpts = undef;
my $toolchain = $configdata{COMPILER_PLAT};
$OtherOpts = &main::CompilerOption($toolchain);
if($kernelOption==1)
{
if(@kernelOptions) {
# Kernel options as read from BSF file (KERNEL_OPTIONS keyword)
Set_BSF_Options('KERNEL_OPTIONS',\@kernelOptions);
}
$OtherOpts .= " ".fetch_config_data($configdata{KERNEL_OPTIONS});
}
elsif($buildAsArmOption==1)
{
if(@armOptions) {
# Arm options as read from BSF file (ARM_OPTIONS keyword)
Set_BSF_Options('ARM_OPTIONS',\@armOptions);
}
$OtherOpts .= " ".fetch_config_data($configdata{ARM_OPTIONS});
}
elsif($thumbOption==1)
{
if(@thumbOptions) {
# Thumb options as read from BSF file (THUMB_OPTIONS keyword)
Set_BSF_Options('THUMB_OPTIONS',\@thumbOptions);
}
$OtherOpts .= " ".fetch_config_data($configdata{THUMB_OPTIONS});
}
if($thumbOption==1 || $buildAsArmOption==1)
{
if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i))
{
$OtherOpts .= " ".$configdata{VFP2MODE_OPTION};
}
else
{
$OtherOpts .= " ".$configdata{SOFTVFPMODE_OPTION};
}
}
if ($thumbOption==1)
{
$OtherOpts .= " ".$configdata{COMPILER_THUMB_DEFINES};
}
$OtherOpts .= " ".$configdata{COMPILER_INTERWORK_DEFINES};
if((&main::Plat eq "ARMV5_ABIV1") || (&main::Plat eq "ARMV5" && !$cfgMacro)
|| ($CustPlat{'CUSTOMIZES'}
&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV1" && $cfgMacro)
|| ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && !$cfgMacro)))) {
ComputeCompilerOpts();
}
elsif($config_file) {
$CCFLAGS = &Cl_bpabi::getConfigVariable('CCFLAGS');
}
$CCFLAGS .= $OtherOpts;
if(@invariantOptions)
{
# Invariant options as read from BSF file (INVARIANT_OPTIONS keyword)
Set_BSF_Options('INVARIANT_OPTIONS',\@invariantOptions);
}
if(@commonOptions)
{
# Common options as read from BSF file (COMMON_OPTIONS keyword)
Set_BSF_Options('COMMON_OPTIONS',\@commonOptions);
}
if(@linkerOptions)
{
# Invariant options as read from BSF file (LD_OPTIONS keyword)
Set_BSF_Options('LD_OPTIONS',\@linkerOptions);
}
if ($BasicTrgType=~/^LIB$/o) {
if(@archiverOptions)
{
# Invariant options as read from BSF file (AR_OPTIONS keyword)
Set_BSF_Options('AR_OPTIONS',\@archiverOptions);
}
}
if($bsfaddoptions)
{
fixbsfoptions($bsfaddoptions);
}
$CCFLAGS .= $bsfaddoptions;
$CCDEFS = $configdata{COMPILER_DEFINES};
$CCDEFS .= printlist("-D", @MacroList);
$CCDEFS .= $configdata{PLATFORM_DEFINES};
if($kernelOption==1)
{
$CCDEFS .= -D__KERNEL_MODE__;
}
if($VariantFile) {
$CCDEFS .= " -D__PRODUCT_INCLUDE__="."\\\"".&main::Path_Split('File',$VariantFile)."\\\"";
}
foreach (@BldList)
{
if($kernelOption == 0)
{
if (/DEB$/o) {
$CCUDEB .= " ".$configdata{EXCEPTIONS};
}
else {
$CCUREL .= " ".$configdata{EXCEPTIONS};
}
}
#collect the options and macro's depending on the whether it is a UREL or UDEB
my @ml = &main::MacroList($_);
if (/DEB$/o) {
$CCUDEB .= " ".$CCFLAGS;
$CCUDEB .= printlist("-D", @ml);
$CCUDEB .= " ".$CCDEFS;
}
else {
$CCUREL .= " ".$CCFLAGS;
$CCUREL .= printlist("-D", @ml);
$CCUREL .= " ".$CCDEFS;
}
}
}
sub ComputeCompilerOpts() {
my %plat = &main::PlatRec();
my $ABI=&main::ABI;
my $TrgType=&main::TrgType;
if (SysTrg()) {
$contingentOptions = $kernelOptions;
} elsif (main::BuildAsARM() or ($ABI eq 'ARMV4')) {
$contingentOptions = $armOptions.$floatingpoint.$exceptions;
} else {
$contingentOptions = $thumbOptions.$floatingpoint.$exceptions.' -D__MARM_THUMB__';
}
# change support for ARMV4
if ($ABI eq 'ARMV4') {
$invopts =~ s/5T/4/;
$invopts =~ s/inter/nointer/;
} else {
$contingentOptions .= ' -D__MARM_INTERWORK__';
}
$CCFLAGS = $commonOptions.' '.$contingentOptions.' '.$invopts.' -c '.' '.&main::CompilerOption("ARMCC");
}
sub GetMajorVersion ($)
{
my ($versionString) = @_;
if ($versionString =~ /^\d\.\d\.\d$/)
{
$versionString =~ s/\.\d$//;
}
return $versionString;
}
sub GetMinorVersion ($)
{
my ($versionString) = @_;
if ($versionString =~ /^\d\.\d\.\d$/)
{
$versionString =~ s/^\d\.\d\.//;
}
else
{
$versionString = 0;
}
return $versionString;
}
sub PMCheckPlatformL {
# check version of CodeWarrior for Symbian OS
my @compatibleCWInstallations;
$CW_major_version = 0;
$CW_minor_version = 0;
my $minimumMajorVersion = GetMajorVersion ($CW_minimum_supported_version);
my $minimumMinorVersion = GetMinorVersion ($CW_minimum_supported_version);
if (defined $ENV{CW_SYMBIAN_VERSION})
{
# CW_SYMBIAN_VERSION is set - either MAKMAKE is being executed by an IDE's .mmp Importer,
# or the user is specifying a specific CW version to target from the command line.
# Either way, we've been given a single version to target, so we attempt to do just that.
$CW_major_version = GetMajorVersion ($ENV{CW_SYMBIAN_VERSION});
$CW_minor_version = GetMinorVersion ($ENV{CW_SYMBIAN_VERSION});
push @compatibleCWInstallations, $ENV{CW_SYMBIAN_VERSION};
}
else
{
# CW_SYMBIAN_VERSION isn't set - either MAKMAKE is being executed by a pre-OEM3.0 IDE .mmp
# Importer or from the command line. Either way, we delve into the registry and attempt to
# target the latest CW for Symbian OS installed, recording all CW for Symbian OS installations
# too.
my $regKeyHandle;
my $topLevelKey = HKEY_LOCAL_MACHINE;
my $productVersionKey = 'SOFTWARE\\Metrowerks\\CodeWarrior\\Product Versions';
if (!RegOpenKeyEx($topLevelKey, $productVersionKey, 0, KEY_READ, $regKeyHandle))
{
die "Can't read \"HKEY_LOCAL_MACHINE\\$productVersionKey\" : ", regLastError(), "\n";
}
my $subKeyIndex = 0;
my $subKeySize = 0;
my $subKeyName;
my @installedCWForSymbianKeys;
while (RegEnumKeyEx($regKeyHandle, $subKeyIndex, $subKeyName, $subKeySize, [], [], [], []))
{
push (@installedCWForSymbianKeys, $productVersionKey."\\".$subKeyName) unless ($subKeyName !~ /Symbian/);
$subKeyIndex++;
}
RegCloseKey($regKeyHandle) || print STDERR "WARNING: Could not close registry key.";
my $versionType;
my $versionValue;
foreach my $installedCWForSymbianKey (@installedCWForSymbianKeys)
{
if (!RegOpenKeyEx($topLevelKey, $installedCWForSymbianKey, 0, KEY_READ, $regKeyHandle))
{
die "Can't read \"HKEY_LOCAL_MACHINE\\$installedCWForSymbianKey\" : ", regLastError(), "\n";
}
if (!RegQueryValueEx($regKeyHandle, "VERSION", [], $versionType, $versionValue, []))
{
die "Can't read \"HKEY_LOCAL_MACHINE\\$installedCWForSymbianKey\\VERSION\" : ", regLastError(), "\n";
}
my $temp_major_version = GetMajorVersion ($versionValue);
my $temp_minor_version = GetMinorVersion ($versionValue);
if (($temp_major_version > $CW_major_version) ||
(($temp_minor_version > $CW_minor_version) &&
($temp_major_version >= $CW_major_version)))
{
$CW_major_version = $temp_major_version;
$CW_minor_version = $temp_minor_version;
}
if (($temp_major_version > $minimumMajorVersion) ||
(($temp_minor_version > $minimumMinorVersion) &&
($temp_major_version >= $minimumMajorVersion)))
{
push @compatibleCWInstallations, $versionValue;
}
RegCloseKey($regKeyHandle);
}
}
# We've determined a CW version to target, now we validate if we actually support this
if (!$CW_major_version ||
($CW_major_version < $minimumMajorVersion) ||
(($CW_major_version >= $minimumMajorVersion) && ($CW_minor_version < $minimumMinorVersion)))
{
if (defined $ENV{CW_SYMBIAN_VERSION})
{
die "Error: CW_SYMBIAN_VERSION is set to $ENV{CW_SYMBIAN_VERSION}.\n The minimum version supported by these tools is $CW_minimum_supported_version.\n";
}
else
{
die "ERROR: Unable to identify a compatible CodeWarrior for Symbian OS installation.\n";
}
}
if (@compatibleCWInstallations > 1)
{
my $targetVersion = $CW_major_version;
$targetVersion .= ".$CW_minor_version" if $CW_minor_version;
print ("Info: More than one compatible CodeWarrior for Symbian OS installation has been detected.\n");
print (" The generated project will target $targetVersion - to override this, set the CW_SYMBIAN_VERSION\n");
print (" environment variable to the version number you wish to target and re-run this command.\n");
print (" Supported version numbers detected : @compatibleCWInstallations.\n");
}
else
{
print ("Info: Detected CodeWarrior Version Major=$CW_major_version Minor=$CW_minor_version\n");
}
# CW version has been validated, tailor generated projects on this basis
$CW_libpath = 'Symbian_Support\Win32-x86 Support\Libraries\Win32 SDK';
push @CW_librarypath,$CW_libpath;
# Lib path to support the Carbide runtime libraries
$CW_libpath = 'Symbian_Support\Runtime\Runtime_x86\Runtime_Win32\Libs';
push @CW_librarypath,$CW_libpath;
if ($CW_major_version == 2.8)
{
$projectTemplate = "CW_project_template_v3.xml";
$linkDescriptorTemplate = "cw_link_descriptor_template.cwlink";
}
else
{
$projectTemplate = "CW_project_template_v4.xml";
$linkDescriptorTemplate = "cw_link_descriptor_template_v2.cwlink";
}
$xmlParser = new XML::DOM::Parser;
$xmlProjectDoc = $xmlParser->parsefile ($FindBin::Bin."\\$projectTemplate");
}
# Check if a platform is a customization
sub IsCustomization($) {
my ($plat) = @_;
return 1 if (Plat_Customizes($plat));
return 0;
}
sub PMPlatProcessMmp (@) {
my $currentPlat=&main::Plat;
return if ($processedPlatforms{$currentPlat});
$processedPlatforms{$currentPlat}=1;
@ToolChainLibList = &GetLibList;
my $TrgType=&main::TrgType;
if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
{
$CustGCCE=1;
}
if ($currentPlat =~ /^WINSCW$/)
{
my $includes = $ENV{MWCWinx86Includes};
&Winutl_DoMmp_Parse(\@_, $includes);
@Win32LibList=&Winutl_Win32LibList;
$Win32Resrc=&Winutl_Win32Resrc;
$Win32StdHeaders=&Winutl_Win32StdHeaders;
$BaseAddress=&Winutl_BaseAddress unless ($TrgType eq 'EXE');
}
elsif ($currentPlat =~ /^ARMV5/ || IsCustomization($currentPlat))
{
&Armutl_DoMmp(@_);
$ArmIncDir = &Armutl_ArmIncDir;
&main::SetStdIncPaths($ArmIncDir);
@ArmLibList = &Armutl_ArmLibList;
$ArmRT = &Armutl_ArmRT;
}
my $BaseTrg=&main::BaseTrg;
my $MakeFilePath=&main::MakeFilePath;
$MmpFile=&main::MmpFile;
$VariantFile=&main::VariantFile();
# Set up the list of known roots
my $epocroot=&main::Path_Drive . &main::EPOCPath;
$epocroot =~ s/EPOC32\\$//i;
if ($currentPlat eq "GCCE" || $CustGCCE)
{
$PrefixFile=$epocroot.'epoc32\\include\\gcce\\gcce.h';
}
else
{
$PrefixFile=$epocroot.'epoc32\\include\\rvct'.$RVCTVersion.'\\rvct'.$RVCTVersion.'.h';
}
my $mmproot = &main::Path_Drive . &main::Path_Split('Path',$MmpFile);
my $mmprootname = "MMPDir";
my $mmpisglobal = 0;
if (defined $ENV{CW_ROOT_NAME})
{
# generate KnownRoots suitable for the IDE MMP importer
# This has a global source tree for EPOCROOT, and puts the
# project next to the MMP file
addKnownRoot($ENV{CW_ROOT_NAME}, 1, $epocroot, "");
$mmprootname = "Project";
$mmpisglobal = 1;
}
else
{
# generate KnownRoots suitable for command-line generated XML files
# We will add a user source tree for MMPDir and EPOCROOT, but can't use
# EPOCROOT for the OutputDirectory
addKnownRoot("EPOCROOT", 0, $epocroot, "");
}
addKnownRoot($mmprootname, $mmpisglobal, $mmproot, "");
# Allow for MMP files in component subdirectories by matching multiple levels
# up to get {MMPDir}..\whatever paths. Stop one level down from the root,
# since "everything on this drive" seems a bit extreme
#
my $tmppath = $mmproot;
my $dotdots = '';
while ($tmppath =~ /^(.:.+\\)[^\\]+\\$/i)
{
$tmppath = $1;
$dotdots .= "..\\";
addKnownRoot($mmprootname, $mmpisglobal, $tmppath, $dotdots);
}
}
sub findTarget($$$) {
my ($name,$platbld,$abibld) = @_;
my @targets = $xmlProjectDoc->getElementsByTagName("TARGET",1);
foreach my $target (@targets)
{
my $element = $target->getElementsByTagName("NAME",0)->item(0);
$element = $element->getFirstChild;
# here we want to get the plat build that is specified in the cw project tempalte
# and not the abi build - there are more platbuilds than abibuilds so other targets
# (e.g. GCCE) can get the wrong tempalte "NAME" (i.e. it will be ARMV5 rather than GCCE, which is not want we want)
if ($element->getData() =~ /$platbld$/)
{
my $newtarget=$target->cloneNode(1);
$target->getParentNode()->appendChild($newtarget);
$element = $newtarget->getElementsByTagName("NAME",0)->item(0);
$element = $element->getFirstChild;
$element->setData("$platbld");
# remember name as an attribute: this is removed before
# writing out the project.
$newtarget->setAttribute("NAME", "$platbld");
return $newtarget;
}
else
{
my $newtarget=$target->cloneNode(1);
my $newplat=&main::Plat." ".&main::Bld;
$target->getParentNode()->appendChild($newtarget);
$element = $newtarget->getElementsByTagName("NAME",0)->item(0);
$element = $element->getFirstChild;
$element->setData("$newplat");
# remember name as an attribute: this is removed before
# writing out the project.
$newtarget->setAttribute("NAME", "$newplat");
return $newtarget;
}
}
return undef;
}
sub newList($$$) {
my ($target, $tag, $replace) = @_;
my $newlist = new XML::DOM::Element($xmlProjectDoc,$tag);
if ($replace==1)
{
my $elements = $target->getElementsByTagName($tag,0);
my $element = $elements->item(0);
$target->replaceChild($newlist, $element);
}
else
{
$target->appendChild($newlist);
}
return $newlist;
}
sub changeValue($$) {
my ($setting, $replacement) = @_;
my $value = $setting->getElementsByTagName("VALUE",0)->item(0);
if (defined $value)
{
if ($value->hasChildNodes)
{
$value->getFirstChild->setData($replacement);
}
else
{
$value->addText($replacement);
}
}
}
sub textSetting($$$$) {
my ($element,$name,$value,$insertionpoint)=@_;
my $setting = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($setting, "NAME", $name);
&textElement($setting, "VALUE", $value);
$element->insertBefore($setting, $insertionpoint);
$element->addText("\n");
}
sub addKnownRoot($$$$) {
my ($rootname, $global, $rootpath, $pathprefix) = @_;
$rootpath=&main::Path_Chop($rootpath);
push @KnownRoots, [$rootname, $global, quotemeta($rootpath), $pathprefix];
}
sub addRootedPath($$$) {
my ($setting,$needglobal,$path) = @_;
my $root = "Absolute";
if ($path =~ /^\\/)
{
$path = &main::Path_Drive . $path; # ensure it has a drive letter
}
foreach (@KnownRoots)
{
my ($rootname, $global, $rootpath, $pathprefix) = @{$_};
next if ($needglobal && !$global);
if ($path =~ /^$rootpath\\/i)
{
$path =~ s/^$rootpath\\/$pathprefix/i;
$root = $rootname;
last;
}
}
$path=&main::Path_Chop($path);
if ($root eq "Absolute" && $path =~ /^(.:)$/)
{
$path .= "\\";
}
&textSetting($setting, "Path", $path);
&textSetting($setting, "PathFormat", "Windows");
&textSetting($setting, "PathRoot", $root);
}
sub changePathSetting($$$) {
my ($setting,$global,$value) = @_;
my @oldstuff = $setting->getElementsByTagName("SETTING",0);
foreach my $old (@oldstuff)
{
&removeNode($old);
}
&addRootedPath($setting,$global,$value);
}
sub addSourceTrees($) {
my ($node) = @_;
my $element = $node->getElementsByTagName("VALUE",0)->item(0);
&removeNode($element) if (defined $element);
if (defined $ENV{CW_ROOT_NAME})
{
return; # paths were converted to be relative to global source trees
}
my $sourcepath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$sourcepath->addText("\n");
&textSetting($sourcepath, "Name", "EPOCROOT");
&textSetting($sourcepath, "Kind", "AbsolutePath");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "Path");
$pathdata->addText("\n");
my $epocroot=&main::EPOCPath;
$epocroot =~ s/\\EPOC32\\$/\\/i;
&addRootedPath($pathdata, 1, $epocroot);
$sourcepath->appendChild($pathdata);
$node->appendChild($sourcepath);
my $mmproot = &main::Path_Split('Path',$MmpFile);
my $sourcepath2 = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$sourcepath2->addText("\n");
&textSetting($sourcepath2, "Name", "MMPDir");
&textSetting($sourcepath2, "Kind", "AbsolutePath");
my $pathdata2 = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata2, "NAME", "Path");
$pathdata2->addText("\n");
&addRootedPath($pathdata2, 1, $mmproot);
$sourcepath2->appendChild($pathdata2);
$node->appendChild($sourcepath2);
}
sub addUserSearchPaths($) {
my ($node) = @_;
my @elements = $node->getElementsByTagName("SETTING",0);
foreach (@elements)
{
&removeNode($_);
}
my %ordereddirs;
my @ordereddirlist=();
foreach my $dir (&main::UserIncPaths)
{
next if (!defined $dir);
$dir = &main::Path_Chop($dir)."\\";
my $key = uc $dir;
if (! defined($ordereddirs{$key}))
{
$ordereddirs{$key}=1;
push @ordereddirlist, $dir;
}
}
# now add the directories used to find source files
my %dirs;
my $SourceStructRef=&main::SourceStructRef;
foreach my $SourceRef (@$SourceStructRef)
{
$dirs{$$SourceRef{SrcPath}}=1;
}
my $DefFile = &main::DefFile;
if ($DefFile)
{
$DefFile = &main::Path_Split('Path',$DefFile);
$dirs{$DefFile}=1;
}
my $MmpFilePath = &main::Path_Split('Path',$MmpFile);
$dirs{$MmpFilePath}=1;
$dirs{$ExtraFilesPath}=1;
foreach my $srcdir (sort keys %dirs)
{
if (!defined($ordereddirs{uc $srcdir}))
{
push @ordereddirlist, $srcdir;
}
}
foreach my $srcdir (@ordereddirlist)
{
my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$accesspath->addText("\n");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "SearchPath");
$pathdata->addText("\n");
&addRootedPath($pathdata, 0, $srcdir);
$accesspath->appendChild($pathdata);
&textSetting($accesspath, "Recursive", "false");
&textSetting($accesspath, "FrameworkPath", "false");
&textSetting($accesspath, "HostFlags", "All");
$node->appendChild($accesspath);
}
}
sub addSystemSearchPaths($) {
my ($node) = @_;
my @elements = $node->getElementsByTagName("SETTING",0);
foreach (@elements)
{
&removeNode($_);
}
my $ASSPLinkPath;
$ASSPLinkPath = &main::ASSPLinkPath if (&main::ASSPLibList);
my @extraIncPaths=();
push @extraIncPaths, $ArmIncDir if $ArmIncDir;
my %ordereddirs;
my @ordereddirlist=();
foreach my $dir (&main::SysIncPaths, @extraIncPaths, &main::StatLinkPath, $ASSPLinkPath, &main::LinkPath)
{
next if (!defined $dir);
$dir = &main::Path_Chop($dir)."\\";
my $key = uc $dir;
if (! defined($ordereddirs{$key}))
{
$ordereddirs{$key}=1;
push @ordereddirlist, $dir;
}
}
my %dirs;
if ($VariantFile)
{
my $VariantFilePath = &main::Path_Split('Path',$VariantFile);
$dirs{$VariantFilePath}=1;
}
if (((&main::Plat =~ /^ARMV5/) || (&main::Plat =~ /^GCCE$/) ||(IsCustomization(&main::Plat))) && $PrefixFile)
{
my $PrefixFilePath = &main::Path_Split('Path',$PrefixFile);
$dirs{$PrefixFilePath}=1;
}
foreach my $srcdir (sort keys %dirs)
{
if (!defined($ordereddirs{uc $srcdir}))
{
push @ordereddirlist, $srcdir;
}
}
foreach my $srcdir (@ordereddirlist)
{
my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$accesspath->addText("\n");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "SearchPath");
$pathdata->addText("\n");
&addRootedPath($pathdata, 0, $srcdir);
$accesspath->appendChild($pathdata);
&textSetting($accesspath, "Recursive", "false");
&textSetting($accesspath, "FrameworkPath", "false");
&textSetting($accesspath, "HostFlags", "All");
$node->appendChild($accesspath);
}
if (&main::Plat =~ /^WINSCW$/)
{
my $lpath;
foreach $lpath (@CW_librarypath)
{
# only add Win32 SDK for WINSCW system access paths
my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$accesspath->addText("\n");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "SearchPath");
$pathdata->addText("\n");
&textSetting($pathdata, "Path", $lpath);
&textSetting($pathdata, "PathFormat", "Windows");
&textSetting($pathdata, "PathRoot", "CodeWarrior");
$accesspath->appendChild($pathdata);
&textSetting($accesspath, "Recursive", "false");
&textSetting($accesspath, "FrameworkPath", "false");
&textSetting($accesspath, "HostFlags", "All");
$node->appendChild($accesspath);
}
}
if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
{
$CustGCCE=1;
}
if (&main::Plat =~ /^GCCE$/ || $CustGCCE)
{
my $accesspath = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$accesspath->addText("\n");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "SearchPath");
$pathdata->addText("\n");
my $GCCE_IncludePath = GetGCCELibPath("-print-libgcc-file-name");
$GCCE_IncludePath .= '\\include';
&textSetting($pathdata, "Path", $GCCE_IncludePath);
&textSetting($pathdata, "PathFormat", "Windows");
&textSetting($pathdata, "PathRoot", "Absolute");
$accesspath->appendChild($pathdata);
&textSetting($accesspath, "Recursive", "false");
&textSetting($accesspath, "FrameworkPath", "false");
&textSetting($accesspath, "HostFlags", "All");
$node->appendChild($accesspath);
}
}
sub addDownloadFileList($) {
my ($node, @DownloadList) = @_;
my @elements = $node->getElementsByTagName("SETTING",0);
foreach (@elements)
{
&removeNode($_);
}
my $epocdata = &main::EPOCPath . "data\\";
foreach my $srcfile (@DownloadList)
{
my $targetpath = $srcfile;
$targetpath =~ s/^Z\\/C:\\/i;
my $download = new XML::DOM::Element($xmlProjectDoc,"SETTING");
$download->addText("\n");
my $pathdata = new XML::DOM::Element($xmlProjectDoc,"SETTING");
&textElement($pathdata, "NAME", "HostFilePath");
$pathdata->addText("\n");
&addRootedPath($pathdata, 0, "$epocdata$srcfile");
$download->appendChild($pathdata);
&textSetting($download, "TargetFilePath", $targetpath);
$node->appendChild($download);
}
}
sub kitRelativePath ($) {
my ($kitRootBasedPath) = @_;
my $kitRoot = &main::EPOCPath;
$kitRoot =~ s/EPOC32\\$//i;
$kitRoot = quotemeta (&main::Path_Chop($kitRoot));
$kitRootBasedPath =~ s/^$kitRoot//i;
$kitRootBasedPath;
}
sub PMBld() {
my %changedsettings;
my $ABI=&main::ABI;
my $Bld=&main::Bld;
my $Plat=&main::Plat;
my $BaseName=&main::BaseMak;
my @SrcList=&main::SrcList;
my $BaseTrg=&main::BaseTrg;
my @BldList=&main::BldList;
my $DefFile=&main::DefFile;
my $FirstLib=&main::FirstLib;
# IsCustomDllUseCase() subroutine is called to check if the given executable
# is a custom dll or not.
my $IsCustomDll = Cl_bpabi::IsCustomDllUseCase();
# ABI flags set depending on the ENABLE_ABIV2_MODE macro set in the variant file.
my $ABIV1 = 0;
my $ABIV2 = 0;
if (($Plat eq "ARMV5_ABIV1" && $cfgMacro) || ($Plat eq "ARMV5" && !$cfgMacro)
|| ($CustPlat{'CUSTOMIZES'}
&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV1" && $cfgMacro) || ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && !$cfgMacro))))
{
$ABIV1=1;
}
elsif (($Plat eq "ARMV5_ABIV2" && !$cfgMacro) || ($Plat eq "ARMV5" && $cfgMacro)
|| ($CustPlat{'CUSTOMIZES'}
&& (($CustPlat{'ROOTPLATNAME'} eq "ARMV5_ABIV2" && !$cfgMacro) || ($CustPlat{'ROOTPLATNAME'} eq "ARMV5" && $cfgMacro))))
{
$ABIV2=1;
}
if ($CustPlat{'CUSTOMIZES'} && ($CustPlat{'ROOTPLATNAME'} eq "GCCE"))
{
$CustGCCE=1;
}
if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
# Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
# Rename FirstLib.lib static lib used with RVCT2.1 as FirstLib2_1.lib
if ($FirstLib=~/^\s*(\S+)(\.lib)$/io) {
if ($1!~/$RVCTVersion/i) {
$FirstLib=$1.$RVCTVersion.".lib";
}
}
}
my $BasicTrgType=&main::BasicTrgType;
my @LibList;
my @StatLibList=&main::StatLibList;
if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
# Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
# Rename all the static libs used with RVCT2.1 as libname2_1.lib
for (my $i =0; $i < scalar(@StatLibList); $i++) {
if ($StatLibList[$i]=~/^\s*(\S+)(\.lib)$/io) {
if ($1!~/$RVCTVersion/i) {
$StatLibList[$i]=$1.$RVCTVersion.".lib";
}
}
}
}
my @ASSPLibList = &main::ASSPLibList;
my $Trg=&main::Trg;
if ($ABIV1 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2)) {
if ($BasicTrgType=~/^LIB$/o) {
# Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
# Rename all the static libs produced with RVCT2.1 as {libname}2_1.lib
if ($Trg=~/^\s*(\S+)(\.lib)$/io) {
if ($1!~/$RVCTVersion/i) {
$Trg=$1.$RVCTVersion.".lib";
}
}
if ($BaseTrg!~/$RVCTVersion/i) {
$BaseTrg .= $RVCTVersion;
}
}
}
my $TrgPath=&main::TrgPath;
my $TrgType=&main::TrgType;
my $epocroot=&main::Path_Drive . &main::EPOCPath;
$epocroot =~ s/EPOC32\\$//i;
my $UIDFile;
$ExtraFilesPath = &main::MakeFilePath;
if ($Bld =~ /DEB/) {
@LibList=&main::DebugLibList;
} else {
@LibList=&main::LibList;
}
my $xmlTarget;
if ($ABI =~ /BPABI/)
{
$ABI = "GCCE";
}
if ($Plat eq "GCCE" || $CustGCCE || $ABIV2) {
if ($CW_major_version < 3.1) {
die "FATAL ERROR: Target $Plat requires CodeWarrior for Symbian release 3.1 at minimum.\n";
}
}
if ($ABIV2 && ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2))
{
die "FATAL ERROR: Target ARMV5_ABIV2 requires RVCT version 2.2 and greater. Detected RVCT $RVCTMajorVersion.$RVCTMinorVersion.\n";
}
if (($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) && $CW_major_version < 3.1 && $ABIV2)
{
die "FATAL ERROR: Detected RVCT Version $RVCTMajorVersion.$RVCTMinorVersion and CodeWarrior version $CW_major_version. RVCT 2.2 and greater requies CodeWarrior version 3.1 at minimum.\n";
}
$xmlTarget = findTarget($BaseName, "$Plat $Bld", "$ABI $Bld");
return if (!defined($xmlTarget));
my $targetname = $xmlTarget->getAttribute("NAME");
my $UnderlyingABI=PMUnderlyingABI($ABI);
my @ChopRTWSysIncPaths=&main::Path_Chop(&main::Path_RltToWork(&main::SysIncPaths));
my @ChopRTWUserIncPaths=&main::Path_Chop(&main::Path_RltToWork(&main::UserIncPaths));
my $EPOCPath=&main::EPOCPath;
my $LinkAs=&main::LinkAs;
my $LibPath=&main::LibPath;
my @UidList=&main::UidList;
my $WarningLevelGCC=&main::CompilerOption("GCC");
my $ExportLibrary=&main::ExportLibrary;
my $NoExportLibrary=&main::NoExportLibrary;
my $SystemTrg = SystemTarget();
my %Version = &main::Version();
my $ExtraExportLibrary;
my $PrimaryExportLibrary = $ExportLibrary;
unless ($Version{explicit}) {
$ExtraExportLibrary = $ExportLibrary;
$ExtraExportLibrary =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
$PrimaryExportLibrary = $ExtraExportLibrary;
}
my $ChopBldPath=&main::Path_Chop(&main::BldPath);
my $EPOCIncPath=&main::EPOCIncPath;
my $ChopRelPath=&main::Path_Chop(&main::RelPath);
my $RelPath=&main::RelPath;
my $StatLinkPath=&main::StatLinkPath;
my $ParentPlat;
# Check if a platform is customization, if yes find the parent platform.
my $IsPlatCustomization=IsCustomization($Plat);
if ($IsPlatCustomization) {
$ParentPlat = Plat_Customizes($Plat);
}
my @RTLibList;
if ($ABIV1) {
@RTLibList = ('dfpaeabi.lib', "dfprvct${RVCTVersion}.lib", 'drtaeabi.lib', 'drtaeabi.lib(VtblExports.o)');
if ($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) {
# The scppnwdl.lib should come before drtrvct2_2.lib
push @RTLibList, "scppnwdl.lib";
push @RTLibList, "drtrvct${RVCTVersion}.lib";
}
else
{
push @RTLibList, "dfprvct${RVCTVersion}-thunk.lib";
push @RTLibList, "drtrvct${RVCTVersion}.lib";
}
}
elsif ($ABIV2)
{
@RTLibList = ('drtaeabi.dso', 'dfpaeabi.dso', "dfprvct${RVCTVersion}.dso");
if ($RVCTMajorVersion == 2 && $RVCTMinorVersion >= 2) {
# The scppnwdl.lib should come before drtrvct2_2.lib
push @RTLibList, "scppnwdl.dso";
push @RTLibList, "drtrvct${RVCTVersion}.dso";
}
}
my @compatibleDOCUMENTExtensions = ("cfg", "h", "hrh", "iby", "inf", "ini", "loc", "mmpi", "policy", "ra", "rh", "rls", "rss", "script", "txt");
my @DocList = &main::DocList;
@addedFiles=();
# set up LinkAs
$UidList[2]=~/^0x(.*)$/o;
if ($1 ne '00000000') { # have to make sure than series of noughts in brackets doesn't appear in name for null uids
$LinkAs=join '', &main::Path_Split('Base',$LinkAs),"[$1]",&main::Path_Split('Ext',$LinkAs);
}
# set up dlltool flag hash
my %ABIDlltool=(
ARMI=>'-m arm_interwork',
ARM4=>'-m arm',
THUMB=>'-m thumb'
);
# work out the flags for various platforms
if ($ABI eq 'ARMI') {
$PlatOpt{Gcc}='-march=armv4t -mthumb-interwork';
$PlatOpt{Dlltool}=$ABIDlltool{ARMI};
}
elsif ($ABI eq 'ARM4T') {
if (&main::BuildAsARM) {
$PlatOpt{Gcc}='-march=armv4t -mthumb-interwork';
$PlatOpt{Dlltool}=$ABIDlltool{ARMI};
}
elsif ($SystemTrg) {
$PlatOpt{Gcc}='-march=armv4';
# allow thumb for ARM4 ABI where necessary
unless (&main::PlatABI eq 'ARM4') {
$PlatOpt{Gcc}.='t';
}
$PlatOpt{Dlltool}=$ABIDlltool{ARM4};
}
else {
$PlatOpt{Gcc}='-mthumb-interwork -D__MARM_THUMB__';
$PlatOpt{Dlltool}=$ABIDlltool{THUMB};
}
}
elsif ($ABI eq 'ARM4') {
$PlatOpt{Gcc}='-march=armv4';
# allow thumb for ARM4 ABI where necessary
unless (&main::PlatABI eq 'ARM4') {
$PlatOpt{Gcc}.='t';
}
$PlatOpt{Dlltool}=$ABIDlltool{ARM4};
}
elsif ($ABI eq 'THUMB') {
$PlatOpt{Gcc}='-mthumb-interwork';
$PlatOpt{Dlltool}=$ABIDlltool{THUMB};
}
elsif ($Plat ne 'WINSCW' && $Plat ne 'ARMV5' && !$IsPlatCustomization && $Plat ne 'GCCE' && $Plat ne 'ARMV5_ABIV2' && $Plat ne 'ARMV5_ABIV1') {
&main::FatalError("Platform module - ABI \"$ABI\" unrecognised");
}
if ($Plat ne 'WINSCW') {
@CompatibleABIs=@{$CompatibleABIs{$UnderlyingABI}};
}
# set up CompatibleABI lib path hash
foreach (@CompatibleABIs) {
$ABILibPath{$_}=&main::Path_Strip("$LibPath..\\..\\$_\\");
}
$Dlltool=$ToolPrefix.'dlltool.exe';
$Archive=$ToolPrefix.'ar.exe';
$Link=$ToolPrefix.'ld.exe';
$Objcopy=$ToolPrefix.'objcopy.exe';
my $WarningLevelCW=&main::CompilerOption("CW");
$xmlFileList = newList($xmlTarget,"FILELIST",1);
$xmlFileList->addText("\n");
$xmlLinkOrder = newList($xmlTarget,"LINKORDER",1);
$xmlLinkOrder->addText("\n");
# Create temporary sublists, which will be
# removed during finaliseProject
$xmlSourceGroup = newList($xmlTarget,"SOURCEGROUP",0);
$xmlSourceGroup->setAttribute("TARGET", $targetname);
$xmlSourceGroup->addText("\n");
$xmlHeadersGroup = newList($xmlTarget,"HEADERSGROUP",0);
$xmlHeadersGroup->setAttribute("TARGET", $targetname);
$xmlHeadersGroup->addText("\n");
$xmlRootGroup = newList($xmlTarget,"ROOTGROUP",0);
$xmlRootGroup->setAttribute("TARGET", $targetname);
$xmlRootGroup->addText("\n");
$xmlLinkGroup = newList($xmlTarget,"LINKGROUP",0);
$xmlLinkGroup->setAttribute("TARGET", $targetname);
$xmlLinkGroup->addText("\n");
$xmlLibGroup = newList($xmlTarget,"LIBGROUP",0);
$xmlLibGroup->setAttribute("TARGET", $targetname);
$xmlLibGroup->setAttribute("PLAT", $Plat);
$xmlLibGroup->addText("\n");
$xmlResourcesGroup = newList($xmlTarget,"RESOURCESGROUP",0);
$xmlResourcesGroup->setAttribute("TARGET", $targetname);
$xmlResourcesGroup->addText("\n");
$xmlDocumentsGroup = newList($xmlTarget,"DOCUMENTSGROUP",0);
$xmlDocumentsGroup->setAttribute("TARGET", $targetname);
$xmlDocumentsGroup->addText("\n");
my $debug="";
$debug="Debug" if ($Bld =~ /DEB$/);
my @RuntimeLibs = (); # add platform-specific runtime libraries here
if (&main::PlatCompiler eq "GCC32")
{
if ($BasicTrgType=~/^DLL$/o)
{ # Add the DLL stub library
push @RuntimeLibs, "EDLLSTUB.LIB";
}
if ($BasicTrgType=~/^(DLL|EXE)/o)
{ # Add the GCC helper fns
push @RuntimeLibs, "EGCC.LIB";
}
}
if ($Plat eq "GCCE" || $CustGCCE)
{
push @RuntimeLibs, "usrt2_2.lib"; # UDEB/UREL Specific
push @RuntimeLibs, "dfpaeabi.dso";
push @RuntimeLibs, "dfprvct2_2.dso";
push @RuntimeLibs, "drtaeabi.dso";
push @RuntimeLibs, "scppnwdl.dso";
push @RuntimeLibs, "drtrvct2_2.dso";
if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
push @RuntimeLibs, "EDLLSTUB.LIB"; # UDEB/UREL Specific
}
}
addFile(&main::Path_Split('File',$MmpFile), "Text", "", "", "Root");
# Create the uid.cpp file
if ($Plat eq "WINSCW" && $BasicTrgType=~/^(EXE|DLL)$/oi)
{
my @UidList=&main::UidList;
# create the UID source file
my $priority = "EPriorityForeground";
if (&main::ProcessPriority) {
$priority="EPriority".&main::ProcessPriority;
}
my $UidText=join(
"\n",
'// Makmake-generated uid source file',
'#include <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 -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;