#!perl
# Copyright (c) 2002-2009 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:
#
#
use strict;
use FindBin;
use lib "$FindBin::Bin";
use Cwd;
use Getopt::Long;
use Utils;
$|++;
#
# Globals
#
my @bldData;
my $descriptionFile;
my $keepGoing = '';
my $saveSpace = '';
my $verbose = 0;
my $clean = 0;
my $outFile = "stdout.log";
my $errorFile = "stderr.log";
my $startTime;
my $cwd;
#
# Main.
#
ProcessCommandLine();
ParseDescriptionFile();
Init();
DoBuild();
End();
#
# Subs
#
sub ProcessCommandLine {
Getopt::Long::Configure ("bundling");
my $help;
GetOptions('c+' => \$clean, 'h' => \$help, 'k' => \$keepGoing, 's' => \$saveSpace, 'v+' => \$verbose);
if ($help) {
Usage(0);
}
$descriptionFile = shift @ARGV;
unless ($descriptionFile and $#ARGV == -1) {
print "Error: Invalid arguments\n";
Usage(1);
}
}
sub Usage {
my $exitCode = shift;
Utils::PrintDeathMessage($exitCode, "\nUsage: mbld [options] <build_description_file>
options:
-h help
-c clean (-cc reallyclean)
-k keep going
-s save space
-v verbose output (-vv very verbose)\n");
}
sub Init {
$startTime = time;
unlink $outFile;
unlink $errorFile;
$cwd = cwd();
$outFile = "$cwd\\$outFile";
$errorFile = "$cwd\\$errorFile";
}
sub ParseDescriptionFile {
open(FILE, $descriptionFile) or die "Error: Unable to open \"$descriptionFile\" for reading: $!\n";
my $line = -1;
while (<FILE>) {
++$line;
# Remove line feed, white space and comments.
chomp;
s/^\s*$//;
s/#.*//;
if ($_ eq '') {
# Nothing left.
next;
}
(my @words) = split /\s+/;
if ($#words < 2) {
print "Warning: Not enough arguments on line $line\n";
next;
}
my $bldEntry;
$bldEntry->{name} = shift @words;
$bldEntry->{bldInf} = shift @words;
if ($words[0] eq 'test') {
$bldEntry->{test} = 1;
shift @words;
if ($#words == -1) {
print "Warning: Not enough arguments on line $line\n";
next;
}
}
$bldEntry->{plat} = shift @words;
if ($#words >= 0) {
if ($words[0] =~ /(udeb)|(urel)/) {
$bldEntry->{var} = shift @words;
}
}
if ($#words >= 0) {
$bldEntry->{mmp} = shift @words;
}
push (@bldData, $bldEntry);
}
close FILE;
}
sub DoBuild {
if ($clean == 1) {
DoPlatformVariantCommand('clean: ', 'abld', 'clean');
}
elsif ($clean == 2) {
DoPlatformVariantCommand('reallyclean: ', 'abld', 'reallyclean');
}
DoBldMake();
DoExport();
DoPlatformCommand('makefile: ', 'abld', 'makefile');
DoPlatformCommand('library: ', 'abld', 'library');
DoPlatformVariantCommand('resource: ', 'abld', 'resource');
my $target = 'target';
if ($keepGoing) {
$target .= " $keepGoing";
}
if ($saveSpace) {
$target .= " $saveSpace";
}
DoPlatformVariantCommand('target: ', 'abld', $target);
DoPlatformVariantCommand('final: ', 'abld', 'final');
DoPlatformVariantCommand('check: ', 'abld -check', 'build');
}
sub DoBldMake {
my %built;
foreach my $bldEntry (@bldData) {
unless (exists $built{lc($bldEntry->{bldInf})}) {
DoPrint("bldfiles: $bldEntry->{name} [bldmake bldfiles]");
chdir $bldEntry->{bldInf} or die "Error: Couldn't change working directory to \"$bldEntry->{bldInf}\": $!\n";
system "bldmake bldfiles >>$outFile 2>>$errorFile";
chdir $cwd or die "Error: Couldn't change working directory to \"$cwd\": $!\n";
$built{lc($bldEntry->{bldInf})} = 1;
}
}
}
sub DoExport {
my %built;
my %builtTest;
foreach my $bldEntry (@bldData) {
if (exists $bldEntry->{test}) {
unless (exists $builtTest{lc($bldEntry->{bldInf})}) {
DoPrint("export: $bldEntry->{name} [abld test export]");
chdir $bldEntry->{bldInf} or die "Error: Couldn't change working directory to \"$bldEntry->{bldInf}\": $!\n";
system "abld test export >>$outFile 2>>$errorFile";
chdir $cwd or die "Error: Couldn't change working directory to \"$cwd\": $!\n";
$builtTest{lc($bldEntry->{bldInf})} = 1;
}
}
else {
unless (exists $built{lc($bldEntry->{bldInf})}) {
DoPrint("export: $bldEntry->{name} [abld export]");
chdir $bldEntry->{bldInf} or die "Error: Couldn't change working directory to \"$bldEntry->{bldInf}\": $!\n";
system "abld export >>$outFile 2>>$errorFile";
chdir $cwd or die "Error: Couldn't change working directory to \"$cwd\": $!\n";
$built{lc($bldEntry->{bldInf})} = 1;
}
}
}
}
sub DoPlatformCommand {
my $prompt = shift;
my $command1 = shift;
my $command2 = shift;
foreach my $bldEntry (@bldData) {
my $command = $command1;
if (exists $bldEntry->{test}) {
$command .= ' test';
}
$command .= " $command2 $bldEntry->{plat}";
if (exists $bldEntry->{mmp}) {
$command .= " $bldEntry->{mmp}";
}
DoPrint("$prompt $bldEntry->{name} [$command]");
chdir $bldEntry->{bldInf} or die "Error: Couldn't change working directory to \"$bldEntry->{bldInf}\": $!\n";
system "$command >>$outFile 2>>$errorFile";
chdir $cwd or die "Error: Couldn't change working directory to \"$cwd\": $!\n";
}
}
sub DoPlatformVariantCommand {
my $prompt = shift;
my $command1 = shift;
my $command2 = shift;
foreach my $bldEntry (@bldData) {
my $command = $command1;
if (exists $bldEntry->{test}) {
$command .= ' test';
}
$command .= " $command2 $bldEntry->{plat}";
if (exists $bldEntry->{var}) {
$command .= " $bldEntry->{var}";
}
if (exists $bldEntry->{mmp}) {
$command .= " $bldEntry->{mmp}";
}
DoPrint("$prompt $bldEntry->{name} [$command]");
chdir $bldEntry->{bldInf} or die "Error: Couldn't change working directory to \"$bldEntry->{bldInf}\": $!\n";
system "$command >>$outFile 2>>$errorFile";
chdir $cwd or die "Error: Couldn't change working directory to \"$cwd\": $!\n";
}
}
sub DoPrint {
my $prompt = $_[0];
print "$prompt\n";
system "echo === $prompt >> $outFile";
system "echo === $prompt >> $errorFile";
}
sub End {
my $finishTime = time;
my $total = $finishTime - $startTime;
my $seconds = $total % 60;$total = ($total - $seconds) / 60;
my $minutes = $total % 60;$total = ($total - $minutes) / 60;
my $hours = $total % 24;$total = ($total - $hours) / 24;
print "\nTotal build time: $hours:$minutes:$seconds\n";
chdir $cwd;
}
__END__
=head1 NAME
MBld - Builds multiple components in one pass.
=head1 SYNOPSIS
mbld [options] <build_description_file>
options:
-h help
-c clean (-cc reallyclean)
-k keep going
-s save space
-v verbose output (-vv very verbose)
=head1 DESCRIPTION
The build description file must be plain text with lines of the following format (one for each item that you want to be built):
component_name bld_inf_path [test] platform [variant] [mmp_file]
=over 4
=item component_name
A string that can be used to identify the component being built - can be anything you like provided it's a single word.
=item bld_inf_path
An absolute or relative path to where the componen't F<bld.inf> file can be found.
=item test
An optional argument to allow test code to be built.
=item platform
The build plaform required (e.g. C<WINS>, C<WINCW>, C<THUMB>, C<ARM4>, C<ARMI>, C<MISA> etc).
=item variant
The build variant (either C<udeb> or C<urel>). If ommitted, both variants will be built.
=item mmp_file
A optional argument that allows specific projects (defined by an F<mmp> file) to be built. If ommitted all F<mmp> files will be used.
=back
The build output is captured to a pair of log files; F<stdout.log> for C<STDOUT> and F<stderr.log> for C<STDERR>.
=head1 KNOWN BUGS
None.
=head1 COPYRIGHT
Copyright (c) 2002-2009 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:
=cut