# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
package Cl_arm;
my $ToolPrefix='';
my %PlatOpt=(
'Dlltool'=>'',
'Entry'=>'-e',
'Ld'=>'',
'Elftran'=>'',
);
# takes an 'expression' to evaluate with $_ bound to each of the
# remaining args
sub PrintList
{
my $expr = shift @_;
foreach (@_) {
my $str = eval($expr);
&main::Output($str);
}
}
# specify floating point model here
my $floatingpointmodel = "softvfp";
if (&main::ARMFPU && (&main::ARMFPU =~ /^VFPV2$/i)) {
$floatingpointmodel = "vfpv2";
}
my $Archive;
my $Link;
my $Objcopy;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(
PMHelp_Mmp
PMPlatProcessMmp
PMStartBldList
PMBld
PMStartSrcList
PMBitMapBld
PMResrcBld
PMStartSrc
PMAifBld
PMSrcDepend
PMSrcBldDepend
PMEndSrcBld
PMEndSrc
PMEndSrcList
PMPrefixFile
PMSupportsFeatureVariants
);
use Cwd;
use Armutl;
use RVCT_plat2set;
use cl_generic;
use E32env;
use Genutl;
use constant NOCOMPRESSIONMETHOD => 0;
use constant INFLATECOMPRESSIONMETHOD => 1;
use constant BYTEPAIRCOMPRESSIONMETHOD => 2;
use constant NON_DEBUGGABLE => 0;
use constant DEBUGGABLE => 1;
use constant DEBUGGABLE_UDEBONLY => 2;
use constant NOTPAGED => 0;
use constant UNPAGED => 1;
use constant PAGED => 2;
sub PMHelp_Mmp {
&Armutl_Help_Mmp;
}
my $Plat=main::Plat();
my ($RVCTMajorVersion, $RVCTMinorVersion, $RVCTBuildNumber) = RVCT_plat2set::get_version_list($Plat);
my $RVCTVersion = "${RVCTMajorVersion}_${RVCTMinorVersion}";
my $ARMCCVersion = "${RVCTMajorVersion}${RVCTMinorVersion}0${RVCTBuildNumber}";
my $oP = '--';
$oP = '-' if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2);
#Check if Function call Logger is enabled
my $Function_Call_Logger=&main::IsFunctionCallLogging();
# Get the information regarding supporting Compiler Wrapper Option
my $IsCompilerWrapperOption=&main::CompilerWrapperOption();
#Check the existence of elf2e32.exe in the system path
my $IsExistELF2E32EXE = 0;
open ELF2E32PIPE, "elf2e32 2>&1 |";
while (<ELF2E32PIPE>) {
if($_=~/^Symbian Post Linker\, Elf2E32/) {
$IsExistELF2E32EXE = 1;
last;
}
next;
}
close ELF2E32PIPE;
my $ArmIncDir;
my @ArmLibList;
my $ArmRT = 0;
my %AsmFiles = ();
my %AsmDirs = ();
my $oe_options = '';
my $NamedSymLkup = 0;
my $symNameLkupOpt = '';
sub PMPlatProcessMmp (@) {
&Armutl_DoMmp(@_);
$ArmIncDir = RVCT_plat2set::get_inc_path($Plat);
&main::SetStdIncPaths($ArmIncDir);
@ArmLibList = &Armutl_ArmLibList;
$ArmRT = &Armutl_ArmRT;
my @AsmFileList = &Armutl_AsmFileList;
foreach (@AsmFileList) { $AsmFiles{ucfirst lc $_} = 1; }
}
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;
}
my $RVCT20 = 0;
# suppress these warnings & errors
#Warning: #66-D: enumeration value is out of "int" range
# "EUSER\CBASE\Ub_act.cpp", line 20: Warning: #161-D: unrecognized #pragma
# 611: overloaded virtual function "entity" is only partially overridden in <entitykind> "entity"
# "EUSER\CBASE\Ub_act.cpp", line 256: Warning: #654-D: declaration modifiers are incompatible with previous declaration
# 997: <entity-kind> "entity" is hidden by "entity" -- virtual function override intended?
# "EPOC32\include\s32stor.h", line 354: Error: #1152-D: polymorphic base classes need to be exported as well
# "INCLUDE\e32base.h", line 31: Warning: #1300-D: ~CBufBase inherits implicit virtual
#"COMPSUPP\\RVCT2_1\\Dfpaeabi.cpp", line 87: Warning: A1488W: PROC/FUNC at line 9 without matching ENDP/ENDFUNC
#"COMPSUPP\\RVCT2_1\\Dfpaeabi.cpp", line 85: Warning: A1464W: ENDP/ENDFUNC without corresponding PROC/FUNC
#Warning: L6318W: _integrator_cm1136_ekern.in(.text) contains branch to a non-code symbol FindMostSignificantOne(unsigned long).
my $diag_suppressions = '--diag_suppress 66,161,611,654,997,1152,1300,1464,1488,6318,6331';
# downgrade from errors to warnings
my $diag_warnings = '';
# upgrade from warnings to errors
# Warning: #1267-D: Implicit physical register R0 should be defined as a variable
my $diag_errors = '--diag_error 1267';
my $commonOptions = $RVCT20 ?
"$diag_suppressions $diag_warnings $diag_errors" :
"$diag_suppressions $diag_warnings $diag_errors";
my @mmpOption = &main::ReplaceOptions("ARMCC");
my $CompilerOption = &main::CompilerOption("ARMCC");
my $contingentOptions;
my $thumbOptions = $RVCT20 ? '-thumb' : '--thumb ';
my $armOptions = $RVCT20 ? '-arm' : '--arm ';
my $kernelOptions = $RVCT20 ? '-arm' : '--arm --no_exceptions --no_exceptions_unwind';
my $invariantOptions = $RVCT20 ?
'-cpu 5T --enum_is_int -Ono_known_library --export_vtbl -apcs /inter' :
'--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);
my $exceptions = $RVCT20 ? '' : ' --exceptions --exceptions_unwind';
my $floatingpoint = $RVCT20 ? '' : ' --fpu '.$floatingpointmodel.'';
my @FCLogger_Macros; # Macros required to be passed to the FCLogger
my $useLinkerFeedBack = 0;
sub LinkerFeedBackFile() {
return unless $useLinkerFeedBack;
my $Trg = &main::Trg;
return "$Trg.lfb";
}
sub LinkerFeedBackOption() {
return "" unless $useLinkerFeedBack;
my $BasicTrgType=&main::BasicTrgType;
return "" unless ($BasicTrgType=~/^(DLL|EXE)/o);
my $file = LinkerFeedBackFile();
return "--feedback $file ";
}
my %BSF_keywords = (
COMMON_OPTIONS => 1,
THUMB_OPTIONS => 1,
ARM_OPTIONS => 1,
KERNEL_OPTIONS => 1,
INVARIANT_OPTIONS => 1
);
sub Read_BSF_Options() {
my %plat = (main::PlatRec());
my @Customization_Data = split(/\n/,$plat{'CUSTOMIZATION_DATA'});
foreach my $option (@Customization_Data) {
next if ($option =~ /^$/);
warn "Unrecognized BSF syntax: $option.\n"
unless ($option =~ /\s*(\S+)\s+(.+)$/);
my $key = uc $1;
my $val = $2;
warn "Unrecognized BSF keyword: $key.\n"
unless ($BSF_keywords{$key});
if ($key =~ /COMMON_OPTIONS/) {
Set_BSF_Options(\$commonOptions,$val);
next;
}
if ($key =~ /THUMB_OPTIONS/) {
Set_BSF_Options(\$thumbOptions,$val);
next;
}
if ($key =~ /ARM_OPTIONS/) {
Set_BSF_Options(\$armOptions,$val);
next;
}
if ($key =~ /KERNEL_OPTIONS/) {
Set_BSF_Options(\$kernelOptions,$val);
next;
}
if ($key =~ /INVARIANT_OPTIONS/) {
Set_BSF_Options(\$invariantOptions,$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=();
# Check if the value of BSF option is to be set or added/removed.
if($Options =~ /\+\[.*\]\+|\-\[.*\]\-/)
{
if (@Fragments = Split_BSF_Options($Options,'RemoveOptions'))
{
foreach my $Opt (@Fragments)
{
# Remove trailing white spaces
$Opt =~ s/\s+$//;
$$OptionName =~ s/$Opt//g;
}
@Fragments=();
}
if (@Fragments = Split_BSF_Options($Options,'AddOptions'))
{
$$OptionName .= " @Fragments";
@Fragments=();
}
# Warn if options are not present in the form '+[...]+' or '-[...]-'
$Options =~ s/\+\[.*?\]\+|\-\[.*?\]\-//g;
if($Options !~ /^\s*$/)
{
print "Warning: Ignoring option(s) \"$Options\" specified in BSF as option(s) should be in the form '+[...]+' or '-[...]-.\n";
}
}
else
{
$$OptionName = $Options;
}
&main::Output(
"\n"
);
}
# Split BSF options to find options which are to be added/removed
# @param String - List of options present in form '+[...]+' or '-[....]-'
# @param $Task - Variable to decide whether to return options to be addded or options to be removed
sub Split_BSF_Options($$)
{
my ($String,$Task) = @_;
my @Result = ();
my @Fragments = ();
my $Pattern = '';
if ($Task eq 'AddOptions')
{
# Get the options which are to be added (present in the form '+[...]+')
@Fragments = $String =~ /\+\[(.*?)\]\+/g;
}
elsif ($Task eq 'RemoveOptions')
{
# Get the options which are to be removed (present in the form '-[...]-')
@Fragments = $String =~ /\-\[(.*?)\]\-/g;
}
# Set the value of '$Pattern' which is required to segregate one option from another based on the option prefix.
# Option prefix for RVCT can be '-' or '--'.
$Pattern = '-{1,2}\S+\s*(?!-)\S*';
foreach my $Val (@Fragments)
{
my @Opt = $Val =~ /$Pattern/g;
push @Result,@Opt;
}
return @Result;
}
sub ComputeCompilerOpts() {
my %plat = &main::PlatRec();
Read_BSF_Options() if ($plat{'CUSTOMIZES'});
my $ABI=&main::ABI;
my $TrgType=&main::TrgType;
if (SysTrg()) {
$contingentOptions = $kernelOptions.$floatingpoint;
} elsif (main::BuildAsARM() or ($ABI eq 'ARMV4')) {
$contingentOptions = $armOptions.$floatingpoint.$exceptions;
} else {
$contingentOptions = $thumbOptions.$floatingpoint.$exceptions.' -D__MARM_THUMB__';
push @FCLogger_Macros, '__MARM_THUMB__';
}
# support for ARMV4
my $invopts = "$invariantOptions";
if ($ABI eq 'ARMV4') {
$invopts =~ s/5T/4/;
$invopts =~ s/inter/nointer/;
} else {
$contingentOptions .= ' -D__MARM_INTERWORK__';
push @FCLogger_Macros, '__MARM_INTERWORK__';
}
#Options to export all the external symbols for OE DLL , OE Exe and OE Static Lib
if ($TrgType=~/^STDDLL$/o || $TrgType=~/^STDEXE$/o || $TrgType=~/^STDLIB$/o) {
$oe_options=' --no_hide_all';
}
return $commonOptions.' '.$contingentOptions.' '.$invopts.' '.$oe_options.' '.&main::CompilerOption("ARMCC");
}
my $Makecmd;
sub PMStartBldList($) {
($Makecmd) = @_;
my $ABI=&main::ABI;
my $BaseTrg=&main::BaseTrg;
my $BasicTrgType=&main::BasicTrgType;
my @BldList=&main::BldList;
my @ChopSysIncPaths=&main::Path_Chop(&main::SysIncPaths);
my @ChopUserIncPaths=&main::Path_Chop(&main::UserIncPaths);
my $DefFile=&main::DefFile;
my $EPOCPath=&main::EPOCPath;
my $LinkAs=&main::LinkAs;
my $LibPath=&main::LibPath.'LIB\\';
my @MacroList=&main::MacroList();
push @MacroList, "__SUPPORT_CPP_EXCEPTIONS__";
my $VariantFile=&main::VariantFile();
my $Plat=&main::Plat;
my $Trg=&main::Trg;
if ($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 $TrgType=&main::TrgType;
my @UidList=&main::UidList;
my $SystemTrg = &main::SystemTrg;
my $ExportLibrary=&main::ExportLibrary;
my $NoExportLibrary=&main::NoExportLibrary;
# N.B. should get better way to detect kernel probably!!
$SystemTrg = 1 if ($ExportLibrary =~ /EKERN/i);
# N.B. should get better way to detect this
$SystemTrg = 1 if ($Trg =~ /KSRT/i);
my %Version = &main::Version();
my $ExtraExportLibrary;
my $PrimaryExportLibrary = $ExportLibrary;
unless ($Version{explicit}) {
$ExtraExportLibrary = $ExportLibrary;
$ExtraExportLibrary =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
$PrimaryExportLibrary = $ExtraExportLibrary;
}
# set up LinkAs
$UidList[2]=~/^0x(.*)$/o;
if ($1 ne '00000000') { # have to make sure than series of noughts in brackets doesn't appear in name for null uids
$LinkAs=join '', &main::Path_Split('Base',$LinkAs),"[$1]",&main::Path_Split('Ext',$LinkAs);
}
# work out the flags for various platforms
unless ($ABI eq 'ARMV5' or $ABI eq 'ARMV4') {
&main::FatalError("Platform module - ABI \"$ABI\" unrecognised");
}
my $ComputeCompilerOpts=ComputeCompilerOpts();
if (@mmpOption)
{
my $pattern = '-{1,2}\S+\s*(?!-)\S*';
foreach my $options (@mmpOption)
{
my @opts = $options =~ /$pattern/g;
my $count = 0;
while ($count <= $#opts)
{
my $opt;
my $rep;
if ($opts[$count] =~ /^(\S+)\s+(\S+)$/)
{
$opt = $1;
$rep = $2;
$ComputeCompilerOpts =~ s/$opt\s+\S+\s+/ $opt $rep /g;
$count++;
}
else
{
$opt = $opts[$count];
$rep = $opts[$count+1];
$ComputeCompilerOpts =~ s/$opt/$rep/g;
$count+=2;
}
}
}
}
$PlatOpt{Arm} = $ComputeCompilerOpts;
my $InterWorking = ($ABI eq 'ARMV4') ? "" : "--inter";
$Archive=$ToolPrefix.'armar';
$Link=$ToolPrefix."armlink ${oP}diag_suppress 6331,6780 ";
$Objcopy=$ToolPrefix.'objcopy';
&Generic_Header(0,$Makecmd); # define standard things using absolute paths
if ($Makecmd eq "nmake") {
&main::Output(
"\n",
"PATH=",&main::Path_Drive,$EPOCPath,"gcc\$(PBUILDPID)\\bin;\$(PATH)\n",
"\n"
);
}
else {
&main::Output(
"\n",
"# must set both PATH and Path to make it work correctly\n",
"Path:=",&main::Path_Drive,$EPOCPath,"gcc\$(PBUILDPID)\\bin;\$(Path)\n",
"PATH:=\$(Path)\n",
"\n"
);
}
&main::Output(
"INCDIR ="
);
PrintList("\" -J \$_\"", @ChopUserIncPaths);
PrintList("\" -J \$_\"", @ChopSysIncPaths);
if ($ArmIncDir) {
&main::Output(
" -J \"$ArmIncDir\" ",
);
}
&main::Output(
"\n",
"\n"
);
#Function Call Logger
if ($Function_Call_Logger) {
&main::Output(
"INCDIR_FCLOGGER ="
);
PrintList("\" -I \$_\"", @ChopUserIncPaths);
PrintList("\" -I \$_\"", @ChopSysIncPaths);
if ($ArmIncDir) {
&main::Output(
" -I \"$ArmIncDir\" "
);
}
&main::Output(
"\n",
"\n"
);
}
&main::Output(
"ARMCCFLAGS=$PlatOpt{Arm} -c\\\n",
"\n"
);
&main::Output(
"ARMCCDEFS = "
);
PrintList("\" -D\$_\"", @MacroList);
if($VariantFile) {
if ($Function_Call_Logger) {
#FC Logger accepts product include file without path
my $file=&main::Path_Split('File', ${VariantFile});
&main::Output(
" -D\"__PRODUCT_INCLUDE__=\\\"${file}\\\"\""
);
}
else {
&main::Output(
" -D__PRODUCT_INCLUDE__=\\\"${VariantFile}\\\""
);
}
}
&main::Output(
" \$(USERDEFS)\n",
"\n"
);
if ($TrgType=~/^STDDLL$/o || $TrgType=~/^STDEXE$/o){
# For now, named symbol lookup is enabled only for the STD binaries. Later, it may be enabled based on an mmp
# keyword.
$NamedSymLkup = 1;
$symNameLkupOpt = '--sym_name_lkup';
}
foreach (@BldList) {
&main::Output(
"ARMCC$_ = armcc"
);
if(&main::DebugSwitchUsed() ) {
# when the debug switch is specified and enabled, set the compiler's debug flag for both udeb or urel.
# when the debug switch is disabled, don't set the compiler's debug flag for either udeb or urel.
# The optimization option is set only based on the build i.e., Udeb or Urel and is independent of
# whether debug is enabled or not. This might give a poorer debug view for debug-enabled Urel build.
if(&main::SymbolicDebugEnabled() ) {
&main::Output(
' -g'
);
}
}
elsif (/DEB$/o) {
&main::Output(
' -g'
);
}
if (/DEB$/o) {
&main::Output(
' -O0'
);
}
else {
&main::Output(
' -O2'
);
}
&main::Output(
' $(ARMCCFLAGS)'
);
my @ml = &main::MacroList($_);
PrintList("\" -D\$_\"", @ml);
&main::Output(
" \$(ARMCCDEFS)\n"
);
}
&main::Output(
"\n",
"\n"
);
#Function call logger
if ($Function_Call_Logger) {
#Send all the debug macros to logger
foreach (@BldList) {
&main::Output (
"FCLOGGER$_ = ",
$EPOCPath,
"tools\\fc_logger\\edgcpfe"
);
my @ml = &main::MacroList($_);
push @ml, "__ARMCC_VERSION=$ARMCCVersion";
PrintList("\" -D\$_\"", @ml);
&main::Output(
" \$(ARMCCDEFS)"
);
PrintList("\" -D\$_\"", @FCLogger_Macros);
&main::Output(
"\n",
"\n"
);
}
}
foreach (@BldList) {
&main::Output(
"$_ :"
);
if ($BasicTrgType !~ /IMPLIB/io) {
&main::Output (
" \\\n\t",
&Generic_Quote("\$(EPOCTRG$_)\\".&main::Trg($_))
);
}
# lib has to come after the main target so that a .DEF file will be generated if the project is not frozen
if ($DefFile and not &main::ExportUnfrozen) {
&main::Output(
" \\\n",
"\tLIBRARY\n"
);
}
&main::Output(
"\n",
"\n"
);
}
# Resource building is done entirely via cl_generic.pm
PrintList("\"\nRESOURCE\$_ : MAKEWORK\$_\"", @BldList);
&main::Output(
"\n",
"\n",
);
&main::Output(
"LIBRARY : MAKEWORKLIBRARY"
);
if ($BasicTrgType=~/^LIB$/o) {
# code to ensure that the static libraries for all builds are built at the library stage
PrintList("\" \$_\"", @BldList);
}
elsif ($DefFile and !$NoExportLibrary) {
unless (&main::ExportUnfrozen) {
if (-e $DefFile) { # effectively "if project frozen ..."
&main::Output(
" ", &Generic_Quote("\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.lib"),
);
# if elf2e32.exe(postlinker) exists, then generate .dso along with .lib
if ($IsExistELF2E32EXE) {
&main::Output(
" ", &Generic_Quote("\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.dso"), "\n"
);
}
else {
&main::Output("\n");
}
}
else {
&main::Output(
"\n",
"\t\@echo WARNING: Not attempting to create any import libraries.\n",
"\t\@echo When exports are frozen in \"$DefFile\", regenerate Makefile.\n"
);
}
} else {
&main::Output(
"\n",
"\t\@echo Not attempting to create \"\$(EPOCLIB)\\LIB\\$PrimaryExportLibrary.lib\"\n",
"\t\@echo from frozen .DEF file, since EXPORTUNFROZEN specified.\n"
);
}
my $theDefFile = $DefFile;
$theDefFile = "\$(EPOCBLD)\\$BaseTrg.def" unless (-e $DefFile);
&main::Output(
"\n",
"\n",
"# REAL TARGET - LIBRARY\n",
"\n",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.lib"), " : ",
&Generic_Quote($DefFile), "\n",
"\tperl -S prepdef.pl ", &Generic_Quote($DefFile), " \"\$(EPOCBLD)\\$ExportLibrary.prep.def\"\n",
"\tdef2dll.bat --path=\$(EPOCLIB)\\LIB \\\n\t\t--bldpath=\$(EPOCBLD) \\\n\t\t--import=$ExportLibrary \\\n",
"\t\t--deffile=\"\$(EPOCBLD)\\$ExportLibrary.prep.def\" \\\n\t\t--linkAs=$LinkAs \\\n\t\t$InterWorking\n",
"\n",
);
if ($ExtraExportLibrary) {
&main::Output(
"\n",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.lib"), " : ",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.lib"), "\n",
"\tcopy \"\$<\" \"\$@\"\n"
);
}
#if elf2e32.exe(postlinker) exists, then generate .dso(which will be used by ABIV2 platforms)
if ($IsExistELF2E32EXE) {
&main::Output(
"\n",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"), " : ",
&Generic_Quote($DefFile), "\n",
"\telf2e32 --definput=\"\$(EPOCBLD)\\$ExportLibrary.prep.def\" --dso=",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"),
" --linkas=$LinkAs\n"
);
if ($ExtraExportLibrary) {
&main::Output(
"\n",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.dso"), " : ",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$ExportLibrary.dso"), "\n",
"\tcopy \"\$<\" \"\$@\"\n"
);
}
}
}
my $freezeDir = &main::Path_Split('Path', $DefFile);
chop($freezeDir);
# dummy rule for def files to cope with filename case differences
unless (&main::ExportUnfrozen) {
if (-e $DefFile) { # effectively "if project frozen ..."
&main::Output(
"\n",
"\n",
&Generic_Quote($DefFile), " : ", "\n",
"\t\@rem Do nothing\n",
);
}
}
&main::Output(
"\n",
"\n",
&Generic_Quote($freezeDir), " : ", "\n",
"\tperl -S emkdir.pl \$\@\n",
);
&main::Output(
"\n",
"\n",
"FREEZE : ",
&Generic_Quote($freezeDir), "\n",
);
if ($DefFile and $BasicTrgType!~/^IMPLIB$/io) {
# call perl on the script here so make will die if there are errors
# - this doesn't happen if calling perl in a batch file
&main::Output( "\tperl -S efreeze.pl \$(EFREEZE_ALLOW_REMOVE) \"$DefFile\" \"\$(EPOCBLD)\\$ExportLibrary.def\" \n" );
}
&main::Output(
"\n",
"CLEANLIBRARY :\n"
);
if ($DefFile and !$NoExportLibrary) {
&main::Output(
"\t-\$(ERASE) \"\$(EPOCLIB)\\LIB\\$ExportLibrary.lib\"\n"
);
if ($ExtraExportLibrary) {
&main::Output(
"\t-\$(ERASE) \"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.lib\"\n"
);
}
}
&main::Output(
"\n",
"\n"
);
&Generic_MakeWorkDir('MAKEWORKLIBRARY',"${LibPath}");
&Generic_Releaseables;
}
sub PMBld {
my $ABI=&main::ABI;
my @ASSPLibList=&main::ASSPLibList;
my @SrcList=&main::SrcList;
my @StringTables=&main::StringTables;
my $BaseTrg=&main::BaseTrg;
my $FeatureVariantBaseTrg=&main::FeatureVariantBaseTrg;
my $Bld=&main::Bld;
my $ChopBldPath=&main::Path_Chop(&main::BldPath);
my $DefFile=&main::DefFile;
my $EPOCIncPath=&main::EPOCIncPath;
my $FirstLib=&main::FirstLib;
if ($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 {libname}2_1.lib
if ($FirstLib=~/^\s*(\S+)(\.lib)$/io) {
if ($1!~/$RVCTVersion/i) {
$FirstLib=$1."${RVCTVersion}.lib";
}
}
}
my $BasicTrgType=&main::BasicTrgType;
my @LibList;
my @RTLibList = $RVCT20 ?
('udfp.lib', 'udrt.lib', 'udrt.lib(VtblExports.o)'):
('dfpaeabi.lib', "dfprvct${RVCTVersion}.lib", 'drtaeabi.lib', 'drtaeabi.lib(VtblExports.o)');
if ( $RVCTVersion lt "2_2" ) {
push @RTLibList, "dfprvct${RVCTVersion}-thunk.lib";
push @RTLibList, "drtrvct${RVCTVersion}.lib";
}
else {
# The scppnwdl.lib should come before drtrvct2_2.lib
push @RTLibList, "scppnwdl.lib";
push @RTLibList, "drtrvct${RVCTVersion}.lib";
}
my $SystemTrg = &main::SystemTrg;
my $LibPath= &main::LibPath;
my $LinkAs=&main::LinkAs;
my $ExportLibrary=&main::ExportLibrary;
my $NoExportLibrary=&main::NoExportLibrary;
# N.B. should get better way to detect kernel probably!!
$SystemTrg = 1 if ($ExportLibrary =~ /EKERN/i);
my $ChopRelPath=&main::Path_Chop(&main::RelPath);
my $RelPath=&main::RelPath;
my @StatLibList=&main::StatLibList;
if ($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 {libname}2_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 $StatLinkPath=&main::StatLinkPath;
my $Trg=&main::Trg;
if ($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;
}
}
}
#OE Glue Code
my @oe_exe_libs=("libcrt0.lib");
my @oe_exe_libs_wchar=("libwcrt0.lib");
#OE Import Library List
my @oe_import_library_list=();
my $TrgType=&main::TrgType;
my @UidList=&main::UidList;
my $InterWorking = ($ABI eq 'ARMV4') ? "" : "--inter";
my %Version = &main::Version();
my $ExtraExportLibrary;
unless ($Version{explicit}) {
$ExtraExportLibrary = $ExportLibrary;
$ExtraExportLibrary =~ s/\{(\d|a|b|c|d|e|f){8}\}//i;
}
my $linkerDebugOpt = "";
if(&main::DebugSwitchUsed() ){
if(&main::SymbolicDebugEnabled ()){
# set the linker's debug flag if the debug switch is specified and enabled.
$linkerDebugOpt = "${oP}debug ";
}
}
elsif ($Bld =~ /DEB/) {
$linkerDebugOpt = "${oP}debug ";
}
if ($Bld =~ /DEB/) {
@LibList = &main::DebugLibList;
} else {
@LibList = &main::LibList;
}
if(not(grep /^euser.lib$/, @LibList)){
push @oe_import_library_list, "euser.lib";
}
if(not (grep /^libc.lib$/i, @LibList)){
push @oe_import_library_list, "libc.lib";
}
# set up $LinkAs
$UidList[2]=~/^0x(.*)$/o;
if ($1 ne '00000000') { # have to make sure than series of noughts in brackets doesn't appear in name for null uids
$LinkAs=join '', &main::Path_Split('Base',$LinkAs),"[$1]",&main::Path_Split('Ext',$LinkAs);
}
# REAL TARGETS
#-------------
&main::Output(
"# REAL TARGET - BUILD VARIANT $Bld\n",
"\n"
);
# releasables
my @releaseables;
push @releaseables, "$RelPath$Trg" if ($BasicTrgType!~/^IMPLIB$/io);
if ($BasicTrgType=~/^(DLL|EXE)$/o) {
push @releaseables, "$RelPath$Trg.map";
}
if (-e $DefFile and !$NoExportLibrary) { # effectively "if project frozen ..."
push @releaseables, "$LibPath$ExportLibrary.lib";
push @releaseables, "$LibPath$ExtraExportLibrary.lib" if ($ExtraExportLibrary);
#if elf2e32.exe(postlinker) exists in the $PATH, then include .dsos also into releasables list
if ($IsExistELF2E32EXE) {
push @releaseables, "$LibPath$ExportLibrary.dso";
push @releaseables, "$LibPath$ExtraExportLibrary.dso" if ($ExtraExportLibrary);
}
}
push @releaseables, &main::FeatureVariantVMapFile() if &main::FeatureVariantVMapFile();
&main::Output(
"WHAT$Bld : WHATGENERIC\n",
"\n",
"CLEAN$Bld : CLEANBUILD$Bld CLEANRELEASE$Bld\n",
"\n",
"CLEANBUILD$Bld : \n",
"\t\@perl -S ermdir.pl \"\$(EPOCBLD$Bld)\"\n",
"\n",
"CLEANRELEASE$Bld : CLEANGENERIC\n",
"\n"
);
&Generic_WhatCleanTargets($Bld, "WHAT$Bld", "CLEANRELEASE$Bld", @releaseables);
&Generic_MakeWorkDir("MAKEWORK$Bld",$ChopBldPath);
&Generic_MakeWorkDir("MAKEWORK$Bld",$ChopRelPath);
return if ($BasicTrgType=~/^IMPLIB$/io);
&main::Output(
"LISTING$Bld : MAKEWORK$Bld"
);
foreach (@SrcList) {
my $BaseSrc = &main::Path_Split('Base', $_);
my $Ext = &main::Path_Split('Ext', $_);
if ($Ext =~ /cia/i) {
$BaseSrc = "$BaseSrc\_";
}
&main::Output(
" \\\n\tLISTING$Bld$BaseSrc"
);
}
&main::Output(
"\n",
"\n"
);
# Compiler wrapper support starts
if($IsCompilerWrapperOption)
{
my $Platcmpwrap=&main::Plat;
&main::Output(
"COMPWRAP$Bld : OUTPUT_NAME = ",
"$Platcmpwrap\_$Bld",
"\n"
);
&main::Output(
"COMPWRAP$Bld : MAKEWORK$Bld"
);
foreach (@SrcList) {
my $BaseSrc = &main::Path_Split('Base', $_);
&main::Output(
" \\\n\tCOMPWRAP$Bld$BaseSrc"
);
}
&main::Output(
"\n",
"\n"
);
}
# Compiler wrapper support
&main::Output(
"LIBS$Bld="
);
if ($BasicTrgType=~/^DLL$/o) { # Add the DLL stub library
if ($RVCTMajorVersion == 2 && $RVCTMinorVersion < 2) {
# Temporary Workaround for RVCT2.1 static libs problem with RVCT2.2 builds
&main::Output(
" \\\n\t",
&Generic_Quote("\$(EPOCSTATLINK$Bld)\\EDLLSTUB$RVCTVersion.lib")
);
}
else {
&main::Output(
" \\\n\t",
&Generic_Quote("\$(EPOCSTATLINK$Bld)\\EDLLSTUB.lib")
);
}
}
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCSTATLINK$Bld\)\\\\\$_\"\)", @StatLibList);
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @LibList);
#OE Import Libraries
if ( $TrgType=~/^STDEXE$/o || $TrgType=~/^STDDLL$/o )
{
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_\"\)", @oe_import_library_list);
}
#OE Glue Code
if ($TrgType=~/^STDEXE$/o) {
if (&main::IsWideCharMain()) {
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\$Bld\\\\\$_\"\)", @oe_exe_libs_wchar);
}
else {
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\$Bld\\\\\$_\"\)", @oe_exe_libs);
}
}
my $StaticRTLib = $RVCT20 ? "usrt20" : "usrt${RVCTVersion}" ;
# use ksrt for system code and usrt for user ARM code
$StaticRTLib = "ksrt${RVCTVersion}" if ($SystemTrg);
&main::Output(
" \\\n\t",
&Generic_Quote("\$(EPOCSTATLINK$Bld)\\$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) {
&main::Output(
" \\\n\t",
&Generic_Quote("\$(EPOCLIB)\\LIB\\$_")
) unless ($_ =~ /$TargLib/i);
}
}
}
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\$_\"\)", @ArmLibList);
&main::Output(
"\n",
"\n"
);
&main::Output(
"\n# ADDITIONAL LINKER OPTIONS",
"\nUSERLDFLAGS = ",
&main::LinkerOption("ARMCC"),
"\n\n"
);
&main::Output(
"VTBLEXPORTS$Bld="
);
my $vtobj = quotemeta("(VtblExports.o)");
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\"\\\$\(EPOCLIB\)\\\\LIB\\\\\$_$vtobj\"\)", @LibList);
&main::Output(
"\n",
"\n"
);
my $objectFiles = "";
my $bldPath = &main::BldPath;
my $replacement;
# If LOCAL_BUILD_PATH is set replace the \epoc32\build with local setting
if ( defined( $ENV{LOCAL_BUILD_PATH} ) ) {
$replacement = $ENV{"LOCAL_BUILD_PATH"};
my $epocroot=$ENV{"EPOCROOT"};
my $match = "\Q${epocroot}\EEPOC32\\\\BUILD";
$bldPath =~ s/${match}/${replacement}/;
}
# Must add StringTable obj files first to preserve Evalid results consistency.
foreach my $item (@StringTables) {
$objectFiles .= $bldPath.$$item{BaseTrg}.".o\n" if !($$item{Hdronly});
}
&main::Output(
"OBJECTS$Bld="
);
foreach (@SrcList) {
my $BaseSrc = &main::Path_Split('Base', $_);
my $Ext = &main::Path_Split('Ext', $_);
if ($Ext =~ /cia/i) {
$BaseSrc = "$BaseSrc\_";
}
&main::Output(
" \\\n\t",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o")
);
# Only add if not already added from @StringTables
my $objectFile = $bldPath.$BaseSrc.".o\n";
$objectFile=~ s/\\/\\\\/g; # escape the '\'
if ($objectFiles !~ m/$objectFile/i){
$objectFiles .= &main::BldPath.$BaseSrc.".o\n";
}
}
&main::Output(
"\n",
"\n"
);
# Create "via" file containing all object files in order to reduce
# command line lengths in pertinent calls
my $objectsViaFile = &main::CommandFile();
&main::CreateExtraFile($objectsViaFile, $objectFiles);
if ($BasicTrgType=~/^LIB$/o) {
&main::Output(
&Generic_Quote("\$(EPOCTRG$Bld)\\$Trg"),
" : \$(OBJECTS$Bld)"
);
} else {
&main::Output(
&Generic_Quote("\$(EPOCTRG$Bld)\\$Trg"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseTrg.in")
);
}
if (-e $DefFile) { # effectively "if project frozen ..."
&main::Output(
" ", &Generic_Quote($DefFile)
);
}
if ($BasicTrgType=~/^(EXE|DLL)$/o) {
&main::Output(
" ", &Generic_Quote("\$(EPOCSTATLINK$Bld)\\$FirstLib")
);
}
&main::Output(
" \$(LIBS$Bld)"
);
# generate an export object from the ordered .DEF file
if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
# make the .exp file a dependency for targets that have exports
&main::Output(" ", &Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.exp"), "\n");
if (&main::ExportUnfrozen) {
&main::Output(
"\tdef2dll.bat --path=\$(EPOCBLD$Bld) \\\n\t\t--bldpath=\$(EPOCBLD$Bld) \\\n\t\t--export=$ExportLibrary \\\n\t\t--import=$ExportLibrary\\\n",
"\t\t--deffile=\$(EPOCBLD$Bld)\\$ExportLibrary.def \\\n\t\t--linkAs=$LinkAs \\\n\t\t$InterWorking $symNameLkupOpt\n",
);
&main::Output(
"\n",
"\tcopy ", " \"\$(EPOCBLD$Bld)\\$ExportLibrary.lib\" ",
"\"\$(EPOCLIB)\\LIB\\$ExportLibrary.lib\"",
"\n"
);
if ($ExtraExportLibrary) {
&main::Output(
"\n",
"\tcopy \"\$(EPOCLIB)\\LIB\\$ExportLibrary.lib\" ",
"\"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.lib\"",
"\n"
);
}
#if elf2e32.exe(postlinker) exists, then generate .dso(which will be used by ABIV2 platforms)
if ($IsExistELF2E32EXE) {
&main::Output(
"\n",
"\telf2e32 --definput=\"\$(EPOCBLD$Bld)\\$ExportLibrary.def\" --dso=",
"\$(EPOCLIB)\\LIB\\$ExportLibrary.dso --linkas=$LinkAs\n"
);
if ($ExtraExportLibrary) {
&main::Output(
"\n",
"\tcopy \"\$(EPOCLIB)\\LIB\\$ExportLibrary.dso\" ",
"\"\$(EPOCLIB)\\LIB\\$ExtraExportLibrary.dso\"",
"\n"
);
}
}
}
} elsif($NamedSymLkup){
# For an EXE, generate the .exp to accomodate 0th ordinal
&main::Output(" ", &Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.exp"), "\n");
}
else {
&main::Output("\n");
}
# get rid of any -symbols produced .map file
if ($BasicTrgType=~/^(DLL|EXE)/o) {
&main::Output(
"\t-\$(ERASE) \"\$(EPOCTRG$Bld)\\$Trg.map\" \n"
);
}
# Generate the dependency info - This is required to put the libraries in the same order
# as mentioned in mmp.
if($NamedSymLkup) {
&main::Output(
"\tperl -S deputil.pl $InterWorking --path=\$(EPOCBLD$Bld) \\\n",
"\t\t--out=$ExportLibrary \\\n",
"\t\t--libpath=\$(EPOCLIB)\\LIB \\\n",
"\t\t\$(LIBS$Bld)\n",
);
}
my $AbsentSubst = '';
if ($BasicTrgType=~/^(DLL|EXE)/o) {
my $datalinkbase = "0x400000";
$datalinkbase = &main::DataLinkAddress if (&main::DataLinkAddress);
# make sure the linker feedback file is writable if it exists.
my $lfbfile = LinkerFeedBackFile();
&main::Output(
"\t\@if exist $lfbfile attrib -r $lfbfile\n"
) if $useLinkerFeedBack;
my $lfboption = LinkerFeedBackOption();
&main::Output(
"\t$Link $linkerDebugOpt ${oP}shl ${oP}reloc ${oP}split ${oP}rw-base $datalinkbase \\\n\t\t$lfboption${oP}noscanlib $PlatOpt{Ld}\\\n"
);
my $EntrySymbol;
if ($BasicTrgType=~/^DLL$/o) {
$EntrySymbol = '_E32Dll';
}
elsif ($BasicTrgType=~/^EXE$/o) {
$EntrySymbol = '_E32Startup';
}
if ($EntrySymbol) {
$AbsentSubst = " -absent $EntrySymbol";
}
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";
}
&main::Output(
"\t\t${oP}entry _E32Dll \$(EPOCSTATLINK$Bld)\\$FirstLib($ObjFile) \$(EPOCSTATLINK$Bld)\\$FirstLib \\\n",
"\t\t\$(EPOCBLD$Bld)\\$ExportLibrary.exp \\\n"
);
} 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 building user-side under RVCT2.0.x, use 2.0.1 static library
if ($RVCT20) {
if ($ObjFile =~/UC_EXE_.o/i) {
$FirstLib = "EEXE20.LIB";
}
}
&main::Output( "\t\t${oP}entry _E32Startup \$(EPOCSTATLINK$Bld)\\$FirstLib($ObjFile) \$(EPOCSTATLINK$Bld)\\$FirstLib \\\n" );
if ($TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o || $NamedSymLkup) {
&main::Output( "\t\t\$(EPOCBLD$Bld)\\$ExportLibrary.exp \\\n" );
}
}
if($NamedSymLkup) {
&main::Output(
"\t\t--edit \"\$(EPOCBLD$Bld)\\$ExportLibrary.dep\" \\\n"
);
}
&main::Output(
"\t\t-o \"\$(EPOCBLD$Bld)\\$Trg\" \\\n",
"\t\t${oP}symbols ${oP}list \"\$(EPOCTRG$Bld)\\$Trg.map\" \\\n",
"\t\t\$(EPOCBLD$Bld)\\$BaseTrg.in \\\n"
);
&main::Output(
"\t\t\$(LIBS$Bld) \\\n",
"\t\t\$(VTBLEXPORTS$Bld) \$(USERLDFLAGS) \n"
);
if(&main::DebugSwitchUsed() ){
if(&main::SymbolicDebugEnabled() ) {
&main::Output(
"\tcopy \"\$(EPOCBLD$Bld)\\$Trg\" \"\$(EPOCTRG$Bld)\\$FeatureVariantBaseTrg.sym\"\n"
);
}
}
elsif ($Bld=~/^UDEB$/o) {
&main::Output(
"\tcopy \"\$(EPOCBLD$Bld)\\$Trg\" \"\$(EPOCTRG$Bld)\\$FeatureVariantBaseTrg.sym\"\n"
);
}
if (&main::CompressTarget) {
&main::Output(
"\telftran $PlatOpt{Elftran} -version ", &Genutl_VersionToUserString(%Version), " -sid ", &main::SecureId(), " ", " -nocompress "
);
}
else {
if(&main::CompressTargetMode==NOCOMPRESSIONMETHOD){
&main::Output(
"\telftran $PlatOpt{Elftran} -version ", &Genutl_VersionToUserString(%Version), " -sid ", &main::SecureId(), " "
);
}
elsif(&main::CompressTargetMode==INFLATECOMPRESSIONMETHOD){
&main::Output(
"\telftran $PlatOpt{Elftran} -version ", &Genutl_VersionToUserString(%Version), " -sid ", &main::SecureId(), " ", " -compressionmethod deflate"
);
}
elsif(&main::CompressTargetMode==BYTEPAIRCOMPRESSIONMETHOD){
&main::Output(
"\telftran $PlatOpt{Elftran} -version ", &Genutl_VersionToUserString(%Version), " -sid ", &main::SecureId(), " ", " -compressionmethod bytepair"
);
}
}
if (&main::IsDebuggable eq DEBUGGABLE) {
&main::Output(
' -debuggable '
);
}
if (&main::SmpSafe) {
&main::Output(
' -smpsafe'
);
}
if (&main::IsDebuggable eq DEBUGGABLE_UDEBONLY) {
if ($Bld=~/^UDEB$/o) {
&main::Output(
' -debuggable '
);
}
}
# change - exexps are allowed data, but they look like dlls to elftran....
if (&main::AllowDllData || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o) {
&main::Output(
' -allow'
);
}
if (not &main::CallDllEntryPoints ) {
&main::Output(
' -nocall'
);
}
if (&main::DataLinkAddress) {
&main::Output(
' -datalinkaddress ',&main::DataLinkAddress
);
}
if (&main::FixedProcess) {
&main::Output(
' -fixed'
);
}
if (&main::HeapSize) {
my %HeapSize=&main::HeapSize;
&main::Output(
' -heap ',$HeapSize{Min},' ',$HeapSize{Max}
);
}
if (&main::ProcessPriority) {
&main::Output(
' -priority ',&main::ProcessPriority
);
}
if (&main::StackSize) {
&main::Output(
' -stack ',&main::StackSize
);
}
if (&main::CodePagingTargetMode == UNPAGED) {
&main::Output(
' -codepaging unpaged'
);
}
elsif (&main::CodePagingTargetMode == PAGED) {
&main::Output(
' -codepaging paged'
);
}
if (&main::DataPagingTargetMode == UNPAGED) {
&main::Output(
' -datapaging unpaged'
);
}
elsif (&main::DataPagingTargetMode == PAGED) {
&main::Output(
' -datapaging paged'
);
}
&main::Output(
"\\\n\t\t"
);
my $i=1;
foreach (@UidList) {
&main::Output(
" -uid$i $_"
);
$i++;
}
if(&main::VendorId) {
&main::Output(
' -vid ',&main::VendorId
);
}
&main::Output(
"\\\n\t\t"
);
&main::Output(
' -fpu ',$floatingpointmodel
);
&main::Output(
' -capability ',&main::Capability
);
if($NamedSymLkup) {
&main::Output(
' -sym_name_lkup'
);
}
&main::Output(
"\\\n\t\t"
);
&main::Output(
" \"\$(EPOCBLD$Bld)\\$Trg\""
);
&main::Output(
"\\\n\t\t"
);
&main::Output(
" \"\$\@\" \n"
);
&main::Output(
"\n"
);
}
elsif ($BasicTrgType=~/^LIB$/o) {
&main::Output(
"\tarmar ${oP}create \$(EPOCSTATLINK$Bld)\\$Trg ${oP}via $objectsViaFile\n"
);
}
&main::Output(
"\n"
);
# add static lib into the object via file
my $libViaFiles=$objectFiles;
if (@StatLibList) {
foreach (@StatLibList) {
$libViaFiles.= &main::RelPath."$_ \n";
}
&main::CreateExtraFile($objectsViaFile, $libViaFiles);
}
# TARGET *.IN
#------------
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseTrg.in"), ": \$(OBJECTS$Bld)\n",
"\t$Link $linkerDebugOpt ${oP}partial \\\n",
"\t\t-o \$\@ \\\n",
"\t\t${oP}via $objectsViaFile\n\n",
);
# reorder the .DEF file taking frozen exports into account if there are any
if ($BasicTrgType=~/^DLL$/o || $TrgType=~/^EXEXP$/o || $TrgType=~/^EXEDLL$/o || $NamedSymLkup) {
# TARGET *.EXP
#------------
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$ExportLibrary.exp"), ": \$(EPOCBLD$Bld)\\$BaseTrg.in"
);
# if project is frozen, makedef (and hence the .exp file) are dependent upon it
unless (&main::ExportUnfrozen) {
if (-e $DefFile) { # effectively "if project frozen ..."
&main::Output(" $DefFile");
}
}
&main::Output(
"\n\tperl -S elf2inf.pl -o \$(EPOCBLD$Bld)\\$ExportLibrary.inf \\\n",
"\t\t\$\<",
"\n\tperl -S makedef.pl $AbsentSubst -Inf \$(EPOCBLD$Bld)\\$ExportLibrary.inf \\\n"
);
if (!$DefFile || $NoExportLibrary) {
&main::Output( "\t\t-ignore_unfrozen_noncallable \\\n" );
}
if (SysTrg()) {
&main::Output( "\t\t-SystemTargetType \\\n" );
}
if (-e $DefFile) { # effectively "if project frozen ..."
&main::Output(
"\t\t-Frzfile \"$DefFile\" \\\n"
);
}
if($NamedSymLkup && !$DefFile){
# For an EXE with named lookup, suppress the 'unfrozen exports' makedef warnings.
&main::Output(
"\t\t-ignore_unfrozen_exports \\\n",
);
}
# freeze ordinals, a maximum of 2, for polymorphic dlls
my $Ordinal;
my $Num=1;
foreach $Ordinal (&main::Exports) {
&main::Output( "\t\t-$Num $Ordinal \\\n" );
$Num++;
}
my $theDefFile = "\$(EPOCBLD$Bld)\\$ExportLibrary.def";
$theDefFile = $DefFile if (-e $DefFile && !&main::ExportUnfrozen);
&main::Output(
"\t\t\"\$(EPOCBLD$Bld)\\$ExportLibrary.def\"\n",
"\tcopy \"\$(EPOCBLD$Bld)\\$ExportLibrary.def\" \"\$(EPOCBLD)\\$ExportLibrary.def\"\n",
"\tdef2dll.bat $AbsentSubst \\\n\t\t--path=\$(EPOCBLD$Bld) \\\n\t\t--bldpath=\$(EPOCBLD$Bld) \\\n\t\t--export=$ExportLibrary \\\n",
"\t\t--deffile=$theDefFile \\\n\t\t--linkAs=$LinkAs \\\n\t\t$InterWorking $symNameLkupOpt\n"
);
}
&main::Output( "\n" );
}
# Set to 1 if multifile compilation wanted
my $domultifile = 0;
sub DoMultiFile () {
return $ENV{RVCTMultiFile} if (defined $ENV{RVCTMultiFile});
return $domultifile;
}
my %CompilationGroups = ();
sub InitMultiFileCompilation() {
# Do preparatory work for multifile compilation
my $SourceStructRef=&main::SourceStructRef;
# We sort the source files by path and extension. These form natural groups to compile together.
my %PathToSourceMap = ();
foreach my $SourceRef (@$SourceStructRef) {
my $SrcFile = $$SourceRef{CurFile};
my $Ext = &main::Path_Split('Ext', $SrcFile);
push @{$PathToSourceMap{$$SourceRef{SrcPath}}{$Ext}}, $SrcFile;
}
# Now we split each group into sets of 10.
foreach my $SrcPath (keys %PathToSourceMap) {
foreach my $Ext (keys %{$PathToSourceMap{$SrcPath}}) {
my @FileList;
my @ObjectList;
my @SourceList;
my $NumToGo = 10;
foreach my $File (@{$PathToSourceMap{$SrcPath}{$Ext}}) {
my $base = &main::Path_Split('Base', $File);
my $cia = ($Ext =~ /cia/i);
$base .= "_" if $cia;
push @FileList, $File;
push @ObjectList, "$base.o";
# this gives us our source files xxx
push @SourceList, $cia ? "$base.cpp" : "$SrcPath$base$Ext";
$NumToGo--;
unless ($NumToGo) {
# Use the last file as the key. This means e.g that all the dependency
# info will have been generated for the earlier files in the list
push @{$CompilationGroups{$FileList[$#FileList]}{Sources}}, @SourceList;
push @{$CompilationGroups{$FileList[$#FileList]}{Objects}}, @ObjectList;
$NumToGo = 10;
undef @FileList;
undef @ObjectList;
undef @SourceList;
}
}
push @{$CompilationGroups{$FileList[$#FileList]}{Sources}}, @SourceList;
push @{$CompilationGroups{$FileList[$#FileList]}{Objects}}, @ObjectList;
}
}
# debug print out
if (0) {
foreach my $keyfile (keys %CompilationGroups) {
print "$keyfile :\n";
foreach my $class (keys %{$CompilationGroups{$keyfile}}) {
print "\t$class:\n\t\t";
print join " ", @{$CompilationGroups{$keyfile}{$class}}, "\n";
}
}
}
}
sub PMStartSrcList {
&main::Output(
"# SOURCES\n",
"\n"
);
InitMultiFileCompilation() if DoMultiFile();
}
sub PMBitMapBld {
&Generic_BitMapBld;
}
sub PMResrcBld {
&Generic_ResrcBld;
}
sub PMAifBld {
&Generic_AifBld;
}
sub PMStartSrc {
my $Src=&main::Src;
&main::Output(
"# Source $Src\n",
"\n"
);
}
sub PMSrcDepend {
my @DepList=&main::DepList;
return if (@DepList == 0);
my @BldList=&main::BldList;
my $BaseSrc=&main::BaseSrc;
my $ExtSrc=&main::ExtSrc;
my $BaseObj=$BaseSrc;
my $cia = 0;
if ($ExtSrc =~ /cia/i ) {
$cia = 1;
$BaseObj .= '_';
}
foreach (@BldList) {
&main::Output(
&Generic_Quote("\$(EPOCBLD$_)\\$BaseSrc.pre"), " ",
&Generic_Quote("\$(EPOCBLD$_)\\$BaseObj.cpp"), " ",
) if $cia;
&main::Output(
&Generic_Quote("\$(EPOCBLD$_)\\$BaseSrc.lis"), " ",
&Generic_Quote("\$(EPOCBLD$_)\\$BaseObj.o"), " \\\n",
);
}
&main::Output(
":"
);
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\$_\)", @DepList);
&main::Output(
"\n",
"\n"
);
}
sub PMSrcBldDepend {
my @DepList=&main::DepList;
return if (@DepList == 0);
my $Bld=&main::Bld;
my $BaseSrc=&main::BaseSrc;
my $ExtSrc=&main::ExtSrc;
my $BaseObj=$BaseSrc;
my $cia = 0;
if ($ExtSrc =~ /cia/i ) {
$cia = 1;
$BaseObj .= '_';
}
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.cpp"), " ",
) if $cia;
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseObj.o"), " :",
);
PrintList("\' \\\n\t\'\.\&Generic_Quote\(\$_\)", @DepList);
&main::Output(
"\n",
"\n"
);
}
my $curdrive = "x";
sub quoted_path
{
my ($arg) = @_;
return "\"$arg\"" if ($arg !~ /^\\[^\\]/); # not an absolute path
if ($curdrive eq "x")
{
$curdrive="";
$curdrive=$1 if (cwd =~ /^(.:)/);
}
return "\"$curdrive$arg\"";
}
sub PMPrefixFile
{
my $IncPath = &main::EPOCIncPath;
return quoted_path(&Generic_Quote("$IncPath"."rvct\\rvct.h"));
}
my $preinclude = "--preinclude \$(EPOCINC)\\rvct\\rvct.h";
my $edg_preinclude = "-I \$(EPOCINC)\\RVCT${RVCTVersion} --preinclude edg_rvct${RVCTVersion}.h";
sub SelectLangOptions {
my ($Ext) = @_;
if ($Ext=~/^.cpp$/) {
# In case of function call logger, the preinclude file is passed to the function call logger
# hence it is not required to pass the same file to the compiler.
return "--cpp " if ($Function_Call_Logger);
return "--cpp $preinclude ";
}
if ($Ext=~/^.cia$/) {
return "--cpp ";
}
if ($Ext=~/^.c$/) {
if($CompilerOption =~/--cpp/) {
#Function Call Logger
return "--cpp " if ($Function_Call_Logger);
return "--cpp $preinclude ";
}
else {
#Function Call Logger
return "--c90 " if ($Function_Call_Logger);
return "--c90 $preinclude ";
}
}
# To support .cc, .cxx, .c++ file extensions for Open Environment
elsif ($Ext=~/^(.cc|.cxx|.c\+\+)$/) {
#Function Call Logger
return "--cpp " if ($Function_Call_Logger);
return "--cpp $preinclude ";
}
return '';
}
sub PMEndSrcBld {
# Generate multifile compilation stuff if needed.
if (DoMultiFile()) {
MultiFileEndSrcBld();
return;
}
my $ABI=&main::ABI;
my $Plat=&main::Plat;
my $BaseSrc=&main::BaseSrc;
my $Bld=&main::Bld;
my $Src=lc &main::Src;
my $SrcPath=&main::Path_Chop(&main::SrcPath);
my $Ext = &main::Path_Split('Ext', $Src);
my $BaseTrg=&main::BaseTrg;
my $BldPath = &main::BldPath;
$Src = ucfirst $Src if ($Ext !~ /\.(cpp|c)$/);
my $LangOptions = &SelectLangOptions($Ext);
# support for auto 'translated' ASM
my $AsmFilep = $AsmFiles{$Src};
# Logger Ouput filename
my $Logger_Output = lc ($BaseSrc) . ".int.cpp";
my $LstExt ;
if($Plat =~ /^(ARMV[6-9])/i){
$LstExt = $1 ;
}
else{
$LstExt = $ABI;
}
my $lfboption = LinkerFeedBackOption();
#Function Call Logger
my $FC_Logger_Option=" --wchar_t_keyword --microsoft_version=1300 --dictionary_file_name $BldPath$BaseTrg.txt --diag_suppress 66,161,611,654,815,830,997,1152,1300,1390";
if ($AsmFilep || $Ext =~ /cia/i) {
&main::Output(
# compile the translated, preprocessed source
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.o"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
"\t\@echo $Src\n",
"\t\$(ARMCC$Bld) $lfboption$LangOptions -J $SrcPath \$(INCDIR) -o \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp\n",
"\n",
# rule to translate the preprocessed source
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), "\n",
"\ttranasm.bat -n -s -o=\$\@ \$(EPOCBLD$Bld)\\$BaseSrc.pre\n",
"\n",
# rule to preprocess the source
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\$(ARMCC$Bld) -D__CIA__ -E $preinclude $LangOptions -J $SrcPath \$(INCDIR) $SrcPath\\$Src -o \$\@ \n",
# generate an assembly listing target too
"LISTING$Bld$BaseSrc\_ : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), "\n",
"\t", &Generic_CopyAction("$SrcPath\\$BaseSrc\_.$LstExt.lst"),
"\n",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
"\t\$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp\n",
"\n"
);
} else {
#If Function Call logging is enabled, add call to function call logger
if ($Function_Call_Logger) {
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o"),
" : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$Logger_Output"),
"\n",
"\t\@echo $Logger_Output\n",
"\t\$(ARMCC$Bld) $lfboption$LangOptions -J $SrcPath \$(INCDIR) -o \$\@ \$(EPOCBLD$Bld)\\$Logger_Output\n",
"\n",
# generate an assembly listing target too
"LISTING$Bld$BaseSrc : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), "\n",
"\t", &Generic_CopyAction("$SrcPath\\$BaseSrc.$LstExt.lst"),
"\n",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " : ",
&Generic_Quote("$SrcPath\\$Logger_Output"), "\n",
"\t\$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ \$(EPOCBLD$Bld)\\$Logger_Output \n",
"\n"
);
#Call to Function Call Logger
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$Logger_Output"), " : ",
&Generic_Quote("$SrcPath\\$Src"),
"\n",
"\t \@echo $Logger_Output\n",
"\t \$(FCLOGGER$Bld) $lfboption$edg_preinclude \\\n",
"\t -I $SrcPath \\\n",
"\t \$(INCDIR_FCLOGGER) $FC_Logger_Option \\\n",
"\t --gen_c_file_name \$\@ $SrcPath\\$Src\n",
"\n\n",
);
}
else {
&main::Output(
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.o"), " : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\@echo $Src\n",
"\t\$(ARMCC$Bld) $lfboption$LangOptions -J $SrcPath \$(INCDIR) -o \$\@ $SrcPath\\$Src\n",
"\n",
# generate an assembly listing target too
"LISTING$Bld$BaseSrc : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), "\n",
"\t", &Generic_CopyAction("$SrcPath\\$BaseSrc.$LstExt.lst"),
"\n",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ $SrcPath\\$Src \n",
"\n"
);
#Compiler wrapper support starts
if($IsCompilerWrapperOption)
{
my $Platcmpwrap=&main::Plat;
&main::Output(
"COMPWRAP$Bld$BaseSrc : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\@echo Analysing $Src\n",
"\t\$(COMPWRAP) \$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ $SrcPath\\$Src \n",
"\n"
);
}
#Compiler wrapper support ends
}
}
}
my $MFVarN = 0;
sub MultiFileEndSrcBld {
my $ABI=&main::ABI;
my $BaseSrc=&main::BaseSrc;
my $Bld=&main::Bld;
my $KeyFile = &main::Src;
my $Src=ucfirst lc $KeyFile;
my $SrcPath=&main::Path_Chop(&main::SrcPath);
my $Ext = &main::Path_Split('Ext', $Src);
my $LangOptions = &SelectLangOptions($Ext);
# support for auto 'translated' ASM
my $AsmFilep = $AsmFiles{$Src};
my $lfboption = LinkerFeedBackOption();
if ($AsmFilep || $Ext =~ /cia/i) {
if ($CompilationGroups{$KeyFile}) {
# compile the translated, preprocessed source
&main::Output( "OBJECTS$MFVarN = ");
foreach my $obj (@{$CompilationGroups{$KeyFile}{Objects}}) {
&main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$obj"), " ");
}
&main::Output( "\n\n");
&main::Output( "SOURCES$MFVarN = ");
foreach my $src (@{$CompilationGroups{$KeyFile}{Sources}}) {
&main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$src", " "));
}
&main::Output( "\n\n");
&main::Output( "\$(OBJECTS$MFVarN) : \$(SOURCES$MFVarN) \n");
&main::Output(
"\t\@echo Compiling \$(SOURCES$MFVarN)\n",
"\t\$(ARMCC$Bld) -J $SrcPath \$(INCDIR) $lfboption\\\n",
"\t\t$LangOptions -o \$\@ --multifile \$(SOURCES$MFVarN)"
);
&main::Output( "\n\n");
$MFVarN++;
}
&main::Output(
# rule to translate the preprocessed source
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), "\n",
"\ttranasm.bat -n -s -o=\$\@ \$(EPOCBLD$Bld)\\$BaseSrc.pre\n",
"\n",
# rule to preprocess the source
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.pre"), " : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\$(ARMCC$Bld) -D__CIA__ -E $preinclude $LangOptions -J $SrcPath \$(INCDIR) $SrcPath\\$Src -o \$\@ \n",
# generate an assembly listing target too
"LISTING$Bld$BaseSrc\_ : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), "\n",
"\t", &Generic_CopyAction("$SrcPath\\$BaseSrc\_.$LstExt.lst"),
"\n",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.lis"), " : ",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc\_.cpp"), "\n",
"\t\$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ \$(EPOCBLD$Bld)\\$BaseSrc\_.cpp\n",
"\n"
);
} else {
if ($CompilationGroups{$KeyFile}) {
# compile the source
&main::Output( "OBJECTS$MFVarN = ");
foreach my $obj (@{$CompilationGroups{$KeyFile}{Objects}}) {
&main::Output( &Generic_Quote("\\\n\t\$(EPOCBLD$Bld)\\$obj"), " ");
}
&main::Output( "\n\n");
&main::Output( "SOURCES$MFVarN = ");
foreach my $src (@{$CompilationGroups{$KeyFile}{Sources}}) {
&main::Output( &Generic_Quote("\\\n\t$src"), " ");
}
&main::Output( "\n\n");
&main::Output( "\$(OBJECTS$MFVarN) : \$(SOURCES$MFVarN) \n");
&main::Output(
"\t\@echo Compiling \$(SOURCES$MFVarN)\n",
"\t\$(ARMCC$Bld) -J $SrcPath \$(INCDIR) $lfboption\\\n",
"\t\t$LangOptions -o \$\@ --multifile \$(SOURCES$MFVarN)"
);
&main::Output( "\n\n");
$MFVarN++;
}
# generate an assembly listing target too
&main::Output(
"LISTING$Bld$BaseSrc : ", &Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), "\n",
"\t", &Generic_CopyAction("$SrcPath\\$BaseSrc.$LstExt.lst"),
"\n",
&Generic_Quote("\$(EPOCBLD$Bld)\\$BaseSrc.lis"), " : ",
&Generic_Quote("$SrcPath\\$Src"), "\n",
"\t\$(ARMCC$Bld) $LangOptions -S -J $SrcPath \$(INCDIR) -o \$\@ $SrcPath\\$Src \n",
"\n"
);
}
}
sub PMEndSrc {
&main::Output(
"\n",
"\n"
);
}
sub PMEndSrcList {
# Deal with accumulated MAKEDIRS etc.
&Generic_End;
}
sub PMSupportsFeatureVariants
{
return 1;
}
1;