Moving feature configuration out of the buildrom scope.
#
# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of the License "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:
# This package is to build rom image
#
use FindBin; # for FindBin::Bin
my $PerlLibPath; # fully qualified pathname of the directory containing our Perl modules
my $PerlEPOCPath;
BEGIN {
# check user has a version of perl that will cope
require 5.005_03;
# establish the path to the Perl libraries
$PerlLibPath = $FindBin::Bin;
# $PerlLibPath =~ s/\//\\/g;
$PerlLibPath .= "\\";
$PerlLibPath =~ s/\\/\//g;
$PerlEPOCPath = $ENV{EPOCROOT};
$PerlEPOCPath =~ s/\\/\//g;
$PerlEPOCPath .= "\/" unless $PerlEPOCPath =~ /\/$/;
$PerlEPOCPath .= "epoc32\/tools\/";
}
use lib $PerlEPOCPath."build/lib/";
use lib $PerlEPOCPath;
use lib $PerlLibPath;
use strict;
use romutl;
use romosvariant;
# Work out the relative path to the epoc32 directory
use Cwd;
use File::Basename;
# global variables specific to data drive image generation.
use File::Path ; # Module to provide functions to remove or create directories in a convenient way.
use File::Find;
use features;
use flexmodload; # To load modules dynamically
my $enforceFeatureManager = 0; # Flag to make Feature Manager mandatory if SYMBIAN_FEATURE_MANAGER macro is defined.
my $BuildromMajorVersion = 0 ;
my $BuildromMinorVersion = 2;
my $BuildromPatchVersion = 0;
my $outputoby = "output.oby" ;
sub print_usage {
# Option "-fm" will be supported instead of option "-f|fr" if SYMBIAN_FEATURE_MANAGER macro is defined.
my $featuresOptionUsage = "-f<featureuids> or\n".
" -fr=<featureuids> -- feature registry database XML file name\n";
if ($enforceFeatureManager) {
$featuresOptionUsage = "-fm=<featuredbfile> -- feature manager/feature registry database XML file name.\n".
" Multiple XML files can be passed seperated by commas.\n".
" -nofm=<featuresdatafile> -- don't generate features data file.\n".
" Instead use pre-built features data file.\n";
}
#........1.........2.........3.........4.........5.........6.........7.....
print <<USAGE_EOF;
FEATURECONFIGURATOR - feature configuration tool V$BuildromMajorVersion.$BuildromMinorVersion.$BuildromPatchVersion
Usage:
featureconfigurator [options] obyfile [obyfile2 ...]
Configurate features from *.iby/*.oby files and output a
consolidated obyfile for buildrom's use.
This is a front end of buildrom, which partly implements
functionalities of buildrom.
The available options are
-h -- Print this message
$featuresOptionUsage
-oby-charset=<charset> -- Used character set in which OBY was written
-k or -keepgoing -- Enable keepgoing,continue to config features
and create oby file.
-argfile=xxx -- Specify argument-file name containing list of
command-line arguments to featureconfigurator
-workdir=xxx -- Specify a directory for generated files.
The working directory will not be changed even this option is used.
-I<directory> -- Use <directory> for the referenced IBY/OBY files
-D<xxx> -- Define xxx for C++ preprocessor
-stdcpp -- Ignore symbian customized cpp and try to find
another cpp in the PATH.(for Windows only)
-cpp=<xxx> -- Use xxx as path of CPP preprocessor.
-o<xxx.oby> -- Output oby file name is set to xxx.oby
If this argument is not given, then output oby file is
"output.oby". output files are placed under workdir.
-s -- strict option, any missing files will stop buildrom
-v -- verbose
-noiby[=<n>] -- if n = 0, then create iby files, otherwise don't create iby files, "-noiby=0" is default
-w -- suppress cpp warnings.
USAGE_EOF
}
my $PerlEPOCPath = &get_epocroot()."epoc32\/tools\/"; # fully qualified pathname of the directory containing EPOC Perl modules
my $xmlrequired = 0; # assume xml required is false. Used to determine if xml
# modules should be loaded.
my @tempfiles;
my $preserve = 0; #flag to indicate if temporary files should be preserved
my $uppath="x"; # will be initialised when first needed
my $epocroot = &get_epocroot;
my @obyfiles;
my $cppargs = "-nostdinc -undef";
my $opt_k = 0;
my $opt_v = 0;
my $opt_w = 0 ;
my $strict = 0;
my $line;
my $errors = 0;
my $thisdir=cwd;
$thisdir=~s-\\-\/-go; # separator from Perl 5.005_02+ is forward slash
$thisdir.= "\/" unless $thisdir =~ /\/$/;
$thisdir =~ s-\/-\\-g if (&is_windows);
my $workdir = $thisdir ;
my $rominclude = $epocroot."epoc32\/rom\/include\/";
$rominclude = &get_epocdrive().$rominclude unless $rominclude =~ /^.:/;
$rominclude =~s-\\-\/-g;
my @xmlDBFile = ();
my $noiby = 0;
my @obydata;
my @featurefilearray; #2d array storing names and locations of feature files in each rom image
my @featureslist; #array of hashes, stores all the features which are to go into the feature files
my $featurefilecount=0; #counts number of feature files in each rom image
my $featurescount=0; #counts number of features
my $dir; # Stores the ROM image location of features.dat/featreg.cfg files
my $featurefilename; # Stores the name of feature file to be generated(i.e. "features.dat" or "featreg.cfg")
my $featuremanager = 0; #Flag to enable support for feature manager database XML file and to generate
# features data file.
my $noFeatureManager = 0; # Flag to stop the generation of features.dat file and use pre-built features.dat if provided.
my $preBuiltFeaturesDataFile = ''; # To store the name of pre-built features.dat file provided with "-nofm" option.
#Image Content XML file that supports specific feature to be added
my $image_content = undef;
#Feature list XML file that acts as database containing all features details
my $featureXml = undef;
my $customizedPlat = undef;
#Summary of files(both executables and data files) currently includes
# host and ROM file names,
# size of the file in ROM
# whether the file is hidden
# This option is added so that the above additional information is emitted by rombuild/rofsbuild tools
# only when supplied with this option so that the existing tools don't get affected.
my $logLevel="";
# Feature Variation modules and data
my %featureVariant;
my $opt_workdir = 0;
my $stdcpp = 0;
my $obycharset;
my $cppoption = 0;
my $preprocessor = "cpp";
sub is_fullpath {
my $path = shift ;
if (&is_windows) {
if( $path =~ /^[a-z]:/i) {
return 1 ;
}
elsif($path =~ /^\\/) {
return 1 ;
}
else {
return 0 ;
}
}
else {
return 1 if($path =~ /^\//) ;
return 0;
}
}
sub match_obyfile
{
my ($obyfile) = @_;
if (-f $obyfile)
{
push @obyfiles, $obyfile;
return 1;
}
# search for the oby file in the list of include directories
my @otherDirs = ($rominclude);
if ($featureVariant{'VALID'})
{
my $dirRef = $featureVariant{'ROM_INCLUDES'};
@otherDirs = @$dirRef if ($dirRef);
}
foreach my $dir (@otherDirs)
{
print "$dir/$obyfile\n" if ($opt_v);
if (-f "$dir/$obyfile")
{
push @obyfiles, "$dir/$obyfile";
return 1;
}
}
return 0;
}
# Subroutine to process parameter-file
sub parameterFileProcessor
{
my $paramFile = shift(@_);
my @paramFileParamaters = ();
my $fileOpenFlag = 1;
open FILE,"<", $paramFile or $fileOpenFlag = 0;
if(!$fileOpenFlag)
{
print "Error: Could not open parameter-file \"$paramFile\" for reading.\n";
return;
}
# Parse parameter-file and collect all the parameters in an array
while(my $line = <FILE>)
{
# Read the line till character ';'(used for providing comments in the file) or EOL
$line = $1 if ($line =~ /(.*);/);
# Split the parameters specified in a line based on white-spaces
my @paramaters = split(/(\s)/,$line);
my $flag = 0;
my $argWithQuotes='';
foreach my $value (@paramaters)
{
# If the parameter doesn't conatian double quotes then push it
# to the list of parameters.
if(($value !~ /\"/) && (!$argWithQuotes))
{
if ($value !~ /^\s*$/)
{
push @paramFileParamaters,$value;
}
}
# If the parameter is in the form -fm="faturedb.xml" then remove
# double quotes and push it to the list of parameters.
elsif(($value =~ /\".*\"/))
{
$value =~ s/\"//g;
push @paramFileParamaters,$value;
}
# If the parameter is in the form -fm="fature db.xml" then read
# the parameter starting from opening quote till the closing quote.
elsif( ($value =~ /\"/) && $argWithQuotes)
{
$argWithQuotes .= $value;
$argWithQuotes =~ s/\"//g;
push @paramFileParamaters,$argWithQuotes;
$argWithQuotes='';
}
else
{
$argWithQuotes .= $value;
}
}
}
close FILE;
if (!@paramFileParamaters)
{
print "Warning: No parameters specified in paramer-file \"$paramFile\".\n";
return;
}
my $paramFileFlag = 1;
# Invoke subroutine "process_cmdline_arguments" to process the parameters read from
# the parameter file.
&process_cmdline_arguments($paramFileFlag, @paramFileParamaters);
}
# Processes the command line arguments passed to buildrom tool
sub process_cmdline_arguments
{
my ($paramFileFlag, @argList);
if (defined @_) {
($paramFileFlag, @argList) = @_;
}
else {
if(scalar(@ARGV) == 0){
my @hrhMacros = &get_variantmacrolist;
$enforceFeatureManager = 1 if (grep /^SYMBIAN_FEATURE_MANAGER\s*$/, @hrhMacros);
print_usage();
exit 1;
}
@argList = @ARGV;
}
if (!defined $paramFileFlag) {
# Enforce Feature Manager if macro SYMBIAN_FEATURE_MANAGER is defined in the HRH file.
my @hrhMacros = &get_variantmacrolist;
$enforceFeatureManager = 1 if (grep /^SYMBIAN_FEATURE_MANAGER\s*$/, @hrhMacros);
# Process the parameters of parameter-file if passed.
foreach my $arg (@argList) {
if ($arg =~ /^-h/i) {
print_usage();
exit 1;
}
}
# Process the parameters of parameter-file if passed.
foreach my $arg (@argList) {
¶meterFileProcessor($1) if ($arg =~ /^-argfile=(.*)/) ;
}
}
# first searching argList for keepgoing option
my @newArgList = () ;
foreach my $arg (@argList) {
if ( $arg =~ /^-k$/i || $arg =~ /^-keepgoing$/i ) {
$opt_k = 1;
}
elsif ($arg =~ /^-s$/) {
$strict = 1;
}
elsif ($arg =~ /^-v$/) {
$opt_v =1;
}
elsif( $arg =~ /^-w$/) {
$opt_w = 1 ;
}
elsif ($arg =~ /^-workdir=(.*)/) {
$workdir = $1;
$workdir = $thisdir.$workdir unless(&is_fullpath($workdir)) ;
$workdir.= "\/" unless $workdir =~ /\/$/;
mkdir($workdir) unless (-d $workdir);
}else {
push @newArgList, $arg ;
}
}
foreach my $arg (@newArgList)
{
if ($arg =~ /^-argfile=(.*)/) {
¶meterFileProcessor($1) if (defined $paramFileFlag);
}
elsif ($arg =~ /^-DFEATUREVARIANT=(.*)/) {
my $varname = $1;
if ($varname =~ /^\.(.*)$/) {
# for testing, locate the VAR file in the current directory
%featureVariant = get_variant($1, ".");
}
else {
%featureVariant = get_variant($varname);
}
if (!$featureVariant{'VALID'}) {
print "FEATUREVARIANT $varname is not VALID\n";
$errors++;
}
if ($featureVariant{'VIRTUAL'}) {
print "FEATUREVARIANT $varname is VIRTUAL\n";
$errors++;
}
addDrivesToFeatureVariantPaths();
}
elsif ($arg =~ /^-[DI]/) {
$cppargs .= " $arg";
}
elsif ($arg =~/^-oby-charset=(.*)$/i) {
$obycharset = $1;
}
elsif($arg =~ /^-o(.*)/i) {
$outputoby = $1;
}
elsif ($arg =~ /^-noiby(=(\d))$/i ) {
if(!$1) {
$noiby = 1;
}
else {
if(!$2) {
print "Warning: No value for \"-noiby=\" option, use default.\n";
}
else {
$noiby = $2 ;
}
}
}
#Process feature manager database xml file
elsif($arg =~ /^-fm=(.*)/) {
if (!$enforceFeatureManager) {
print "Unknown arg: $arg\n";
$errors++;
next;
}
$featureXml = $1;
$xmlrequired = 1;
$featuremanager = 1;
if ($featureXml =~ /^$/) {
print "Error: No filename specified with \"-fm=\" option.\n";
}
else {
@xmlDBFile = split /,/,$featureXml if($noiby == 0);
}
}
elsif ($arg =~ /^-nofm(=(.*))?$/) {
if (!$enforceFeatureManager) {
print "Unknown arg: $arg\n";
$errors++;
next;
}
$noFeatureManager = 1;
if(!$2) {
print "Warning: No filename specified with \"-nofm=\" option, feature data file might not be included.\n";
}
else {
$preBuiltFeaturesDataFile = $2;
}
}
#Process feature registry database xml file
elsif($arg =~ /^-fr=(.*)/ || $arg =~ /^-f(.*)/) {
if ($enforceFeatureManager)
{
print "Error: Option \"-f|-fr\" is no longer supported.\n";
$errors++;
next;
}
$featureXml = $1;
$xmlrequired = 1;
print "Error: No filename specified with \"-f|-fr\" option.\n" if ($featureXml =~ /^$/) ;
}
elsif ($arg =~ /^-stdcpp$/i) {
if (&is_linux) {
print "Warning: option -stdcpp only apply for Windows\n";
}
if ($cppoption) {
print "Error: -stdcpp option and -cpp=xxx option cannot be used at the same time.\n";
exit (1);
}
$stdcpp = 1;
}
elsif ($arg =~ /^-cpp=(.*)/) {
if ($stdcpp) {
print "Error: -stdcpp option and -cpp=xxx option cannot be used at the same time.\n";
exit (1);
}
print "Warning: -cpp option has been set before. The previous configuration will be overwritten!\n" if ($cppoption);
$cppoption = 1;
$preprocessor = $1;
$preprocessor =~ s-\\-\/-g;
$preprocessor =~ s-EPOCROOT##\/?-$epocroot-g;
if (-d $preprocessor) {
$preprocessor .= "\/" unless $preprocessor =~ /\/$/;
$preprocessor .= "cpp";
}
}
elsif ($arg =~ /^-/) {
print "Unknown arg: $arg\n";
$errors++;
next;
}
else {
# It's an OBY file
next if (match_obyfile($arg));
next if (match_obyfile("$arg.oby"));
print "Cannot find oby file: $arg\n";
$errors++ if(!$opt_k);
}
}
return if (defined $paramFileFlag) ;
if (@obyfiles<1 ) {
print "Missing obyfile argument\n";
$errors++ if(!$opt_k);
}
if(defined($obycharset)) {
print "Warning: Ignoring not supportted charset $obycharset, local charset will be used as default!\n" unless($obycharset =~ /utf-?8/i);
}
if ($errors) {
print_usage();
exit 1;
}
if ($noFeatureManager && $featuremanager) {
print "Warning: Ignoring \"-nofm\" option, as both \"-nofm\" and \"-fm\" options are provided.\n";
$noFeatureManager = 0;
}
# Adding variant specific macros by including a HRH file
# (only required if no Feature Variant is used)
if (!$featureVariant{'VALID'}) {
my $variantMacroHRHFile = get_variantmacroHRHfile();
if($variantMacroHRHFile){
my $variantFilePath = split_path('Path',$variantMacroHRHFile);
$cppargs .= " -I " . &append_driveandquote($variantFilePath) . " -include " . &append_driveandquote($variantMacroHRHFile);
print "in cmd process $cppargs\n" if ($opt_v);
}
}
# load the required modules if xml is required
if ($xmlrequired == 1) {
load_featuresutil() if (defined ($featureXml));
}
}
#----------------------------------------------------------------------------------
# Preprocessing phase
#
# Concatentate the specified .oby files and pass them through cpp
# to get the raw ROM specification in tmp1.oby
sub preprocessing_phase
{
my $temp1OBYFile = $workdir."tmp1.oby";
unlink "$temp1OBYFile";
# Macro "ROM_FEATURE_MANAGEMENT" is defined when "-f|fr" or "-fm" is used
$cppargs .= " -w" if($opt_w) ;
$cppargs .= " -DROM_FEATURE_MANAGEMENT " if (defined ($featureXml));
# add pre-include file and include directories for feature variants
if ($featureVariant{'VALID'})
{
$cppargs .= " -I.";
my $incRef = $featureVariant{'ROM_INCLUDES'};
if ($incRef) {
foreach (@$incRef) {
$cppargs .= " -I \"$_\"";
}
}
my $HRH = $featureVariant{'VARIANT_HRH'};
$cppargs .= " -include \"$HRH\"" if ($HRH);
}
else {
# no feature variant so use the standard includes
$cppargs .= " -I. -I \"$rominclude\"";
}
$preprocessor = find_stdcpp() if ($stdcpp);
print "* $preprocessor -Wno-endif-labels -o $temp1OBYFile $cppargs\n" if ($opt_v);
is_existinpath("$preprocessor", romutl::DIE_NOT_FOUND);
$errors = 0;
open CPP, "| $preprocessor -Wno-endif-labels -o $temp1OBYFile $cppargs" or die "* Can't execute cpp";
foreach my $arg (@obyfiles) {
print CPP "\n#line 1 \"$arg\"\n";
if(open(OBY, $arg)) {
print "* reading $arg\n" if ($opt_v);
while ($line=<OBY>) {
print CPP $line;
}
close OBY;
}
else {
print STDERR "* Can't open $arg\n";
if(!$opt_k){
close CPP;
exit(1);
}
}
}
close CPP;
my $cpp_status = $?;
die "* cpp failed\n" if ($cpp_status != 0 || !-f "$temp1OBYFile");
if( defined ($image_content)) {
#Read the OBY file that was generated by the pre-processor
&ReadPreprocessedFile($temp1OBYFile);
# Check if the static dependencies of the OBY binaries are resolved.
&ImageContentHandler::UpdateObyBinaryStaticDep();
#Now append the files collected from cdfs.
&ImageContentHandler::GenObyFile($temp1OBYFile);
}
if($obycharset =~ /utf-?8/i) {
my $utf8file = $workdir."tmp1utf8.oby";
open INFILE, "<$temp1OBYFile" or die "* Can't open file $temp1OBYFile";
open CHARSETTRAN, "| charsettran -to=hostcharset > $utf8file" or die "* Can't execute charsetran";
while(<INFILE>) {
print CHARSETTRAN $_;
}
close CHARSETTRAN;
close INFILE;
unlink $temp1OBYFile or die "* Can't remove file $temp1OBYFile";
rename $utf8file, $temp1OBYFile or die "* Can't rename file $utf8file to file $temp1OBYFile";
}
open TMPOBY, "<$temp1OBYFile" or die "*cpp output can not be read.\n";
@obydata = <TMPOBY> ;
close TMPOBY;
}
sub load_featuresutil
{
&FlexLoad_ModuleL("featuresutil");
# Parse the feature database XML file
if(!&featuresutil::parseXMLDatabase($featureXml, $featuremanager, $strict))
{
$featureXml = undef;
exit(1) if($strict);
}
}
#----------------------------------------------------------------------------------
# Feature registry configuration file/Features data file generation phase
#
# If feature registry configuration files/features data files are required then creates these files for
# each ROM/ROFS image
#
sub featurefile_creation_phase
{
# Set the name and Rom Image location of feature file.
if ($enforceFeatureManager) {
# features data file location
$dir = "private\/10205054\/";
$featurefilename = "features.dat";
}
else {
# feature registry configuration file location
$dir = "private\/102744CA\/";
$featurefilename = "featreg.cfg";
}
my $onlysmrimage = 1 ;
foreach $line(@obydata) {
if(($line =~ /^\s*romsize\s*=/i) || ( $line=~ /^\s*rom_image/i) || ($line =~ /^\s*data_image/i)) {
$onlysmrimage = 0;
last;
}
}
if ($enforceFeatureManager && (!$featuremanager) && (!$noFeatureManager) ) {
my $defaultFeatureDbFlag = 0;
foreach $line(@obydata) {
if ($line=~/^\s*defaultfeaturedb\s*=?\s*(\S+)/i) {
# Get the default value for featuredatabasefile
$featureXml = "$epocroot$1";
$featureXml =~ s-\\-\/-g;
$featuremanager = 1;
$defaultFeatureDbFlag = 1;
load_featuresutil();
last;
}
}
if(!$defaultFeatureDbFlag && !$onlysmrimage)
{
print "Error: Neither option \"-fm|-nofm\" nor default value for featuredatabase file is provided.\n";
exit(1);
}
}
my @newobydata = ();
if (defined ($featureXml)) {
my $featurefilecount=0;
my $romimage=0;
foreach $line (@obydata) {
# specify which romimage following lines are part of
if ($line=~/^\s*ROM_IMAGE\[(\d)\]/) {
$romimage=$1;
$featurefilecount=0;
}
elsif ($line =~ /^\s*REM/i || $line =~ /^\s*\r?\n$/ ){
next ;
# ignore empty
}
elsif($line =~ /^\s*(FEATURE)\s*(\S*)\s*(.*)/i || $line =~ /^\s*(EXCLUDE_FEATURE)\s*(\S*)\s*(.*)/i) {
# FEATURE <feature_name> [ SF <status falgs> ] [ UD <user data> ]
my $feature = $1;
my $featurevalue = $2;
my $featureargs = $3;
my $reservedbit = 0;
my %featureflags=();
# Options 'SF' and 'UD' will be supported only for "-fm" option
if ($featuremanager) {
# [ SF <status falgs> ] [ UD <user data> ]
$featureargs =~ /(\S*)\s*(\S*)\s*(\S*)\s*(\S*)\s*/ ;
# Store the values of 'SF' and 'UD', or any invalid option, if provided
$featureflags{uc($1)} = $2 if ($1);
$featureflags{uc($3)} = $4 if ($3);
# Generate a warning if the option provided with Feature/Exclude_Feature keyword is
# not 'SF' or 'UD'.
foreach my $Key (keys %featureflags) {
if ($Key !~ /^(SF|UD)$/) {
print "Warning: Invalid argument \"$Key\" specified for feature $featurevalue\n";
delete $featureflags{$Key};
next;
}
}
}
# In verbose mode, generate warning if "SF|UD" arguments or invalid arguments are specified
# for "-f|fr" option.
elsif ($featureargs && $opt_v) {
print "Invalid argument(s) \"$featureargs\" provided for feature \"$featurevalue\"\n";
foreach my $Key (keys %featureflags) {
delete $featureflags{$Key};
}
}
# The feature file name is of the format featreg.cfg[x-y] or features.dat[x-y]
# where x is the romimage id, y is always 0, reserved for future use.
my $targetfeaturefile;
if (($romimage == 0) && ($reservedbit == 0)) {
# Core image will not have the mangled name
$targetfeaturefile = $featurefilename;
}
else {
$targetfeaturefile = $featurefilename . "\[". $romimage . "\-$reservedbit\]";
}
my $flag=1;
my $featureflag;
if ($feature =~ /^FEATURE$/i) {
$featureflag = 1;
}
else {
$featureflag = 0;
}
my $i;
# loop to see if name of feature file already added to this romimage in array
for($i=0;$i<$featurefilecount && $flag;$i++) {
$flag=0 if($featurefilearray[$romimage][$i]{cfgfile} eq $targetfeaturefile);
}
if($flag) { # adds feature file if not yet listed for this romimage in array
$featurefilearray[$romimage][$featurefilecount++]={cfgfile=>$targetfeaturefile, cfgdir=>$dir};
$i=$featurefilecount;
}
$featureslist[$featurescount]= {feature=>$featurevalue, include=>$featureflag, rom=>$romimage, cfgfile=>$i-1};
# Store the value of 'SF' in 'featureslist' array
$featureslist[$featurescount]->{SF} = $featureflags{SF} if (defined $featureflags{SF}) ;
# Store the value of 'UD' in 'featureslist' array
$featureslist[$featurescount]->{UD} = $featureflags{UD} if (defined $featureflags{UD}) ;
$featurescount++;
}
}
# Create Feature File
for(my $i=0;$i<scalar @featurefilearray;$i++) {
my $j=0;
while(defined $featurefilearray[$i][$j])
{
my $targetfeaturefile = $workdir.$featurefilearray[$i][$j]{cfgfile};
if (!(&featuresutil::createFeatureFile($i,$j,$targetfeaturefile,\@featureslist,$featuremanager))) {
$featurefilearray[$i][$j]{cfgfile}= undef;
exit(1) if($strict);
}
$j++;
}
}
my $flag=1;
my $imageIdx=0;
# Add feature files to ROM image, adds lines to obey file to specify existing locations
# of feature files and target locations.
# features.dat will be written to the end of rom/rofs
my @lastFLs = ();
my $lastRomIndex = 0 ;
foreach $line (@obydata) {
if($line =~/^\s*ROM_IMAGE\[(\d)\]/i) {
my $index=$1;
if($lastRomIndex != $index) {
foreach my $fl(@lastFLs) {
push @newobydata,$fl ;
}
@lastFLs = ();
$lastRomIndex = $index ;
}
push @newobydata, "\n" . $line . "\n";
my $j=0;
while(defined $featurefilearray[$index][$j]) {
$flag = 0 if($index == 0);
# Put in feature files for current ROM_IMAGE
my $targetfeaturefile = $featurefilearray[$index][$j]{cfgfile};
# Rom images will not have mangled name for feature files
# Rofsbuild will set attribute 'exattrib=U' in the entry record when this field is used.
# File Server when asked for a directory listing would notice the attribute and will return the
# list with mangled names. Hence, mangled name for feature files should not be put in ROM_IMAGE.
my $exattribute = "" ;
if (defined $targetfeaturefile ) {
$exattribute = "exattrib=U" if($index > 0);
push @lastFLs, "ROM_IMAGE[$index] data=" . $workdir . $targetfeaturefile . " \"". $featurefilearray[$index][$j]{cfgdir} .$featurefilename . "\"\t\t" . $exattribute . "\n";
$featurefilearray[$index][$j]{cfgfile} = undef ;
}
$j++;
}
}
elsif($line !~ /^\s*(FEATURE)\s*/i && $line !~ /^\s*(EXCLUDE_FEATURE)\s*/i && $line !~/^\s*defaultfeaturedb\s*=?\s*(\S+)/i) {
# Put in all other lines except the FEATURE and EXCLUDE_FEATURE keywords
push @newobydata, $line;
}
else {
push @newobydata, " ";
}
}
foreach my $fl(@lastFLs) {
push @newobydata,$fl ;
}
if($flag) {
# Put in feature files for ROM_IMAGE[0] if it is the only ROM_IMAGE
my $k=0;
while(defined $featurefilearray[0][$k])
{
my $targetfeaturefile = $featurefilearray[0][$k]{cfgfile};
if (defined $targetfeaturefile)
{
push @newobydata, "data=" . $workdir . $targetfeaturefile . " \"" . $featurefilearray[0][$k]{cfgdir} . $targetfeaturefile . "\"\n";
$featurefilearray[0][$k]{cfgfile} = undef ;
}
$k++;
}
}
}
elsif ($enforceFeatureManager && $noFeatureManager && $preBuiltFeaturesDataFile) {
print "Valid: $preBuiltFeaturesDataFile\n";
if (-e $preBuiltFeaturesDataFile) {
my $flag = 1;
foreach my $line (@obydata)
{
# Put in the pre-built features data file in ROM_IMAGE[0]
if($line =~/^\s*ROM_IMAGE\[1\]/i)
{
push @newobydata, "data=$preBuiltFeaturesDataFile" . " \"" . $dir . $featurefilename . "\"\n";
$flag =0;
}
push @newobydata, $line;
}
if($flag)
{
# Put in the pre-built features data file in ROM_IMAGE[0] if it is the only ROM_IMAGE
push @newobydata, "data=$preBuiltFeaturesDataFile" . " \"" . $dir . $featurefilename . "\"\n";
}
}
else
{
print "Error: File \"$preBuiltFeaturesDataFile\" doesn't exist.\n";
exit(1);
}
}
elsif ($enforceFeatureManager) {
print "Error: no feature data file or pre-built feature data file is provided!";
exit(1);
}
my $output ;
if(&is_windows) {
if($outputoby =~ /^[\\\/]/ || $outputoby =~ /^[a-zA-Z]:/) {
$output = $outputoby ;
}
else {
$output = $workdir.$outputoby;
}
}
else {
if($outputoby =~ /^[\/]/ ) {
$output = $outputoby ;
}
else {
$output = $workdir.$outputoby;
}
}
unlink $output if(-e $output);
print "* Writing $output...\n" if($opt_v);
unless(open FOUT, ">$output"){
print "Error: Can not write to $output.\n";
exit(1);
}
foreach(@newobydata){
chomp ;
print FOUT "$_\n";
}
close FOUT ;
print "* Done.\n" if($opt_v);
}
# make sure that all the absolute feature variant paths include a
# drive letter. This is required because cpp will not work with
# absolute paths starting with slashes.
sub addDrivesToFeatureVariantPaths
{
return unless $featureVariant{'VALID'};
my $current = &get_epocdrive;
my $drive = $1 if ($current =~ /^(.:)/);
# pre-include file
my $HRH = $featureVariant{'VARIANT_HRH'};
$featureVariant{'VARIANT_HRH'} = $drive . $HRH if ($HRH =~ /^[\\\/]/);
# ROM include path
my $dirRef = $featureVariant{'ROM_INCLUDES'};
return unless $dirRef;
my $i = 0;
foreach my $dir (@$dirRef)
{
$$dirRef[$i] = $drive . $dir if ($dir =~ /^[\\\/]/);
$i++;
}
}
#
# Process the given absolute path
# Add backslash at the end if required
# @param - path to be processed
#
sub processPath
{
my ($path) = shift;
return if( $$path =~ /(\\$)/ );
return if( $$path =~ /(\/$)/ );
$$path .= "/";
}
# Main block for buildrom module invocation
# Processes the buildrom command line parameters.
&process_cmdline_arguments;
if(scalar(@xmlDBFile) > 0) {
&processPath(\$epocroot);
&processPath(\$thisdir);
&features::set_DefaultPath($epocroot, \$thisdir, \$thisdir, \$thisdir, \$thisdir);
if(&features::open_Database(@xmlDBFile)) {
&features::generate_Obeyfile($workdir);
}
}
#Preprocessing phase
&preprocessing_phase;
# Creates feature registry configuration file/features data file.
&featurefile_creation_phase;
1;