You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
9.2 KiB
314 lines
9.2 KiB
#---------------------------------------------------------------------
|
|
package PbuildEnv;
|
|
#
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
#
|
|
# Version:
|
|
# 1.00 07/06/2000 JeremyD: inital version
|
|
# 1.01 07/13/2000 JeremyD: do as little as possible
|
|
# 1.02 07/26/2000 JeremyD: new logging style
|
|
# 1.03 10/04/2001 JeremyD: enable per-script debugging with PB_DEBUG
|
|
#---------------------------------------------------------------------
|
|
use strict;
|
|
use vars qw($VERSION);
|
|
use lib $ENV{RAZZLETOOLPATH};
|
|
use Carp;
|
|
use File::Basename;
|
|
use Logmsg;
|
|
use cklang;
|
|
|
|
$VERSION = '1.03';
|
|
|
|
my ($DoNothing, $StartTime);
|
|
|
|
BEGIN {
|
|
|
|
# avoid running in a -c syntax check
|
|
if ($^C) {
|
|
$DoNothing++;
|
|
return;
|
|
}
|
|
|
|
|
|
# required for logging
|
|
$ENV{SCRIPT_NAME} = basename($0);
|
|
|
|
|
|
# save a copy of the command line for logging
|
|
my $command_line = join ' ', $0, @ARGV;
|
|
|
|
|
|
# mini command line parser to snoop @ARGV for -l and -?
|
|
for (my $i=0; $i<@ARGV; $i++) {
|
|
# use the argument to -l to set $ENV{LANG} and then remove
|
|
# both items from @ARGV
|
|
if ($ARGV[$i] =~ /^[\/-]l(?::(.*))?$/) {
|
|
my $lang = $1;
|
|
if (!$lang and $ARGV[$i+1] !~ /^[\/-]/) {
|
|
$lang = $ARGV[$i+1];
|
|
splice @ARGV, $i+1, 1;
|
|
}
|
|
splice @ARGV, $i, 1;
|
|
$ENV{LANG} = $lang;
|
|
}
|
|
# if a -? is present exit immediately instead of setting
|
|
# up the full environment and logs
|
|
elsif ($ARGV[$i] =~ /^[\/-]?\?/) {
|
|
$DoNothing++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
# 'usa' is the default language
|
|
$ENV{LANG} ||= 'usa';
|
|
|
|
|
|
# validate language, bad languages are fatal
|
|
if( lc $ENV{LANG} eq "cov" )
|
|
{
|
|
if( !$ENV{_COVERAGE_BUILD} )
|
|
{
|
|
croak "Language $ENV{LANG} is not valid without a proper env var."
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!&cklang::CkLang($ENV{LANG})) {
|
|
croak "Language $ENV{LANG} is not listed in codes.txt.";
|
|
}
|
|
}
|
|
|
|
# set up a unique value to be used in log file names, this
|
|
# has the horrific side effect of making log names unbearably
|
|
# long and irritating to type
|
|
# BUGBUG: this is not unique enough, multiple instances of
|
|
# the same script in the same postbuild will clobber each
|
|
# other's file
|
|
my $unique_name = "$ENV{SCRIPT_NAME}.$ENV{_BUILDARCH}." .
|
|
"$ENV{_BUILDTYPE}.$ENV{LANG}";
|
|
|
|
|
|
# select postbuild dir using our language (usa is a special case)
|
|
$ENV{_NTPOSTBLD_BAK} ||= $ENV{_NTPOSTBLD};
|
|
$ENV{_NTPOSTBLD} = $ENV{_NTPOSTBLD_BAK};
|
|
if (lc($ENV{LANG}) ne 'usa' && lc($ENV{LANG}) ne 'cov' && !$ENV{dont_modify_ntpostbld} ) {
|
|
$ENV{_NTPOSTBLD} .= "\\$ENV{LANG}";
|
|
}
|
|
|
|
|
|
# select a temp dir using our language
|
|
$ENV{TEMP_BAK} ||= $ENV{TEMP};
|
|
$ENV{TEMP} = $ENV{TMP} = "$ENV{TEMP_BAK}\\$ENV{LANG}";
|
|
|
|
|
|
# create the directories for our logs if nescessary
|
|
# BUGBUG perl mkdir will not recursively create dirs
|
|
if (!-d $ENV{TEMP}) { mkdir $ENV{TEMP}, 0777 }
|
|
|
|
|
|
# select the final logfile we will append to when finished
|
|
# save the parent logfile to append to
|
|
if ($ENV{LOGFILE}) {
|
|
$ENV{LOGFILE_BAK} = $ENV{LOGFILE};
|
|
}
|
|
# this is the outermost script, set the final logfile name and
|
|
# clear it
|
|
else {
|
|
$ENV{LOGFILE_BAK} = "$ENV{TEMP}\\$unique_name.log";
|
|
if (-e $ENV{LOGFILE_BAK}) { unlink $ENV{LOGFILE_BAK} }
|
|
}
|
|
|
|
|
|
# select the final errfile we will append to when finished
|
|
# save the parent errfile to append to
|
|
if ($ENV{ERRFILE}) {
|
|
$ENV{ERRFILE_BAK} = $ENV{ERRFILE};
|
|
}
|
|
# we are the top level, select a filename and clear
|
|
else {
|
|
$ENV{ERRFILE_BAK} = "$ENV{TEMP}\\$unique_name.err";
|
|
if (-e $ENV{ERRFILE_BAK}) { unlink $ENV{ERRFILE_BAK} }
|
|
}
|
|
|
|
|
|
# we will acutally log to a tempfile during script execution
|
|
# we need to clear/create our temporary logging file
|
|
$ENV{LOGFILE} = "$ENV{TEMP}\\$unique_name.tmp";
|
|
unlink $ENV{LOGFILE};
|
|
|
|
$ENV{ERRFILE} = "$ENV{TEMP}\\$unique_name.err.tmp";
|
|
unlink $ENV{ERRFILE};
|
|
|
|
|
|
# turn on debugging if this script is mentioned by name
|
|
# in PB_DEBUG
|
|
if (defined $ENV{PB_DEBUG} and
|
|
$ENV{PB_DEBUG} =~ /\b\Q$ENV{SCRIPT_NAME}\E\b/i) {
|
|
$ENV{DEBUG} = 1;
|
|
}
|
|
|
|
$SIG{__WARN__} = sub {
|
|
if ($^S or !defined $^S) { return }
|
|
wrnmsg($_[0]);
|
|
};
|
|
|
|
$SIG{__DIE__} = sub {
|
|
if ($^S or !defined $^S) { return }
|
|
errmsg(Carp::longmess($_[0]));
|
|
};
|
|
|
|
# save the starting time to compute elapsed time in END block
|
|
$StartTime = time();
|
|
|
|
|
|
# record the command line in the log
|
|
infomsg("START \"$command_line\"" );
|
|
|
|
}
|
|
|
|
|
|
END {
|
|
|
|
# avoid running in a -c syntax check
|
|
return if $DoNothing;
|
|
|
|
|
|
# compute elasped time and make a nice string out of it
|
|
my $elapsed_time = time() - $StartTime;
|
|
my $time_string = sprintf("(%d second%s)", $elapsed_time,
|
|
($elapsed_time == 1 ? '' : 's'));
|
|
|
|
|
|
my $error_string = '';
|
|
# an error occurred iff this script called Logmsg::errmsg
|
|
if (-e $ENV{ERRFILE} and !-z $ENV{ERRFILE}) {
|
|
$error_string = "errors encountered";
|
|
|
|
# force a non-zero exit code, it's bad form to exit with
|
|
# 0 when you have an error
|
|
$? ||= 1;
|
|
}
|
|
# for historical reasons an exit code without an errmsg call is
|
|
# not an error
|
|
elsif ($?) {
|
|
$error_string = "nonzero exit code ($?)";
|
|
}
|
|
# no errmsg calls and exit code 0, clearly success
|
|
else {
|
|
$error_string = "success";
|
|
}
|
|
|
|
|
|
# record the elapsed time and success / failure status in the log
|
|
infomsg("END $time_string $error_string");
|
|
|
|
|
|
# at this point all logging is complete, our temporary log and
|
|
# error file are now appended back to the log and error file of
|
|
# the enclosing script
|
|
|
|
# save the names of the files we were using temporarily
|
|
my $temp_logfile = $ENV{LOGFILE};
|
|
my $temp_errfile = $ENV{ERRFILE};
|
|
|
|
# set the logging environment to the final locations
|
|
$ENV{ERRFILE} = $ENV{ERRFILE_BAK};
|
|
$ENV{LOGFILE} = $ENV{LOGFILE_BAK};
|
|
|
|
# append from our temporary log to the final log
|
|
open LOGFILE, ">>$ENV{LOGFILE}";
|
|
open TMPFILE, $temp_logfile;
|
|
print LOGFILE <TMPFILE>;
|
|
close LOGFILE;
|
|
close TMPFILE;
|
|
unlink($temp_logfile);
|
|
|
|
# append any errors back to the final error log
|
|
if (-e $temp_errfile) {
|
|
# skip 0 length error files
|
|
if (!-z $temp_errfile) {
|
|
open ERRFILE, ">>$ENV{ERRFILE}";
|
|
open TMPFILE, $temp_errfile;
|
|
print ERRFILE <TMPFILE>;
|
|
close ERRFILE;
|
|
close TMPFILE;
|
|
}
|
|
unlink($temp_errfile);
|
|
}
|
|
|
|
}
|
|
|
|
1;
|
|
|
|
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
PbuildEnv - Set up a local environment for postbuild scripts
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
use PbuildEnv;
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
PbuildEnv sets a BEGIN and END block that provide the nescessary
|
|
framework for running a script in the postbuild environment.
|
|
|
|
Be sure to use this module before any other postbuild specific
|
|
modules. Otherwise, some required variables may not be set up before
|
|
the other module tries to use them.
|
|
|
|
At compile time PbuildEnv will parse any language switches on the
|
|
command line. The argument to a -l switch will be stored in the
|
|
environment variable LANG by PbuildEnv at the time that it is use'd.
|
|
The -l and its argument will be removed from @ARGV before control
|
|
returns to your program.
|
|
|
|
PbuildEnv also sets the environment variables LOGFILE and ERRFILE
|
|
which are used by Logmsg. You should not use these environment
|
|
variables or the files they refer to directly in your program (use
|
|
Logmsg).
|
|
|
|
The TEMP and TMP environment variables have a per-language
|
|
subdirectory added to them (default is 'usa'). If your script uses
|
|
these variables be aware that you will need to append the language
|
|
manually when you are working at the command line. This modification
|
|
is to aid having multiple languages postbuilding on the same machine.
|
|
used by Logmsg, logs a beginning and ending message with elapsed
|
|
time, and propogates errors back to the calling context.
|
|
|
|
The _NTPOSTBLD environment variable will be set by PbuildEnv. This is
|
|
the location of binaries currently being postbuilt. Do not use
|
|
_NTTREE in postbuild, this will not be the correct location of
|
|
binaries on international builds.
|
|
|
|
=head1 NOTES
|
|
|
|
The following issues should be addressed in future versions of this
|
|
module.
|
|
|
|
Does not handle multiple invocations of the same script (within the
|
|
same arch / type / language combination) correctly. Unique names
|
|
should be created more carefully/randomly to prevent collisions.
|
|
|
|
Bad languages specified with -l cause a rather ungraceful exit.
|
|
|
|
During the log appending process no error checking is done. Along
|
|
with the uniqueness problem this makes the append logs somewhat less
|
|
robust than they should be.
|
|
|
|
Scripts that return non-zero exit codes but do not call
|
|
Logmsg::errmsg will be considered successful by postbuild.cmd.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Jeremy Devenport <JeremyD>
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
=cut
|