Leaked source code of windows server 2003
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.

717 lines
22 KiB

  1. # FileName: timebuild.pl
  2. #
  3. # Have any changes to this file reviewed by DavePr, BryanT, or WadeLa
  4. # before checking in.
  5. # Any changes need to verified in all standard build/rebuild scenarios.
  6. #
  7. # Reads in the commands from commandfile, and executes them with system() -- recording
  8. # the elapsed times on the standard output.
  9. # Echo and timing can be supressed by prepending '@'.
  10. # The magic 'CHECKFATAL' command can be used to end a script if the previous command failed.
  11. # If commandfile is not specified, uses a canned list of commands.
  12. #
  13. # Note: ':' can be used instead of '=' in command line arguments, since '=' is a separator to cmd.exe
  14. #
  15. # WARNING:
  16. # WARNING: make sure pathname comparisons are case insensitive. Either convert the case or do the
  17. # WARNING: comparisons like this:
  18. # WARNING: if ($foo =~ /^\Q$bar\E$/i) {}
  19. # WARNING: or if ($foo !~ /^\Q$bar\E$/i) {}
  20. # WARNING:
  21. # use appropriate pm files
  22. use lib $ENV{ "RazzleToolPath" } . "\\PostBuildScripts";
  23. use cookie;
  24. #
  25. # Default cmdlist
  26. # Enclose in single quotes, unless getting tricky with parameters
  27. #
  28. # Note that RESUME and STOPAFTERBUILD are referenced in the code.
  29. #
  30. @ValidFlagList = ("NOSYNC", "NOPOSTBUILD", "STOPAFTERBUILD", "RELEASE", "NOSCORCH", "NOCLEANBUILD", "CHECKSYNC");
  31. $Usage = $PGM . "Usage: timebuild.pl\n"
  32. . " [-]\n"
  33. . " [-START=[[YY]MMDD-]HH[:]MM[(a|p)] - specify a time to start the commands (start => revision time to use)\n"
  34. . " [-START=+[HH[:]MM]] - specify a delay before starting commands\n"
  35. . " [-RESUME] - start-up again after the build step\n"
  36. . " [-STOPAFTERBUILD] - stop commands right after the build step\n"
  37. . " [-NOSYNC] - do not sync/resolve\n"
  38. . " [-NOSCORCH] - do not run scorch\n"
  39. . " [-NOCLEANBUILD] - don't use -c with build\n"
  40. . " [-NOPOSTBUILD] - skip the postbuild step\n"
  41. . " [-NOCOOKIE] - ignore synchronization against concurrent timebuilds\n"
  42. . " [-COVERBUILD] - produce one build with coverage-enabled files\n"
  43. . " [-COVERBUILDONLY] - [REMOVED] same as COVERBUILD\n"
  44. . " [-RELEASE] - release the build (automatic on build machines)\n"
  45. . " [-REVISION=<sdrevision>] - SD file revision to use (\@yyyy/mm/dd:hh:ss or \#rev -- see sd help revisions)\n"
  46. . " [commandfile | - ] - instead of built-in commands use file or stdin\n\n";
  47. #
  48. # Conditional execution based on either ValidFlagList (specified on command line) or environment variables.
  49. #
  50. @cmdlist = (
  51. ' @echo Running <<timebuild>>',
  52. '=%OFFICIAL_BUILD_MACHINE ECHO This is an OFFICIAL BUILD MACHINE!',
  53. '=%OFFICIAL_BUILD_MACHINE=PRIMARY ECHO Publics will be published if timebuild succeeds.',
  54. ' @if EXIST <<fixederr>> del <<fixederr>>',
  55. '=NOSYNC @echo SKIPPING sync/resolve',
  56. '=NOSYNC SUCCESS', # set current result code to 0
  57. '!NOSYNC revert_public.cmd',
  58. '=CHECKSYNC CHECKWARN perl %sdxroot%\Tools\sendbuildstats.pl -warn -m revert_public failed',
  59. '=NOSCORCH @echo SKIPPING scorch',
  60. '!NOSCORCH nmake -lf makefil0 scorch_source',
  61. '!NOSCORCH CHECKWARN perl %sdxroot%\Tools\sendbuildstats.pl -warn -m scorch failed see %sdxroot%\build.scorch',
  62. '!NOSYNC sdx sync <<timestamp>> -q -h > build.changes 2>&1',
  63. '=CHECKSYNC CHECKWARN perl %sdxroot%\Tools\sendbuildstats.pl -warn -m sdx sync failed',
  64. '!NOSYNC sdx resolve -af',
  65. '=CHECKSYNC CHECKWARN perl %sdxroot%\Tools\sendbuildstats.pl -warn -m sdx resolve failed',
  66. '!NOSYNC perl %sdxroot%\Tools\ChangesToFiles.pl build.changes > build.changedfiles 2>&1',
  67. '!NOSYNC @echo BUILDDATE=<<BUILDDATE_timestamp>> > __blddate__',
  68. # ' sdx delta > build.baseline',
  69. '!NOCLEANBUILD build -cZP',
  70. '=NOCLEANBUILD @echo NOT BUILDING CLEAN',
  71. '=NOCLEANBUILD build -ZP',
  72. ' CHECKBUILDERRORS',
  73. ' CHECKFATAL perl %sdxroot%\Tools\sendbuildstats.pl -too -buildfailure',
  74. 'RESUME',
  75. '=RESUME ECHO Resuming timebuild after build step.',
  76. '=RESUME ECHO Resuming timebuild after build step. >> build.changes',
  77. # '=RESUME ECHO The following changes have been made since the build was started. >> build.changes',
  78. # '=RESUME perl %sdxroot%\Tools\DetermineChanges.pl build.baseline >> build.changes',
  79. # '=RESUME perl %sdxroot%\Tools\ChangesToFiles.pl build.changes > build.changedfiles 2>&1',
  80. '=STOPAFTERBUILD QUIT TIMEBUILD stopping after build, use /RESUME to continue.',
  81. ' perl %sdxroot%\Tools\PopulateFromVBL.pl -verbose -checkbinplace -force',
  82. ' CHECKFATAL',
  83. '!NOPOSTBUILD postbuild',
  84. '!NOPOSTBUILD CHECKFATAL perl %sdxroot%\tools\sendbuildstats.pl -postbuildfailure',
  85. '=RELEASE perl %RazzleToolPath%\PostBuildScripts\release.pl -nd',
  86. '!NOPOSTBUILD perl %sdxroot%\tools\sendbuildstats.pl -successful',
  87. '=NOPOSTBUILD ECHO SKIPPING postbuild',
  88. 'ECHO Finished Timing Build'
  89. );
  90. if ($ENV{'BUILD_OFFLINE'} eq "1") { @cmdlist = (
  91. ' @echo Running <<timebuild>>',
  92. ' @if EXIST <<fixederr>> del <<fixederr>>',
  93. '=NOSYNC @echo SKIPPING sync/resolve',
  94. '=NOSCORCH @echo SKIPPING scorch',
  95. '!NOCLEANBUILD build -cZP',
  96. '=NOCLEANBUILD @echo NOT BUILDING CLEAN',
  97. '=NOCLEANBUILD build -ZP',
  98. ' CHECKBUILDERRORS',
  99. ' CHECKFATAL',
  100. # ' CHECKFATAL perl %sdxroot%\Tools\sendbuildstats.pl -fb;',
  101. 'RESUME',
  102. '=RESUME ECHO Resuming timebuild after build step.',
  103. '=RESUME ECHO Resuming timebuild after build step. >> build.changes',
  104. # '=RESUME ECHO The following changes have been made since the build wsa started. >> build.changes',
  105. # '=RESUME perl %sdxroot%\Tools\DetermineChanges.pl build.baseline >> build.changes',
  106. '=STOPAFTERBUILD QUIT TIMEBUILD stopping after build, use /RESUME to continue.',
  107. # ' perl %sdxroot%\Tools\PopulateFromVBL.pl -verbose -checkbinplace -force',
  108. ' CHECKFATAL',
  109. '!NOPOSTBUILD postbuild',
  110. '!NOPOSTBUILD CHECKFATAL',
  111. # '!NOPOSTBUILD CHECKFATAL perl %sdxroot%\tools\sendbuildstats.pl -fpb',
  112. '=RELEASE perl %RazzleToolPath%\PostBuildScripts\release.pl -nd',
  113. # '!NOPOSTBUILD perl %sdxroot%\tools\sendbuildstats.pl -s',
  114. '=NOPOSTBUILD ECHO SKIPPING postbuild',
  115. 'ECHO Finished Timing Build'
  116. );
  117. }
  118. for (@ValidFlagList) {
  119. $ValidFlag{lc $_} = 1;
  120. }
  121. $TimeLogFileName = "build.time";
  122. $ChangeLogFileName = "build.changes";
  123. $TimeHistFileName = "build.timehistory";
  124. $BuildErrorFileName = "build.err";
  125. $BuildCheckFileName = "build.fixed-err";
  126. $CookieSleepDuration = 60;
  127. $cmdvar{fixederr} = $BuildCheckFileName;
  128. #
  129. # Debug routines for printing out variables
  130. #
  131. sub gvar {
  132. for (@_) {
  133. print "\$$_ = $$_\n";
  134. }
  135. }
  136. #
  137. # print on the various files
  138. #
  139. sub printall {
  140. print TIMELOGFILE @_;
  141. print TIMEHISTFILE @_;
  142. print $PGM unless @_ == 1 and $_[0] eq "\n";
  143. print @_;
  144. }
  145. sub printfall {
  146. printf TIMELOGFILE @_;
  147. printf TIMEHISTFILE @_;
  148. print $PGM unless @_ == 1 and $_[0] eq "\n";
  149. printf @_;
  150. }
  151. #
  152. # Sub hms
  153. # Takes Argument time in seconds and returns as list of (hrs, mins, secs)
  154. #
  155. sub hms {
  156. $s = shift @_;
  157. $h = int ($s / 3600);
  158. $s -= 3600*$h;
  159. $m = int ($s / 60);
  160. $s -= 60*$m;
  161. return ($h, $m, $s);
  162. }
  163. #
  164. # Sub toseconds
  165. # Takes Argument time string and returns how many seconds from now.
  166. # Balks at negative time, or time greater than a week.
  167. # Returns 0 on error. Any valid time returns at least 1 second.
  168. # Flavors of time specs:
  169. # +MM
  170. # +HH:MM
  171. # HH:MM
  172. # HH:MMa
  173. #
  174. sub toseconds {
  175. my($y, $M, $d, $h, $m, $s, $mday, $wday, $yday, $isdst);
  176. my($delta, $now, $then, $th, $tm, $ampm);
  177. my($arg) = $_[0];
  178. ($s, $m, $h, $mday, $M, $y, $wday, $yday, $isdst) = localtime;
  179. $y += 1900;
  180. $M += 1;
  181. $mday += 1;
  182. if ($arg =~ /^\+(\d+)$/i) {
  183. $delta = $1;
  184. } elsif ($arg =~ /^\+(\d+)\:(\d{1,2})$/i) {
  185. $delta = $1 * 60 + $2;
  186. } elsif ($arg =~ /^(\d{1,2})\:(\d{1,2})([ap]m{0,1}){0,1}$/i
  187. or $arg =~ /^(\d\d)(\d\d)([ap]m{0,1}){0,1}$/i) {
  188. $th = $1;
  189. $tm = $2;
  190. $ampm = $3;
  191. return -1 if $ampm and ($th == 0 or $th > 12);
  192. if ($ampm =~ /^pm{0,1}$/i) {
  193. $th += 12 if $th < 12;
  194. } else {
  195. $th = 0 if $th == 12;
  196. }
  197. $now = $h *60 + $m;
  198. $then = $th *60 + $tm;
  199. $then += (24 *60) if ($now > $then);
  200. $delta = $then - $now;
  201. } else {
  202. $delta = -1;
  203. }
  204. return $delta * 60 if $delta > 0; # convert to seconds
  205. return 1 if $delta == 0; # minimum valid wait
  206. return 0 if $delta < 0; # error
  207. }
  208. #
  209. # Initialization
  210. #
  211. $PGM='TIMEBUILD: ';
  212. $cmdvar{timebuild} = "TIMEBUILD";
  213. $TimeLogFileSpec = ">" . $TimeLogFileName;
  214. $TimeHistFileSpec = ">>" . $TimeHistFileName;
  215. open TIMELOGFILE, $TimeLogFileSpec or die $PGM, "Could not open: ", $TimeLogFileName, "\n";
  216. open TIMEHISTFILE, $TimeHistFileSpec or die $PGM, "Could not open: ", $TimeHistFileName, "\n";
  217. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
  218. $foo = sprintf "Timed Build script started at %04d/%02d/%02d-%02d:%02d:%02d.\n",
  219. 1900+$year, 1+$mon, $mday, $hour, $min, $sec;
  220. printall "\n";
  221. printall $foo;
  222. $begintime = time();
  223. #
  224. # Assume we're setting the build date.
  225. #
  226. $ENV{"BUILD_DATE_SET"} = 1;
  227. #
  228. # Make sure NT_SIGNCODE is off as it disables most of the postbuild changes.
  229. #
  230. $ENV{"NT_SIGNCODE"} = "";
  231. #
  232. # Process and validate arguments
  233. #
  234. $CommandFile = 0;
  235. $DoResume = 0;
  236. $ResumeTag = "";
  237. $Verbose = 0;
  238. $Fake = 0;
  239. $WaitSeconds = 0;
  240. $NoCookie = 0;
  241. $Revision = "";
  242. for (@ARGV) {
  243. if (/^[\-\/]{0,1}\?$/i) { die $Usage; }
  244. if (/^[\-\/]help$/i) { die $Usage; }
  245. if (/^[\-\/]resume$/i) { $DoResume++; $ResumeTag = ""; next; }
  246. if (/^[\-\/]resume[:=](.+)$/i) { $DoResume++; $ResumeTag = $1; next; }
  247. if (/^[\-\/]revision[:=]([@#].+)$/i) { $Revision = $1; next; }
  248. if (/^[\-\/]verbose$/i) { $Verbose++; next; }
  249. if (/^[\-\/]fake$/i) { $Fake++; next; }
  250. if (/^[\-\/]nocookie$/i) { $NoCookie++; next; }
  251. if (/^[\-\/]start[:=](.+)$/i) { $WaitSeconds = toseconds $1;
  252. die $PGM, "Invalid start time: ", $1, "\n" unless $WaitSeconds;
  253. next;
  254. }
  255. #
  256. # Set the environment variables we need for producing a coverage build
  257. #
  258. if (/^[\-\/]coverbuild/i) {
  259. $ENV{"_COVERAGE_BUILD"} = 1;
  260. if (/^[\-\/]coverbuildonly$/i) { $ENV{"_COVERAGE_BUILD_ONLY"} = 1; }
  261. next;
  262. }
  263. #
  264. # We don't set the build date if this is a nosync build.
  265. #
  266. if (/^[\-\/]nosync/i) {
  267. $ENV{"BUILD_DATE_SET"} = "";
  268. }
  269. #
  270. # Flags can be used for things like -STOPAFTERBUILD
  271. #
  272. if (/^[\-\/](\S+)[:=](\S+)$/i) {
  273. $argkey = lc $1;
  274. $argval = lc $2;
  275. die $PGM, "Invalid option: ", $argkey, "\n", $Usage unless $ValidFlag{$argkey};
  276. $Flags{$argkey} = $argval;
  277. next;
  278. }
  279. if (/^[\-\/](\S+)$/i) {
  280. $argkey = lc $1;
  281. die $PGM, "Invalid option: ", $argkey, "\n", $Usage unless $ValidFlag{$argkey};
  282. $Flags{$argkey}++;
  283. next;
  284. }
  285. #
  286. # All that should be left is the commandfile (we only allow one).
  287. #
  288. die $Usage if $CommandFile;
  289. $CommandFile = $_;
  290. }
  291. print $PGM, "Only Faking.\n" if $Fake;
  292. die $Usage if $DoResume > 1;
  293. if ($CommandFile) {
  294. @cmdlist = ();
  295. open CMD, $CommandFile or die $PGM, "Could not open command file: ", $CommandFile, "\n";
  296. for (<CMD>) {
  297. push @cmdlist, $_;
  298. }
  299. close CMD;
  300. print $PGM, 'Running commands from: ', $CommandFile, "\n";
  301. } else {
  302. print $PGM, "Running default build commands.\n";
  303. }
  304. #
  305. # Set up some global variables: nttree
  306. #
  307. # Check the environmental assumptions.
  308. #
  309. # _nttree has to point at a directory containing build_logs
  310. # no_binaries results in a warning
  311. # VBL release has to be detectable
  312. # VBL has to have binlist and binplace files.
  313. #
  314. # Get the current directory
  315. #
  316. open CWD, 'cd 2>&1|';
  317. $CurrDir = <CWD>;
  318. close CWD;
  319. chomp $CurrDir;
  320. $s = $ENV{'sdxroot'};
  321. if (not $s) {
  322. printall "sdxroot not defined\n";
  323. exit 1;
  324. }
  325. if ($s !~ /^\Q$CurrDir\E$/i) {
  326. printall "ERROR: CD ($CurrDir) mismatch with sdxroot ($s)\n";
  327. exit 1;
  328. }
  329. $nttree = $ENV{'_NTTREE'};
  330. if (not $nttree) {
  331. printall "_NTTREE not defined - Adding STOPAFTERBUILD to arg list\n";
  332. $Flags{"STOPAFTERBUILD"} = 1;
  333. }
  334. if (not $ENV{'USERNAME'} and not $ENV {'_NT_BUILD_DL'} and not $ENV {'OFFICIAL_BUILD_MACHINE'}) {
  335. printall "ERROR: Must be an official build machine, or set USERNAME or _NT_BUILD_DL in the environment\n";
  336. exit 1;
  337. }
  338. # THIS IS STILL TODO
  339. use File::Compare;
  340. #
  341. # Process the commands
  342. #
  343. #
  344. # Calculate the build date value to write to __blddate__
  345. #
  346. $BuildDate = "";
  347. if ($Revision) {
  348. # For now, if they specified a revision, just use the current time/date for the build date
  349. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time() + $WaitSeconds);
  350. $BuildDate = sprintf "%02d%02d%02d-%02d%02d", (1900+$year)%100, 1+$mon, $mday, $hour, $min;
  351. }
  352. #
  353. # sleep if we were told /START=...
  354. #
  355. if ($WaitSeconds) {
  356. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time() + $WaitSeconds);
  357. if ($sec < $WaitSeconds) {
  358. $WaitSeconds -= $sec;
  359. $sec = 0;
  360. }
  361. $foo = sprintf "Waiting to run commands until %04d/%02d/%02d-%02d:%02d:%02d.\n",
  362. 1900+$year, 1+$mon, $mday, $hour, $min, $sec;
  363. printall $foo;
  364. sleep $WaitSeconds;
  365. #
  366. # yyyy/mm/dd:hh:mm:ss
  367. #
  368. if (not $Revision) {
  369. $Revision = sprintf "@%04d/%02d/%02d:%02d:%02d", 1900+$year, 1+$mon, $mday, $hour, $min;
  370. $BuildDate = sprintf "%02d%02d%02d-%02d%02d", (1900+$year)%100, 1+$mon, $mday, $hour, $min;
  371. }
  372. #
  373. # reset the beginning time if we slept
  374. #
  375. $begintime = time();
  376. }
  377. if (not $Revision) {
  378. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time());
  379. $Revision = sprintf "@%04d/%02d/%02d:%02d:%02d", 1900+$year, 1+$mon, $mday, $hour, $min;
  380. $BuildDate = sprintf "%02d%02d%02d-%02d%02d", (1900+$year)%100, 1+$mon, $mday, $hour, $min;
  381. }
  382. $cmdvar{timestamp} = "$Revision";
  383. $cmdvar{BUILDDATE_timestamp} = "$BuildDate";
  384. printall "sdx sync revision: $Revision\n";
  385. #
  386. # do the cookie check, unless -nocookie
  387. #
  388. if ( $NoCookie == 0 ) {
  389. printall "Checking for other instances of timebuild ...\n";
  390. $CookieName = "timebuild." . $ENV{ "SDXROOT" };
  391. $CookieName =~ s/[\:\\]/\./g;
  392. $CheckCookie = "TRUE"; # loop variable to see if we've acquired the cookie
  393. while ( $CheckCookie eq "TRUE" ) {
  394. # attempt to acquire the cookie
  395. $CookieRC = &cookie::CreateCookieQuiet( $CookieName );
  396. if ( $CookieRC ) {
  397. # we successfully created the cookie, we're the only instance of timebuild
  398. printall "No other timebuilds running, continuing ...\n";
  399. $CheckCookie = "FALSE";
  400. } else {
  401. # someone else has the cookie, there is another instance of timebuild running.
  402. printall "Other timebuilds are running, sleeping $CookieSleepDuration seconds ...\n";
  403. sleep( $CookieSleepDuration );
  404. }
  405. }
  406. }
  407. $rc = 0;
  408. for (@cmdlist) {
  409. chomp;
  410. s/\#.*$//;
  411. s/^\s+//;
  412. s/\s+$//;
  413. $skipchar = s/^\@//;
  414. #
  415. # replace any cmd variables
  416. #
  417. while (s/<<([^<]+)>>/$cmdvar{$1}/) {}
  418. #
  419. # Skip through the specified RESUME line
  420. #
  421. if (/^RESUME\s*/i) {
  422. if ($DoResume) {
  423. $DoResume = 0 if /^RESUME\s*(\Q$ResumeTag\E)$/i;
  424. $Flags{'resume'} = 1;
  425. }
  426. next;
  427. }
  428. next if $DoResume;
  429. #
  430. # Handle conditional execution of commands (before CHECKFATAL)
  431. #
  432. if (/^([!=])(\%{0,1})(\w+)%{0,1}\s*=(\S*)\s+(.*)$/i) {
  433. $argkey = lc $3;
  434. $argval = lc $4;
  435. $keyval = ($2 eq '%')? $ENV{$argkey} : $Flags{$argkey};
  436. $keyval = lc $keyval;
  437. printall ("Info: Picking up %$argkey%=$ENV{$argkey} from environment.\n") if $Verbose and !$Flags{$argkey} and $ENV{$argkey};
  438. next if $1 eq '=' and $keyval ne $argval;
  439. next if $1 eq '!' and $keyval eq $argval;
  440. $_ = $5;
  441. }
  442. elsif (/^([!=])(\%{0,1})(\w+)%{0,1}\s+(.*)$/i) {
  443. $argkey = lc $3;
  444. $keyval = ($2 eq '%')? $ENV{$argkey} : $Flags{$argkey};
  445. $keyval = lc $keyval;
  446. printall ("Info: Picking up %$argkey%=$ENV{$argkey} from environment.\n") if $Verbose and !$Flags{$argkey} and $ENV{$argkey};
  447. next if $1 eq '!' and $keyval;
  448. next if $1 eq '=' and not $keyval;
  449. $_ = $4;
  450. }
  451. #
  452. # SUCCESS - reset the current result code to 0
  453. #
  454. if (/^SUCCESS\s*$/i) {
  455. $rc = 0;
  456. next;
  457. }
  458. #
  459. # Handle CHECKBUILDERRORs
  460. # $rc is set to 0, and cmdlist parsing continues, if the
  461. # errors in the check build.err file matches those in build.err
  462. #
  463. if (/^CHECKBUILDERRORS\s*(.*)$/i) {
  464. next unless $rc;
  465. next unless -r $BuildCheckFileName;
  466. $foo = "Checking $BuildErrorFileName "
  467. . "against $BuildCheckFileName...\n";
  468. printall $foo;
  469. $r = compare ($BuildErrorFileName, $BuildCheckFileName);
  470. if ($r) {
  471. $foo = "Comparison failed. Build error will be fatal.\n";
  472. printall $foo;
  473. } else {
  474. #
  475. # No new build errors have occurred so reset $rc.
  476. #
  477. $foo = "Error file hasn't changed. Build errors ignored.\n";
  478. printall $foo;
  479. $rc = 0;
  480. }
  481. next;
  482. }
  483. #
  484. # Handle CHECKFATALs
  485. #
  486. if (/^CHECKFATAL\s*(.*)$/i) {
  487. $checkcommand = $1;
  488. if ($rc) {
  489. $foo = "Failure of last command is fatal. Script aborted.\n";
  490. printall $foo;
  491. system "$checkcommand" if $checkcommand;
  492. last;
  493. }
  494. next;
  495. }
  496. #
  497. # Handle CHECKWARNs (like CHECKFATALs, but not fatal).
  498. #
  499. if (/^CHECKWARN\s*(.*)$/i) {
  500. $checkcommand = $1;
  501. if ($rc) {
  502. $foo = "WARNING: Last command failed.\n";
  503. printall $foo;
  504. system "$checkcommand" if $checkcommand;
  505. }
  506. next;
  507. }
  508. #
  509. # The built-in ECHO command
  510. #
  511. if (/^ECHO\s*(.*)$/i) {
  512. printall $1, "\n";
  513. next;
  514. }
  515. #
  516. # The built-in TESTFATAL command
  517. #
  518. if (/^TESTFATAL\s*(.*)$/i) {
  519. $rc = 1;
  520. printall $1, "\n";
  521. next;
  522. }
  523. #
  524. # The built-in QUIT command
  525. #
  526. if (/^QUIT\s*(.*)$/i) {
  527. printall "QUITTING: $1.\n";
  528. $rc = 0;
  529. last;
  530. }
  531. #
  532. # Run the command
  533. #
  534. printall "Running: $_\n" unless $skipchar;
  535. $rc = 0;
  536. $then = time();
  537. $rc = system $_ unless $Fake;
  538. $now = time();
  539. if ($rc) {
  540. $foo = sprintf "FAILURE. Returned 0x%x: %s\n", $rc, $_;
  541. printall $foo;
  542. }
  543. if (not $skipchar and not $Fake) {
  544. $t = $now - $then;
  545. ($h, $m, $s) = hms $t;
  546. printfall "Elapsed time: %5d seconds (%d:%02d:%02d) <%s>\n", $t, $h, $m, $s, $_;
  547. }
  548. }
  549. die $PGM, "Could not find RESUME <tag=$ResumeTag>\n" if $DoResume;
  550. if (not $Fake) {
  551. $t = time() - $begintime;
  552. ($h, $m, $s) = hms $t;
  553. printfall "Total Elapsed time: %5d seconds (%d:%02d:%02d)\n", $t, $h, $m, $s;
  554. }
  555. #
  556. # Close the logfile and copy it into the binplace directory.
  557. #
  558. close TIMEHISTFILE;
  559. close TIMELOGFILE;
  560. $src = $TimeLogFileName;
  561. $dst = $nttree . "\\build_logs\\";
  562. if (not $Fake and -r $src and -d $dst and -w $dst) {
  563. $rc = system("xcopy /y $src $dst");
  564. if ($rc) {
  565. $foo = sprintf "Warning... could not copy %s to %s\n", $src, $dst;
  566. print $PGM, $foo;
  567. }
  568. }
  569. #
  570. # Copy the sd change log to the binplace directory also.
  571. #
  572. $src = $ChangeLogFileName;
  573. if (not $Fake and -r $src and -d $dst and -w $dst) {
  574. $rc = system("xcopy /y $src $dst");
  575. if ($rc) {
  576. $foo = sprintf "Warning... could not copy %s to %s\n", $src, $dst;
  577. print $PGM, $foo;
  578. }
  579. }
  580. exit $rc;