--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sbsv1/abld/e32util/featurevariantmap.pm Fri Jun 25 17:29:25 2010 +0800
@@ -0,0 +1,505 @@
+# Copyright (c) 2007-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:
+#
+
+# modified start: makefile improvement
+use Cwd;
+# modified end: makefile improvement
+use Digest::MD5;
+use File::Basename;
+
+package featurevariantmap;
+our $verbose = 0;
+
+my $featureListDir = "$ENV{EPOCROOT}epoc32\\include\\variant\\featurelists";
+
+sub LoadFeatureList
+ {
+ my %featurehash;
+
+ # Try and find the feature master list folder
+ if (!opendir DIR, $featureListDir)
+ {
+ print "\nERROR: Failed to open feature list directory $featureListDir: $!";
+ return \%featurehash;
+ }
+
+ # Load the list of features from each file
+ foreach my $file ( grep(/\.txt$/i, readdir DIR) )
+ {
+ $file = "$featureListDir\\$file";
+ print "Reading feature list from $file\n" if ($verbose);
+
+ if (!open IN, $file)
+ {
+ print "\nERROR: Failed to read feature list $file: $!";
+ }
+ else
+ {
+ while(my $line = <IN>)
+ {
+ $line =~ s/\/\/.+$//; # Get rid of c++ style comments
+ if ($line =~ /(\S+)/)
+ {
+ $featurehash{$1} = $file;
+ }
+ }
+ close IN;
+ }
+
+ }
+ closedir DIR;
+ return \%featurehash;
+ }
+
+sub ValidFeature
+{
+ our $featurelist;
+ my $name = shift;
+
+ $featurelist = LoadFeatureList() if !$featurelist;
+ return exists $featurelist->{$name};
+# modified start: makefile improvement
+}
+sub GetVariantListFromVmap
+{
+ my $obj = shift;
+ my $vmapfile = shift;
+ if(open(VMAP, "<$vmapfile"))
+ {
+ my @varlist;
+ while(<VMAP>)
+ {
+ if(/^\w{32}\s+(\w+)/)
+ {
+ push @varlist, $1;
+ }
+
+ }
+ close(VMAP);
+ return @varlist;
+ }
+ close(VMAP);
+ return;
+
+}
+sub CheckOldVmapFile
+{
+ my $thisObj = shift;
+ my $vmapfile = shift;
+ my $varRef = shift;
+ my $buildincludes = $$varRef{BUILD_INCLUDES};
+ my $parents = $$varRef{PARENTS};
+ my $children = $$varRef{CHILDREN};
+ my $varianthrh = $$varRef{VARIANT_HRH};
+ my %variantMacrolist;
+ my $Options = "-dM -undef -nostdinc -+";
+ my $Drive = $1 if (Cwd->cwd =~ /^(.:)/);
+ if($buildincludes)
+ {
+ foreach (@$buildincludes)
+ {
+ $Options .= " -I \"".$Drive.$_."\"";
+ }
+ }
+ if($varianthrh)
+ {
+ $Options .= " \"".$Drive.$varianthrh."\"";
+ }
+ if(open(CPP, "cpp $Options 2>&1 |"))
+ {
+ while(<CPP>)
+ {
+ my ( $key, $value );
+ if (/^#define (\w+(?:\([^\)]*\))?)(?:\s(\S.*?))?\s*$/)
+ {
+ my $tmpKey = $1;
+ my $tmpValue = $2;
+ $tmpValue =~ s/,/\\,/g;
+ ($key, $value ) = ( $tmpKey, $tmpValue ? "\'$tmpValue\'" : 'defined' );
+ }
+ if ($key && ValidFeature($key))
+ {
+ $variantMacrolist{$key} = $value;
+ }
+ }
+ if(!close(CPP))
+ {
+ print "Incomplete pre-precess of $varianthrh \n";
+ }
+ }
+ my $findReusedKey = 1;
+ my %vmapfeatureinfo;
+ my $keyhash;
+ my $macroList;
+ if(open(VMAP, "<$vmapfile"))
+ {
+ while(<VMAP>)
+ {
+ if(/^\w{32}\s+(\w+)/)
+ {
+ $findReusedKey = 1;
+ s/(^\w{32})\s+\w+\s+//;
+ $keyhash = $1;
+ my @feature = split(/(?<=[^\\]),/, $_);
+ foreach my $value (@feature)
+ {
+ if($value =~ /([^\s]*)\s*=\s*(.*)/)
+ {
+ $vmapfeatureinfo{$1} = $2;
+ }
+ }
+ foreach my $key (sort keys %vmapfeatureinfo)
+ {
+
+ if(($vmapfeatureinfo{$key} eq "undefined") && (not(exists($variantMacrolist{$key}))))
+ {
+ $findReusedKey = 1;
+ }
+ elsif($vmapfeatureinfo{$key} eq $variantMacrolist{$key})
+ {
+ $findReusedKey = 1;
+ }else
+ {
+ $findReusedKey = 0;
+ last;
+ }
+ }
+ if( $findReusedKey == 1)
+ {
+ $macroList = $_;
+ last;
+ }
+ undef(%vmapfeatureinfor);
+ undef($keyhash);
+ }
+ }
+ }
+ if($findReusedKey == 1)
+ {
+ return ($keyhash, $macroList);
+ }
+ else
+ {
+ return;
+ }
+}
+# modified end: makefile improvement
+
+# Usage: featurevariantmap->Hash(\@sources, \%var)
+#
+# Generate a hash value from the source files for a target using the
+# given feature variant data.
+#
+# \@sources - list of source files (full path)
+# \%var - variant data (from featurevariantparser->GetVariant)
+#
+# returns the hash value, or "" if an error occurs.
+
+sub Hash
+{
+ my $thisObj = shift;
+ my @result = $thisObj->HashAndFeatures(@_);
+ return $result[0];
+}
+
+# Usage: featurevariantmap->HashAndFeatures(\@sources, \%var)
+#
+# Generate a hash value from the source files for a target using the
+# given feature variant data.
+#
+# \@sources - list of source files (full path)
+# \%var - variant data (from featurevariantparser->GetVariant)
+#
+# returns a list of two entries [0] the hash value, or "" if an error occurs [1] A string of macros tested or affecting the code
+
+sub HashAndFeatures
+{
+ my $thisObj = shift;
+ my $srcRef = shift;
+ my $varRef = shift;
+
+ return "" if (!$srcRef || !$varRef);
+ return "" if (!$$varRef{'VALID'});
+
+ # get the pre-processing options
+ my $pre = $$varRef{'PREINCLUDE'};
+ my $inc = $$varRef{'BUILD_INCLUDES'};
+ my $mac = $$varRef{'MACROS'};
+
+ # Pass -dU option to get list of macros affecting the code
+ my $options = "-dU -undef -nostdinc -+";
+
+ if ($pre) # pre-include file
+ {
+ $options .= " -include \"$pre\"";
+ }
+
+ if ($inc) # include directories
+ {
+ foreach (@$inc)
+ {
+ $options .= " -I \"$_\"";
+ }
+ }
+
+ if ($mac) # macro definitions
+ {
+ foreach (@$mac)
+ {
+ $options .= " -D$_";
+ }
+ }
+
+ my %testedMacrosHash;
+
+ # Macros that affect the mmp file also affect the variant - so add them to the list
+ foreach my $key ( keys %{ $$varRef{MMPTESTED} } )
+ {
+ $testedMacrosHash{$key} = $$varRef{MMPTESTED}->{$key} if (ValidFeature($key));
+ }
+
+ foreach my $src (@$srcRef)
+ {
+ my $options = "-I " . File::Basename::dirname($src) . " $options";
+
+ print "cpp $options $src\n" if ($verbose);
+
+ if (open(CPP, "cpp $options $src 2>&1 |"))
+ {
+ while (<CPP>)
+ {
+ print $_ if ($verbose && /No such file/);
+
+ # Scan for #define or #undef generated for -dU
+ my ( $key, $value );
+ if (/^#define (\w+(?:\([^\)]*\))?)(?:\s(\S.*?))?\s*$/)
+ {
+# modified start: makefile improvement
+ my $tmpKey = $1;
+ my $tmpValue = $2;
+ $tmpValue =~ s/,/\\,/g;
+ ( $key, $value ) = ( $tmpKey, $tmpValue ? "\'$tmpValue\'" : 'defined' );
+# modified end: makefile improvement
+ }
+ elsif (/^#undef (.+)$/)
+ {
+ ( $key, $value ) = ( $1, 'undefined' );
+ }
+
+ if ($key && ValidFeature($key))
+ {
+ # Warn the user if a macro appears to have changed value - shouldn't really happen
+ # Feature macros should only be set in platform HRH files and not in the code
+ if (exists $testedMacrosHash{$key} && $testedMacrosHash{$key} ne $value)
+ {
+ print "WARNING: Feature macro $key redefined from $testedMacrosHash{$key} to $value\n";
+ }
+
+ # Store the macro details
+ $testedMacrosHash{$key} = $value;
+ }
+ }
+ if (!close(CPP))
+ {
+ # this probably means that a rsg file was included
+ # that hasn't been generated yet.
+ print "Incomplete pre-process of $src\n" if ($verbose);
+ }
+ }
+ else
+ {
+ print "ERROR: Could not pre-process $src\n";
+ return "";
+ }
+ }
+
+ # Now generate the tested macros string
+ my $testedMacros = '';
+ foreach my $key ( sort keys %testedMacrosHash )
+ {
+ $testedMacros .= ',' if $testedMacros;
+ $testedMacros .= "$key=$testedMacrosHash{$key}";
+ }
+
+ print "Tested feature list: $testedMacros\n" if $verbose;
+ return ( Digest::MD5::md5_hex($testedMacros), $testedMacros );
+}
+
+# Usage: featurevariantmap->Save("my.dll", "1234", "myvar", \@hints)
+#
+# Write a hash value for a target into the target.vmap file along
+# with some optional hints data.
+#
+# "my.dll" - the target (full path)
+# "1234" - the hash value (32 character hex number)
+# "myvar" - the feature variant name
+# \@hints - optional list of extra strings (eg. "FEATUREVARIANT")
+#
+# returns 0 if OK and non-zero if an error occurs.
+
+sub Save
+{
+ my $thisObj = shift;
+ my $binName = shift;
+ my $keyValue = shift;
+ my $varName = shift;
+ my $features = shift;
+ my $hintRef = shift;
+
+ # read the current data first if the .vmap file already exists
+# modified by SV start: makefile improvement
+ my $vmapFile = "$binName.$varName.vmap";
+ my @lines;
+ my $tmpinfo = "$keyValue $varName";
+ $tmpinfo .= " $features" if $features;
+ if (open(VMAP, $vmapFile))
+ {
+ my @tmp=<VMAP>;
+ if (grep (/$tmpinfo/, @tmp)){
+ close(VMAP);
+ return 0;
+ }
+ else {
+ foreach (@tmp)
+ {
+ if (/^\w{32}\s+(\w+)/)
+ {
+ push(@lines, $_) unless (uc($1) eq uc($varName));
+ }
+ }
+ close(VMAP);
+ }
+ }
+# modified by SV end: makefile improvement
+
+ # write the new data to the .vmap file
+ if (!open(VMAP, ">$vmapFile"))
+ {
+ print "ERROR: Could not write VMAP to $vmapFile\n";
+ return 1;
+ }
+
+ # put the hints at the beginning
+ if ($hintRef)
+ {
+ foreach (@$hintRef)
+ {
+ print VMAP "$_\n";
+ }
+ }
+
+ # then the "key var" pairs
+ foreach (@lines)
+ {
+ print VMAP $_;
+ }
+ print VMAP "$keyValue $varName";
+ print VMAP " $features" if $features;
+ print VMAP "\n";
+
+ close(VMAP);
+ return 0;
+}
+
+# Usage: featurevariantmap->Find("my.dll", "myvar")
+#
+# Look for a binary using its "final" name. We will use the feature
+# variant map and the feature variant name to deduce the "variant"
+# binary name and test for its existence.
+#
+# "my.dll" - the final target (full path)
+# "myvar" - the feature variant name
+#
+# returns the file name if found, or "" otherwise.
+
+sub Find
+{
+ my $thisObj = shift;
+ my $binName = shift;
+ my $varName = shift;
+
+ # look for the vmap file
+# modified by SV start: makefile improvement
+ my $vmapFile = "$binName.$varName.vmap";
+# modified by SV end: makefile improvement
+
+ if (-e $vmapFile)
+ {
+ my $key = $thisObj->GetKeyFromVMAP($varName, $vmapFile);
+
+ if ($key)
+ {
+ $binName =~ /^(.*)\.([^\.]*)$/;
+ $binName = "$1.$key.$2";
+ }
+ else
+ {
+ print "ERROR: No \'$varName\' variant for $binName in $vmapFile\n";
+ return ""; # file not found
+ }
+ }
+
+ # check that the actual binary exists
+ if (-e $binName)
+ {
+ return $binName;
+ }
+ return ""; # file not found
+}
+
+# internal functions
+
+sub GetKeyFromVMAP
+ {
+ my $thisObj = shift;
+ my @res = $thisObj->GetDataFromVMAP(@_);
+ return $res[0];
+ }
+
+# Usage: featurevariantmap->GetDataFromVMAP("myvar", "mydll.vmap")
+#
+# Opens the vmap file indicated and returns the data for the requested variant
+#
+# "myvar" - the feature variant name
+# "my.vmap" - the final target vmap file (full path)
+#
+# Returns a list ( hash, features ) for the variant in the vmap or undef if not found
+
+sub GetDataFromVMAP
+{
+ my $thisObj = shift;
+ my $varName = shift;
+ my $fileName = shift;
+
+ if (!open(VMAP, $fileName))
+ {
+ print "ERROR: Could not read VMAP from $fileName\n";
+ return "";
+ }
+ while (<VMAP>)
+ {
+ chomp;
+ if (/(\w{32})\s+$varName\s+(.*)$/i or /(\w{32})\s+$varName$/i)
+ {
+ my ( $hash, $features ) = ( $1, $2 ? $2 : '' );
+ close(VMAP);
+ return ( $hash, $features );
+ }
+ }
+ close(VMAP);
+ return;
+}
+
+1;