sbsv1/abld/bldmake/metabld.pl
changeset 599 fa7a3cc6effd
equal deleted inserted replaced
596:9f25be3da657 599:fa7a3cc6effd
       
     1 # Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 # all variables called *Path* are set up to end with a backslash
       
    15 # all variables called *Path or *File are stored as absolute (file)paths within makmake
       
    16 # all variables called UpPath* are stored as relative paths within makmake
       
    17 # 
       
    18 #
       
    19 
       
    20 
       
    21 use FindBin;		# for FindBin::Bin
       
    22 use File::Find;
       
    23 use Cwd;
       
    24 
       
    25 my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
       
    26 
       
    27 BEGIN {
       
    28 # check user has a version of perl that will cope
       
    29 	require 5.005_03;
       
    30 # establish the path to the Perl libraries: currently the same directory as this script
       
    31 	$PerlLibPath = $FindBin::Bin;	# X:/epoc32/tools
       
    32 	$PerlLibPath =~ s/\//\\/g;	# X:\epoc32\tools
       
    33 	$PerlLibPath .= "\\";
       
    34 }
       
    35 
       
    36 use lib $PerlLibPath;
       
    37 use E32env;
       
    38 use Prepfile;
       
    39 use Pathutl;
       
    40 
       
    41 # autoflush prevents our ouptut from getting jumbled up
       
    42 use FileHandle;
       
    43 autoflush STDOUT 1;
       
    44 autoflush STDERR 1;
       
    45 
       
    46 my (@Commands, @BldInfDirs);
       
    47 # should end in .mbc where .mbc means for "MetaBld Configuration file"
       
    48 # must end in .mbc if passed on command-line
       
    49 my $ConfigFile;
       
    50 
       
    51 my $StartDir=&cwd();
       
    52 my $relative;
       
    53 	{
       
    54 	# Process command-line
       
    55 	
       
    56   	unless (@ARGV)
       
    57 		{
       
    58 		&Usage();
       
    59 		}
       
    60 	else
       
    61 		{
       
    62 		# check to see if we are using a relative path 
       
    63 	  	if ($ARGV[0] eq "-r")
       
    64 			{
       
    65 			$relative = 1;
       
    66 			shift @ARGV;
       
    67 			}
       
    68 
       
    69 		# check for a root from a config file in EPOCROOT dir as first argument
       
    70 	  	if (-e "$ENV{EPOCROOT}$ARGV[0].mbc")
       
    71 			{
       
    72 		  	$ConfigFile="$ENV{EPOCROOT}$ARGV[0].mbc";
       
    73 		  	shift @ARGV;
       
    74 			}
       
    75 		# check for a config file as the first argument
       
    76 	  	elsif ($ARGV[0]=~/.mbc$/io)
       
    77 			{
       
    78 			$ConfigFile=shift @ARGV;
       
    79 			if ($ConfigFile=~/^.:/o)
       
    80 				{
       
    81 				&Error("Config file can't be specified with a drive letter, as \"$ConfigFile\" is");
       
    82 				}
       
    83 			unless (-e $ConfigFile)
       
    84 				{
       
    85 				&Error("Can't find file $ConfigFile");
       
    86 				}
       
    87 			}
       
    88 		if (@ARGV)
       
    89 			{
       
    90 			# pass any other arguments as commands
       
    91 			@Commands=("@ARGV");
       
    92 			}
       
    93 		}
       
    94 	}
       
    95 
       
    96 	{
       
    97 	# scan config file if necessary
       
    98 	
       
    99 	if ($ConfigFile)
       
   100 		{
       
   101 		# make config file path absolute
       
   102 		$ConfigFile=&Path_AbsToWork($ConfigFile);
       
   103 		
       
   104 		my @Config2D;
       
   105 		eval { &Prepfile_ProcessL(\@Config2D, $ConfigFile); };
       
   106 		&Error($@) if $@;
       
   107 		
       
   108 		my %CheckDir;
       
   109 		
       
   110 		my @ConfigCommands;
       
   111 		my $Section='';
       
   112 		my @Death;
       
   113 		my $Line;
       
   114 		my $CurFile=$ConfigFile;
       
   115 	  LINE: foreach $Line (@Config2D)
       
   116 			{
       
   117 			my $LineNum=shift @$Line;
       
   118 			$_=shift @$Line;
       
   119 			if ($LineNum eq '#')
       
   120 				{
       
   121 				$CurFile=$_;
       
   122 				next;
       
   123 				}
       
   124 			if (/^SECTION_(\w*)$/io)
       
   125 				{
       
   126 				$Section=uc $1;
       
   127 				if ($Section=~/^(COMMANDS|DIRS|OPTIONALDIRS)$/o)
       
   128 					{
       
   129 					if (@$Line)
       
   130 						{
       
   131 						push @Death, "$CurFile($LineNum) : Can't specify anything on the same line as a section header\n";
       
   132 						}
       
   133 					next LINE;
       
   134 					}
       
   135 				push @Death, "$CurFile($LineNum) : Unknown section header - $_\n";
       
   136 				$Section=0;
       
   137 				next LINE;
       
   138 				}
       
   139 			unshift @$Line, $_;
       
   140 			if ($Section eq 'COMMANDS')
       
   141 				{
       
   142 				if ($$Line[0]=~/^ONEOFF$/io)
       
   143 					{
       
   144 					# check syntax for oneoff commands
       
   145 					unless (@$Line>=3)
       
   146 						{
       
   147 						push @Death, "$CurFile($LineNum) : Too few arguments for oneoff command\n";
       
   148 						}
       
   149 					# resolve oneoff dir relative to .mb file location
       
   150 					$$Line[1]=~s-^.*[^\\]$-$&\\-o; # add trailing backslash if necessary
       
   151 					$$Line[1]=&Path_MakeAbs($CurFile, $$Line[1]);
       
   152 					unless (-d $$Line[1])
       
   153 						{
       
   154 						warn "$CurFile($LineNum) : Can't find dir $$Line[1]\n";
       
   155 						}
       
   156 					}
       
   157 				push @ConfigCommands, "@$Line";
       
   158 				next LINE;
       
   159 				}
       
   160 			if ($Section eq 'DIRS' || $Section eq 'OPTIONALDIRS')
       
   161 				{
       
   162 				my $Dir;
       
   163 				foreach $Dir (@$Line)
       
   164 					{
       
   165 					if ($Dir=~/^.:/o)
       
   166 						{
       
   167 						push @Death, "$CurFile($LineNum) : directory $Dir is specified with a drive letter\n";
       
   168 						next;
       
   169 						}
       
   170 					$Dir=~s-^.*[^\\]$-$&\\-o;
       
   171 					$Dir=&Path_MakeAbs($CurFile, $Dir); # dirs must be the same for check
       
   172 					if ($CheckDir{uc $Dir})
       
   173 						{
       
   174 						# Silently ignore duplicate directories - #including of several .mbc files
       
   175 						# will often cause directory duplication.
       
   176 						# We can't do the same for duplicate commands because the order in which
       
   177 						# the commands are executed might be significant.
       
   178 						# push @Death, "$CurFile($LineNum) : Directory $Dir already specified\n";
       
   179 						next;
       
   180 						}
       
   181 					print "$Dir\n";
       
   182 					
       
   183 					unless (-d $Dir)
       
   184 						{
       
   185 						if ($Section ne 'OPTIONALDIRS')
       
   186 							{
       
   187 							push @Death, "$CurFile($LineNum) : Can't find directory $Dir\n";
       
   188 							}
       
   189 						next;
       
   190 						}
       
   191 					push @BldInfDirs, $Dir;
       
   192 					$CheckDir{uc $Dir}=$LineNum;
       
   193 					}
       
   194 				next LINE;
       
   195 				}
       
   196 			else
       
   197 				{
       
   198 				push @Death, "$CurFile($LineNum) : No section specified\n";
       
   199 				}
       
   200 			}
       
   201 		
       
   202 		if (@Death)
       
   203 			{
       
   204 			chomp $Death[$#Death];
       
   205 			&Error(@Death);
       
   206 			}
       
   207 		
       
   208 		# apply the commands unless already collected
       
   209 		unless (@Commands)
       
   210 			{
       
   211 			&Error("$ConfigFile : No Commands specified") unless @ConfigCommands;
       
   212 			@Commands=@ConfigCommands;
       
   213 			}
       
   214 		}
       
   215 	
       
   216 	# Should have commands now
       
   217 	&Usage() unless @Commands;
       
   218 	}
       
   219 
       
   220 	{
       
   221 	# Search for the BLD.INF files if necessary
       
   222 
       
   223 	my $mystartdir;
       
   224 	if ($relative)
       
   225 	{
       
   226 		$mystartdir = substr($StartDir, 2);
       
   227 	}
       
   228 
       
   229 	$mystartdir=~s:\/:\\:g;
       
   230 
       
   231 	if ($mystartdir ne "\\")
       
   232 		{
       
   233 		$mystartdir=$mystartdir."\\";
       
   234 		}
       
   235 
       
   236 	unless (@BldInfDirs)
       
   237 		{
       
   238 		# find the files in the source directories - skip the EPOCROOT directory
       
   239 		
       
   240 		my $EPOCROOTDir=$E32env::Data{EPOCPath};
       
   241 		$EPOCROOTDir=~s/^\\([^\\]*).*$/$1/o;
       
   242 		
       
   243 		opendir DIR, $mystartdir or &Error("Can't open dir: $!");
       
   244 		# remove ., .. and EPOCROOT dir
       
   245 		my @SrcDirs=grep !/^(\.\.?|$EPOCROOTDir|RECYCLER|System Volume Information)$/i, readdir DIR; 
       
   246 		foreach (@SrcDirs)
       
   247 			{
       
   248 			# prepend with current path
       
   249 			$_=$mystartdir.$_;
       
   250 			}
       
   251 		@SrcDirs=grep -d, @SrcDirs;
       
   252 		find(\&BldInfDirs, @SrcDirs);
       
   253 		@BldInfDirs=sort @BldInfDirs;
       
   254 
       
   255 		# if we are doing it relative to current location, need to include current dir
       
   256 		# if it contains a bld.inf
       
   257 		if (-f "BLD.INF" && $relative)
       
   258 			{
       
   259 			push @BldInfDirs, $mystartdir;
       
   260 			}
       
   261 
       
   262 		}
       
   263 	}
       
   264 
       
   265 	{
       
   266 	# Execute the commands
       
   267 	
       
   268 	my $Time=localtime;
       
   269 	print "=== metabld started $Time.\n";
       
   270 	my $Command;
       
   271 	foreach $Command (@Commands)
       
   272 		{
       
   273 		
       
   274 		$Time=localtime;
       
   275 		# Check if we should execute this command just the once
       
   276 		if ($Command=~s/^\s*ONEOFF\s+(\S+)\s+(.*)$/$2/io)
       
   277 			{
       
   278 			my $OneOffDir=$1;
       
   279 			# execute the command once rather than for each BLD.INF directory
       
   280 			chdir $OneOffDir or &Error("Can't change dir to $OneOffDir: $!");
       
   281 			print
       
   282 			(
       
   283 			 "===-------------------------------------------------\n",
       
   284 			 "=== $Command\n",
       
   285 			 "===-------------------------------------------------\n",
       
   286 			 "=== $Command started $Time.\n",
       
   287 			 "=== $Command == $OneOffDir\n"
       
   288 			);
       
   289 			system( "$Command");
       
   290 			}
       
   291 		else
       
   292 			{
       
   293 			# execute the command for each BLD.INF directory
       
   294 			print
       
   295 			(
       
   296 			 "===-------------------------------------------------\n",
       
   297 			 "=== $Command\n",
       
   298 			 "===-------------------------------------------------\n",
       
   299 			 "=== $Command started $Time.\n",
       
   300 			);
       
   301 			my $Dir;
       
   302 			foreach $Dir (@BldInfDirs)
       
   303 				{
       
   304 				chdir $Dir or &Error("Can't change dir to $Dir: $!");
       
   305 				print "=== $Command == $Dir\n";
       
   306 				system( "$Command");
       
   307 				}
       
   308 			}
       
   309 		chdir $StartDir or &Error("Can't change dir to $StartDir: $!");
       
   310 		$Time=localtime;
       
   311 		print "=== $Command finished $Time.\n";
       
   312 		}
       
   313 	}
       
   314 
       
   315 
       
   316 #################################################
       
   317 #	SUBROUTINES
       
   318 #################################################
       
   319 
       
   320 sub Usage
       
   321 	{
       
   322 	print <<ENDHERESTRING;
       
   323 usage: metabld [EPOCROOT .mbc file basename|.mbc config file] [command]
       
   324 MetaBld is a tool for carrying out build commands across several components.
       
   325 A .mbc config file contains directories and commands, eg:
       
   326 
       
   327 SECTION_COMMANDS
       
   328 bldmake bldfiles
       
   329 abld target wins udeb
       
   330 // "oneoff" means carry out command just once, not for each directory.
       
   331 // First arg after "oneoff" must be a start dir, and can be "."
       
   332 oneoff \\e32\\rombuild rom xxx
       
   333 oneoff . \\e32test\\group\\abld test build wins urel
       
   334 SECTION_DIRS
       
   335 \\e32
       
   336 \\f32\\group
       
   337 
       
   338 It's possible to #include lists of dirs from other files if necessary,
       
   339 and may be useful for carrying out different sets of commands on the same set
       
   340 of directories via different .mbc files.
       
   341 If a command is specified on the command-line, it will be executed instead
       
   342 of any commands specified in a .mbc file.
       
   343 If no directories are specified in a .mbc file, then all the directories
       
   344 containing a bld.inf file on the current drive will be searched for instead.
       
   345 ENDHERESTRING
       
   346 exit 1;
       
   347 }
       
   348 
       
   349 sub Error (@)
       
   350 	{
       
   351 	
       
   352 	die
       
   353 	@_, "\n",
       
   354 	"Error executing metabld.bat\n"
       
   355 	;
       
   356 	}
       
   357 
       
   358 sub BldInfDirs
       
   359 	{
       
   360 	s-\/-\\-go;
       
   361 	if (/^BLD.INF$/io)
       
   362 		{
       
   363 		$File::Find::dir=~s-\/-\\-go;
       
   364 		push @BldInfDirs, $File::Find::dir;
       
   365 		}
       
   366 	}
       
   367