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.

978 lines
34 KiB

  1. @rem ='
  2. @echo off
  3. REM ------------------------------------------------------------------
  4. REM
  5. REM SYMCD.cmd
  6. REM Create Symbol CD.
  7. REM
  8. REM Copyright (c) Microsoft Corporation. All rights reserved.
  9. REM
  10. REM ------------------------------------------------------------------
  11. perl -x "%~f0" %*
  12. goto :EOF
  13. REM ';
  14. #!perl
  15. use strict;
  16. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  17. use lib $ENV{RAZZLETOOLPATH};
  18. use PbuildEnv;
  19. use ParseArgs;
  20. use File::Basename;
  21. use IO::File;
  22. use Win32;
  23. use File::Path;
  24. use File::Copy;
  25. use IO::File;
  26. use Logmsg;
  27. use SymMake;
  28. use SymDelegate;
  29. #
  30. # SFS: SYMBOL FILESPECS
  31. # SFN: SYMBOL FILENAMES
  32. # ST: SYMBOL TOOL
  33. # SDIR: SYMBOL DIRECTORIES
  34. # SOPT: SYMBOL OPTIONS
  35. # COPT: COMMAND OPTIONS
  36. #
  37. my (%SFS, %SFN, %ST, %SDIR, %SOPT, %COPT);
  38. my ($NTPostBld, $BuildArch, $BuildType, $RazzleToolPath, $BuildLogs, $Lang, $CoverageBuild,
  39. $MungePath, $SymbolCD, $CabSize, $SymbolCDHandle, $Delegate, $ARCH, %DontShip, %SymBad
  40. );
  41. # my ($Project);
  42. my ($Symbol_Path_Creator);
  43. sub Usage { print<<USAGE; exit(1) }
  44. Create Symbol CD.
  45. SymCD [-l lang] [-m | -t]
  46. -l lang to specify which language
  47. -m run only munge public
  48. -t run all sections
  49. If you define Official_Build_Machine, the script creates the cabs.
  50. If not, the default does only munge public symbols.
  51. For example, if you only want to munge public symbols on official
  52. build machine, you can specify 'symcd.cmd /m'.
  53. PS:
  54. The 'Official_Build_Machine' is the environment variable to set
  55. to as a official build machine.
  56. USAGE
  57. sub Dependencies {
  58. if ( !open DEPEND, ">>$ENV{_NTPOSTBLD}\\..\\build_logs\\dependencies.txt" ) {
  59. errmsg("Unable to open dependency list file.");
  60. die;
  61. }
  62. print DEPEND<<DEPENDENCIES;
  63. \[$0\]
  64. IF {...} ADD {}
  65. DEPENDENCIES
  66. close DEPEND;
  67. exit;
  68. }
  69. my $qfe;
  70. #
  71. # parse the command line arguments
  72. #
  73. parseargs(
  74. 'l:' => \$Lang,
  75. # 'p:' => \$Project,
  76. 'm' => \$COPT{'NEED_MUNGE_PUBLIC'},
  77. 't' => \$COPT{'NEED_ALL'},
  78. '?' => \&Usage,
  79. 'plan' => \&Dependencies,
  80. 'qfe:' => \$qfe
  81. );
  82. if ( -f "$ENV{_NTPOSTBLD}\\..\\build_logs\\skip.txt" ) {
  83. if ( !open SKIP, "$ENV{_NTPOSTBLD}\\..\\build_logs\\skip.txt" ) {
  84. errmsg("Unable to open skip list file.");
  85. die;
  86. }
  87. while (<SKIP>) {
  88. chomp;
  89. exit if lc$_ eq lc$0;
  90. }
  91. close SKIP;
  92. }
  93. &main;
  94. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  95. #
  96. # main()
  97. # - symcd main function; according the $SOPT (symcd options) to do below steps,
  98. # 1. munge public symbols,
  99. # 2. create symbols.inf, symbols.cdf and symbols.ddf,
  100. # 3. according symbols(n).ddf and symbols.cdf, create symbols(n).cab and symbols.cat
  101. # 4. merge symbols(n).cab to symbols.cab
  102. # 5. sign symbols.cab and symbols.cat
  103. # PS. for 2 - 5, we create both update and full packages
  104. #
  105. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  106. sub main
  107. {
  108. my (%pkinfo, $symcd);
  109. my $pkinfoptr = \%pkinfo;
  110. &Initial_Variables();
  111. # If localize builds, do nothing
  112. if (!&IsUSA() and !$qfe) {
  113. logmsg "Language = $Lang. Do not create symbolcd.";
  114. return;
  115. }
  116. &Prepare_Reference_Files();
  117. &Munge_Public() if ($SOPT{'NEED_MUNGE_PUBLIC'});
  118. if ($SOPT{'NEED_CREATE_SYMBOLCD_TXT'}) {
  119. if ($SOPT{'USE_SYMLIST'}) {
  120. # &Create_SymbolCD_TXT_1_field();
  121. errmsg("Cannot find the symupd.txt");
  122. } else {
  123. Create_SymbolCD_TXT_3_fields();
  124. }
  125. }
  126. # create symbols.inf, symbols.cdf and symbols(n).ddf
  127. &Create_Make_File($pkinfoptr) if ($SOPT{'NEED_CREATE_MAKE_FILE'});
  128. undef $symcd; # Free memory; unload full symbolcd.txt
  129. &Create_SymbolCAT() if ($SOPT{'NEED_CREATE_SYMBOLCAT'});
  130. &Create_SymbolCAB($pkinfoptr) if ($SOPT{'NEED_CREATE_SYMBOLCAB'});
  131. $Delegate->Start() if (($SOPT{'NEED_CREATE_SYMBOLCAT'} ne '') || ($SOPT{'NEED_CREATE_SYMBOLCAB'} ne ''));
  132. while(!$Delegate->AllJobDone()) {$Delegate->CompleteAll(); sleep 5;}
  133. &Merge_SymbolCAB($pkinfoptr) if ($SOPT{'NEED_CREATE_SYMBOLCAB'});
  134. &Sign_Files($pkinfoptr) if ($SOPT{'NEED_SIGN_FILES'});
  135. }
  136. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  137. #
  138. # Munge public symbols
  139. #
  140. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  141. sub Munge_Public
  142. {
  143. my ($filename, $filepath, $fileext);
  144. my ($mySymbol, $mySymbolPath, $myBinary, $myMungePath, $oldMungePath, $newMungePath);
  145. my ($c_ext, @myCompOpt);
  146. my ($optCL, $optML, $optLINK);
  147. my @ppdirs = &Exists("$MungePath\\*.*");
  148. @myCompOpt = @ENV{qw(_CL_ _ML_ _LINK_)} if (lc$ENV{'_BuildArch'} eq 'x86');
  149. logmsg("Adding type info to some public pdb files for debugging...");
  150. for (@ppdirs) {
  151. next if (!-d);
  152. ($filename, $filepath, $fileext) = FileParse($_);
  153. if (length($fileext) ne '3') {
  154. errmsg("$_ name has the wrong format.");
  155. return;
  156. }
  157. $mySymbol = &SymbolPath("$NTPostBld\\symbols", "retail", "$filename\.$fileext");
  158. $mySymbolPath = &SymbolPath("$NTPostBld\\symbols", "retail");
  159. $myBinary = "$NTPostBld\\$filename\.$fileext";
  160. if (-f $mySymbol) {
  161. $myMungePath = "$MungePath\\$filename\.$fileext";
  162. ($oldMungePath, $newMungePath) = ("$myMungePath\\original", "$myMungePath\\updated");
  163. logmsg("Working on $filename\.$fileext");
  164. ## See if we need to do anything, or if the symbol file has already been updated
  165. ## If the symbol file passes symbol checking, with types present then don't update it.
  166. if (!&IsSymchkFailed($myBinary, $mySymbolPath, "/o")) {
  167. logmsg("Skipping $filename\.$fileext because it's public pdb already has type info in it.");
  168. next;
  169. }
  170. mkpath([$oldMungePath, $newMungePath]);
  171. ## See if the pdb, if it exists, in original matches the exe in binaries
  172. if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
  173. logmsg("Saving a copy of $filename\.pdb to $oldMungePath");
  174. copy($mySymbol, $oldMungePath) or errmsg("copy $mySymbol to $oldMungePath failed.");
  175. if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
  176. errmsg("cannot copy the correct pdb file to $oldMungePath\.");
  177. next;
  178. }
  179. }
  180. if (&Exists("$myMungePath\\*.*") > 0) {
  181. if (!copy("$oldMungePath\\$filename\.pdb", $newMungePath)) {
  182. errmsg("copy failed for $oldMungePath\\$filename\.pdb to $newMungePath\.");
  183. next;
  184. }
  185. logmsg("Pushing type info into the stripped $filename\.pdb");
  186. $c_ext = (-e "$myMungePath\\$filename\.c")? "c": "cpp";
  187. if (&IsVC7PDB("$newMungePath\\$filename\.pdb")) {
  188. logmsg("This is a vc7 pdb");
  189. @ENV{qw(_CL_ _ML_ _LINK_)} = ();
  190. } else {
  191. logmsg("This is a vc6 pdb");
  192. @ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt;
  193. }
  194. logmsg("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj");
  195. if (system("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj") > 0) {
  196. errmsg("cl /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb had errors.");
  197. next;
  198. }
  199. if (&IsSymchkFailed($myBinary, $newMungePath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
  200. errmsg("the munged $newMungePath\\$filename\.pdb doesn't match $myBinary.");
  201. next;
  202. }
  203. logmsg("Copying $newMungePath\\$filename\.pdb to $mySymbolPath\\$fileext");
  204. copy("$newMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
  205. if (&IsSymchkFailed($myBinary, $mySymbolPath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
  206. copy("$oldMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
  207. errmsg("the munged $newMungePath\\$filename\.pdb didn't get copied to $mySymbolPath\\$fileext\.");
  208. logmsg("Copying the original pdb back to $mySymbolPath\\$fileext");
  209. copy("$oldMungePath\\$filename\.$fileext", "$mySymbolPath\\$fileext") or do {
  210. errmsg("cannot get $filename\.$fileext symbols copied to $mySymbolPath\\$fileext\.");
  211. next;
  212. }
  213. }
  214. }
  215. } else {
  216. logmsg("Skipping $filename\.$fileext because $mySymbol does not exist.");
  217. }
  218. }
  219. @ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt if (lc$ENV{'_BuildArch'} eq 'x86');
  220. return;
  221. }
  222. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  223. #
  224. # Create symbolcd.txt from a 3 fields (bin,pri,pub) symupd.txt
  225. #
  226. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  227. sub Create_SymbolCD_TXT_3_fields
  228. {
  229. my ($fh, $bin, $pri, $pub, $binname, $binext, $pubname, $pubpath, $pubext, $pripath, $symbol, $availsym, $weight, $binnameext);
  230. my ($symdontship, $pubdontexist, $pubdontmatch, $badpubdontmatch, $symdorec, $dupsymdomatch, $dupsymdontmatch) = (0) x 7;
  231. my $duplicate = {};
  232. my (@results, @lists);
  233. local $_;
  234. logmsg("Examining the update list to compute the list of symbol files ...");
  235. # Read symupd.txt
  236. $fh = new IO::File $SFS{'SYMUPD'};
  237. while (<$fh>) {
  238. chomp;
  239. next if (!/\S/);
  240. ($bin, $pri, $pub) = split(/\,/, $_);
  241. # skip if not defined $pub
  242. if ($pub !~ /\S/) {
  243. logmsg("Skipping $bin - Reason \#1.");
  244. $pubdontexist++;
  245. next;
  246. }
  247. #
  248. # $weight = 2 if public symbol file path starts with symbols\retail
  249. # = 1 if public symbol file path starts with symbols, but not with symbols\retail
  250. # = 0 if public symbol file path doesn't start with symbols
  251. #
  252. # We will sort first by weight in order to give priority to symbol file that are in these directories.
  253. # This is to give priority to US symbols and symbols in symbols\retail over symbols for various languages.
  254. # Also it gives priority to symbols in symbols\retail versus symbols in other directories like symbols\idw.
  255. #
  256. # One case that this is trying to solve is the SP drop of spuninst.dll, update.exe and spcustom.dll where
  257. # all the languages work with the US symbols, but each language has a symbol file checked in that is different.
  258. # The symbols work, but the only difference is a path in the symbol file. This is happened during the BBT process
  259. # and the SP team checked in the actual symbols that got created for each language. In this case, they won't get
  260. # errors because symchk passes for all of them with the US symbol. We do the sort by weight in order to give
  261. # preference to the US symbol.
  262. #
  263. $weight = ($pub=~/^symbols[^\\]*\\(retail)?/i)?((defined $1)?2:1):0;
  264. push @lists, [$bin, $pri, $pub, $weight];
  265. }
  266. $fh->close();
  267. # Sort symupd.txt by symbols\retail first
  268. @results = sort {&sort_symupd($a,$b)} @lists;
  269. undef @lists;
  270. # Write to symbolcd.txt
  271. $SymbolCDHandle = new IO::File ">" . $SFS{'CD'};
  272. N1: for (@results) {
  273. # N1: while (<$fh>) {
  274. ($bin, $pri, $pub) = @{$_};
  275. ($binname, $binext) = (FileParse($bin))[0,2];
  276. ($pubname, $pubpath, $pubext) = FileParse($pub);
  277. ($binnameext) = (fileparse($bin))[0];
  278. $symbol = "$pubname\.$pubext";
  279. $pripath = (FileParse($pri))[1];
  280. # skip if the binary name is in symdontship.txt
  281. if (exists $DontShip{lc"$binname\.$binext"}) {
  282. logmsg("Skipping $bin - Reason \#2.");
  283. # logmsg("Skipping $bin because it\'s in symdontship.txt.");
  284. $symdontship++;
  285. next;
  286. }
  287. # skip if the public symbol file is not defined or is a directory
  288. if (!-f "$NTPostBld\\$pub") {
  289. logmsg("Skipping $bin - Reason \#1.");
  290. $pubdontexist++;
  291. next;
  292. }
  293. if (!-f "$NTPostBld\\$pri") {
  294. logmsg("Warnning - private symbols ($pri) for $bin does not exist.");
  295. }
  296. # skip if the public symbols does not match the binary
  297. if (&IsSymchkFailed("$NTPostBld\\$bin", "$NTPostBld\\$pubpath", $SOPT{'PUB_SYM_FLAG'})) {
  298. if (!exists $SymBad{lc(basename($bin))}) {
  299. errmsg("Error - symbols $pub does not match with $bin"); # because it\'s public pdb $pub does not match with its binary");
  300. $pubdontmatch++;
  301. } else {
  302. logmsg("Skipping $bin - Reason \#3."); # bad symbols for $bin because it\'s public pdb $pub does not match");
  303. $badpubdontmatch++;
  304. }
  305. next;
  306. }
  307. if (&IsSymchkFailed("$NTPostBld\\$bin", "$NTPostBld\\$pripath")) {
  308. logmsg("Warnning - private pdb ($pri) does not match with its binary $bin.");
  309. }
  310. if (exists $duplicate->{$binnameext}->{$symbol}) {
  311. if ((exists $duplicate->{$binnameext}->{$symbol}->{$bin}) ||
  312. (exists $duplicate->{$binnameext}->{$symbol}->{$pub})) {
  313. $symdorec++;
  314. next;
  315. }
  316. # Because we record binary name and symbol, we loop each key to get public symbol path
  317. for $availsym (keys %{$duplicate->{$binnameext}->{$symbol}}) {
  318. next if ($availsym !~ /(pdb|dbg)$/i); # ignore the binary
  319. #
  320. # If the file passes with the symbol we have already put into symbolcd.txt, then ignore this and don't
  321. # put the duplicate symbol into symbolcd.txt. Since symchk passes, don't give an error saying that there
  322. # are duplicates
  323. #
  324. if (!&IsSymchkFailed("$NTPostBld\\$bin", dirname("$NTPostBld\\$availsym"), $SOPT{'PUB_SYM_FLAG'})) {
  325. $dupsymdomatch++;
  326. next N1;
  327. }
  328. }
  329. if (exists $SymBad{lc(basename($bin))}) {
  330. logmsg("Skipping $bin - Reason \#3."); # bad symbols for $bin because it\'s public pdb $pub does not match");
  331. $badpubdontmatch++;
  332. next;
  333. }
  334. errmsg("Error - $bin has duplicate symbols ($pub) and mismatch with other symbols."); # $bin has the same symbol file $symbol with other binaries");
  335. $dupsymdontmatch++;
  336. next;
  337. }
  338. print $SymbolCDHandle "$bin,$pubname\.$pubext,$pub,$binext\n"; #$symbol,$subsympath,$installpathname\n";
  339. $duplicate->{$binnameext}->{$symbol}->{$bin} = 1;
  340. $duplicate->{$binnameext}->{$symbol}->{$pub} = 1;
  341. }
  342. $SymbolCDHandle->close();
  343. logmsg(sprintf("Reason 1: %d files skipped because its public symbols is not exist.", $pubdontexist));
  344. logmsg(sprintf("Reason 2: %d files skipped because its in symdontship.txt.", $symdontship));
  345. logmsg(sprintf("Reason 3: %d files skipped because the public symbol file does not match but listed in symbad.txt.", $badpubdontmatch));
  346. logmsg(sprintf("Reason 4: %d files skipped because it is a duplicate line in update list", $symdorec));
  347. logmsg(sprintf("Reason 5: %d files skipped because the binary match with other exist symbols", $dupsymdomatch));
  348. logmsg(sprintf("Error 1: %d files were errors because the public symbol file does not match with its binary.", $pubdontmatch));
  349. logmsg(sprintf("Error 2: %d files were errors because the public symbol file has duplicate install path with other symbols.", $dupsymdontmatch));
  350. logmsg(sprintf("Total files skipped + error = %d",
  351. $symdontship + $pubdontexist + $pubdontmatch + $badpubdontmatch + $symdorec + $dupsymdomatch + $dupsymdontmatch));
  352. }
  353. #
  354. # sort_symupd($a,$b)
  355. # - Sort first by the $weight (hight to low) and then second by the path and name of the binary in alphabetical order.
  356. # The second sort is equivalent to the order that symupd.txt is given to the script in the first place.
  357. # - we keep this function here for easy reference (see Create_SymbolCD_TXT_3_fields)
  358. #
  359. sub sort_symupd
  360. {
  361. return ($_[1]->[3] <=> $_[0]->[3]) or ($_[0]->[0] cmp $_[1]->[0]);
  362. }
  363. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  364. #
  365. # Create_Make_File($pkinfoptr)
  366. # - Create the make file (symbols.ddf, symbols.cdf and symbols.inf)
  367. #
  368. # IN: an empty packageinfo hash reference
  369. #
  370. # OUT: none
  371. #
  372. # REMARK: it store package information to $pkinfoptr
  373. # for example, $pkinfoptr->{'FULL'} =
  374. # 'CABNAME' = $SDIR{'FULL_CAB'}\\$SFN{'FULL_CAB'}
  375. # ...
  376. #
  377. # we store information to $pkinfoptr, because SymMake::Create_Symbols_DDF, SymMake::Create_Symbols_CDF,
  378. # and SymMake::Create_Symbols_IDF are working with $pkinfoptr
  379. #
  380. # and, $pkinfoptr->{'DDFLIST'} stored the ddf filenames we created from SymMake::Create_Symbols_DDF
  381. # according this, we can check the makecab process make the cab or not
  382. #
  383. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  384. sub Create_Make_File
  385. {
  386. my ($pkinfoptr) = @_;
  387. my ($symcd, $packagetype);
  388. if (defined $CoverageBuild) {
  389. logmsg("Coverage build ... skipping making the cab file");
  390. return;
  391. }
  392. logmsg("Creating the makefile and the DDF's for creating the cabs");
  393. $symcd = new SymMake $ARCH, $NTPostBld;
  394. for $packagetype (qw(FULL UPDATE)) {
  395. &SymMake::RegisterPackage($pkinfoptr, $packagetype, {
  396. 'CABNAME' => $SDIR{$packagetype . '_CAB'} . '\\' . $SFN{$packagetype . '_CAB'},
  397. 'DDFNAME' => $SDIR{$packagetype . '_DDF'} . '\\' . $SFN{$packagetype . '_DDF'},
  398. 'INFNAME' => $SDIR{$packagetype . '_INF'} . '\\' . $SFN{$packagetype . '_INF'},
  399. 'CDFNAME' => $SDIR{$packagetype . '_CDF'} . '\\' . $SFN{$packagetype . '_CDF'},
  400. 'CATNAME' => $SDIR{$packagetype . '_CAT'} . '\\' . $SFN{$packagetype . '_CAT'},
  401. 'CABSIZE' => $CabSize,
  402. });
  403. # register the package type ('FULL' or 'UPDATE')
  404. $symcd->{'PKTYPE'} = $packagetype;
  405. # read "$ARCH\\symbolcd\\symbolcd.txt" for 'FULL' and $ENV{_NTPOSTBLD}\\symbolcd\\symbolcd.txt for 'UPDATE'
  406. $symcd->ReadSource();
  407. }
  408. # create symbols.ddf, symbols.cdf and symbols.inf
  409. $symcd->Create_Symbols_DDF($pkinfoptr); # Return $pkinfoptr->{$packagetype}->{CABLIST}
  410. $symcd->Create_Symbols_CDF($pkinfoptr);
  411. $symcd->Create_Symbols_INF($pkinfoptr);
  412. undef $symcd;
  413. }
  414. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  415. #
  416. # Create_SymbolCAT($packagetype)
  417. # - add job to job queue for creating symbols.cat (symcab.cmd -f $SFN{'FULL_CDF'} -s $SDIR{'FULL_CDF'} -t 'CAT' -d $SDIR{'FULL_CAT'})
  418. # - register checkexistsub the verifying function
  419. #
  420. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  421. sub Create_SymbolCAT
  422. {
  423. my ($packagetype);
  424. for $packagetype (qw(FULL UPDATE)) {
  425. my $chkexistsub = &Check_Exist_File(
  426. $SDIR{$packagetype . '_CAT'} . '\\' . $SFN{$packagetype . '_CAT'} . '.CAT',
  427. $SDIR{$packagetype . '_CDF'} . '\\' . $SFN{$packagetype . '_CDF'} . '.CAT.LOG');
  428. logmsg("Delegating to create $SFN{$packagetype . '_CAT'}\.CAT");
  429. $Delegate->AddJob($packagetype . '_CATALOG',
  430. "$ST{'CAB'} " . join(' ',
  431. '-f' => $SFN{$packagetype . '_CDF'},
  432. '-s' => $SDIR{$packagetype . '_CDF'},
  433. '-t' => 'CAT',
  434. '-d' => $SDIR{$packagetype . '_CAT'}),
  435. $chkexistsub,
  436. 1); # priority
  437. }
  438. }
  439. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  440. #
  441. # Create_SymbolCAB($packagetype)
  442. # - add job to job queue for creating symbols(n).cab (symcab.cmd -f $ddfname -s $SDIR{'FULL_DDF'} -t 'CAB' -d $SDIR{'FULL_CAB'})
  443. # - register checkexistsub the verifying function
  444. #
  445. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  446. sub Create_SymbolCAB
  447. {
  448. my ($pkinfoptr) = shift;
  449. my ($packagetype, $ddfname, $cabname);
  450. for $packagetype (qw(FULL UPDATE)) {
  451. logmsg("Delegating to create $SFN{$packagetype . '_CAB'}\.CAB");
  452. for $ddfname (keys %{$pkinfoptr->{$packagetype}->{'DDFLIST'}}) {
  453. my $chkexistsub;
  454. next if (!-e $ddfname);
  455. $cabname = (FileParse($pkinfoptr->{$packagetype}->{'DDFLIST'}->{$ddfname}))[0];
  456. $ddfname = (FileParse($ddfname))[0];
  457. $chkexistsub = &Check_Exist_File(
  458. $SDIR{$packagetype . '_CAB'} . '\\' . $cabname . '.CAB',
  459. $SDIR{$packagetype . '_DDF'} . '\\' . $ddfname . '.CAB.LOG');
  460. $Delegate->AddJob($packagetype . $ddfname . '_CAB',
  461. "$ST{'CAB'} " . join(' ',
  462. '-f' => $ddfname,
  463. '-s' => $SDIR{$packagetype . '_DDF'},
  464. '-t' => 'CAB',
  465. '-d' => $SDIR{$packagetype . '_CAB'}),
  466. $chkexistsub,
  467. $ddfname);
  468. }
  469. }
  470. }
  471. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  472. #
  473. # Merge_SymbolCAB($pkinfoptr)
  474. # - merge the symbols(n).cab to symbols.cab with cabbench.exe
  475. #
  476. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  477. sub Merge_SymbolCAB
  478. {
  479. my ($pkinfoptr) = shift;
  480. my ($packagetype, $mergecommand, $cabname);
  481. $pkinfoptr->{'FULL'}->{'DDFLIST'} = {%{$pkinfoptr->{'FULL'}->{'DDFLIST'}}, %{$pkinfoptr->{'UPDATE'}->{'DDFLIST'}}};
  482. for $packagetype (qw(FULL UPDATE)) {
  483. # If there is no cab generated, we don't merge 'nothing'.
  484. next if (scalar(values %{$pkinfoptr->{$packagetype}->{'DDFLIST'}}) eq 0);
  485. logmsg("Merging cabs into $SFN{$packagetype . '_CAB'}\.cab");
  486. $mergecommand = "";
  487. for $cabname (sort values %{$pkinfoptr->{$packagetype}->{'DDFLIST'}}) {
  488. $mergecommand .= 'load ' . $cabname . ' merge ';
  489. }
  490. $mergecommand .= 'save ' . $SDIR{$packagetype . '_PKG'} . '\\' . $SFN{$packagetype . '_CAB'} . '.cab';
  491. # According the cabbench syntax, remove first merge
  492. $mergecommand =~ s/ merge / /;
  493. system("$ST{'BENCH'} $mergecommand");
  494. }
  495. }
  496. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  497. #
  498. # Sign_Files()
  499. # - sign the exist cab and cat files
  500. #
  501. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  502. sub Sign_Files {
  503. my ($packagetype, $myBuildType, $myBuildArch, $mypkgdir, $catfile, %signhash);
  504. logmsg("Test signing files on CD");
  505. for $packagetype (qw(FULL UPDATE)) {
  506. for $myBuildType (qw(fre chk)) {
  507. for $myBuildArch (qw(x86 amd64 ia64)) {
  508. $mypkgdir = &{$Symbol_Path_Creator->{$packagetype}}($SDIR{$packagetype . '_CD'} . '\\Symbols', $myBuildArch, $myBuildType);
  509. $catfile = $mypkgdir . $SFN{'CAT'} . '.CAT';
  510. if ((!exists $signhash{lc$mypkgdir}) && (-e $catfile)) {
  511. system("$ST{'SIGN'} $catfile");
  512. }
  513. }
  514. }
  515. }
  516. }
  517. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  518. #
  519. # Initial variables
  520. #
  521. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  522. sub Initial_Variables
  523. {
  524. # Set Variables
  525. $Lang = $ENV{'LANG'} if ("$Lang" eq "");
  526. $ENV{'LANG'} = $Lang;
  527. $BuildArch = $ENV{'_BuildArch'};
  528. $BuildType = $ENV{'_BuildType'};
  529. $NTPostBld = $ENV{'_NTPostBld'};
  530. # $NTPostBld = "d:\\Ins_Sym\\$Project\\$Lang";
  531. $MungePath = "$NTPostBld\\pp";
  532. $SymbolCD = "$NTPostBld\\SymbolCD";
  533. $RazzleToolPath = $ENV{'RazzleToolPath'};
  534. $BuildLogs = "$NTPostBld\\build_logs";
  535. $CabSize = 60000000;
  536. $SymbolCDHandle = '';
  537. $Delegate = new Delegate 3, $ENV{'NUMBER_OF_PROCESSORS'} * 4;
  538. # $ARCH = "\\\\arch\\archive\\ms\\windows\\windows_xp\\rtm\\2600\\$BuildType\\all\\$BuildArch\\pub";
  539. $ARCH = "d:\\Ins_Sym\\Win2k\\$Lang\\symbols";
  540. $Symbol_Path_Creator = {
  541. 'FULL' => \&Full_Package_Path,
  542. 'UPDATE' => \&Update_Package_Path
  543. };
  544. # SDIR: SYMBOL DIRECTORIES
  545. %SDIR = (
  546. 'SYMBOLCD' => $SymbolCD,
  547. 'PUBSYM' => "$NTPostBld\\Symbols",
  548. 'FULL_CD' => "$NTPostBld\\SymbolCD\\CD",
  549. 'FULL_PKG' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  550. 'FULL_INF' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  551. 'FULL_CAB' => "$SymbolCD\\CABs\\FULL",
  552. 'FULL_DDF' => "$SymbolCD\\DDF\\FULL",
  553. 'FULL_CDF' => "$SymbolCD\\DDF\\FULL",
  554. 'FULL_CAT' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  555. 'UPDATE_CD' => "$NTPostBld\\SymbolCD\\UPD",
  556. 'UPDATE_PKG' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  557. 'UPDATE_INF' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  558. 'UPDATE_CAB' => "$SymbolCD\\CABs\\UPDATE",
  559. 'UPDATE_DDF' => "$SymbolCD\\DDF\\UPDATE",
  560. 'UPDATE_CDF' => "$SymbolCD\\DDF\\UPDATE",
  561. 'UPDATE_CAT' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  562. );
  563. # SFS: SYMBOL FILESPECS
  564. %SFS = (
  565. 'CD' => $SDIR{'SYMBOLCD'} . '\\SymbolCD.txt',
  566. 'BLDNUM' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType) . "\\QFEnum.txt",
  567. 'LIST' => $SDIR{'SYMBOLCD'} . '\\SymList.txt',
  568. 'BAD' => $SDIR{'SYMBOLCD'} . '\\SymBad.txt',
  569. 'SYMUPD' => $SDIR{'SYMBOLCD'} . '\\SymUpd.txt',
  570. 'CAGENERR' => $SDIR{'SYMBOLCD'} . '\\cabgenerr.log',
  571. 'EXCLUDE' => $SDIR{'SYMBOLCD'} . '\\Exclude.txt',
  572. 'BINDIFF' => $BuildLogs . '\\bindiff.txt',
  573. 'WITHTYPES' => $SDIR{'SYMBOLCD'} . '\\SymbolsWithTypes.txt',
  574. 'DONTSHIP' => $SDIR{'SYMBOLCD'} . '\\SymDontShip.txt'
  575. );
  576. # SFN: SYMBOL FILENAMES
  577. %SFN = (
  578. 'FULL_INF' => 'Symbols',
  579. 'FULL_CAB' => 'Symbols',
  580. 'FULL_DDF' => 'Symbols',
  581. 'FULL_CDF' => 'Symbols',
  582. 'FULL_CAT' => 'Symbols',
  583. 'UPDATE_INF' => 'Symbols',
  584. 'UPDATE_CAB' => 'Symbols',
  585. 'UPDATE_DDF' => 'Symbols',
  586. 'UPDATE_CDF' => 'Symbols',
  587. 'UPDATE_CAT' => 'Symbols',
  588. );
  589. # ST: SYMBOL TOOL
  590. %ST = (
  591. 'MAKE' => "symmake.exe",
  592. 'PERL' => "perl.exe",
  593. 'CHECK' => "symchk.exe",
  594. 'BENCH' => "cabbench.exe",
  595. 'DUMP' => "pdbdump.exe",
  596. 'SIGN' => $RazzleToolPath . "\\ntsign.cmd",
  597. 'CAB' => $RazzleToolPath . "\\sp\\symcab.cmd"
  598. );
  599. # SOPT: SYMBOL OPTIONS
  600. #
  601. # the default option is doing all steps
  602. #
  603. %SOPT = (
  604. 'PUB_SYM_FLAG' => '/p',
  605. 'GOLD_BUILD' => 1,
  606. 'RUN_ALWAYS' => 1,
  607. 'NEED_MUNGE_PUBLIC' => undef,
  608. 'NEED_CREATE_SYMBOLCD_TXT' => undef,
  609. 'NEED_CREATE_MAKE_FILE' => 1,
  610. 'NEED_CREATE_SYMBOLCAT' => 1,
  611. 'NEED_CREATE_SYMBOLCAB' => 1,
  612. 'NEED_SIGN_FILES' => 1,
  613. 'NEED_FLAT_DIR' => 1,
  614. 'NEED_CLEAN_BUILD' => 1,
  615. 'FLAT_SYMBOL_PATH' => undef,
  616. 'USE_SYMLIST' => undef
  617. );
  618. if ((defined $COPT{'NEED_ALL'}) && (defined $COPT{'NEED_MUNGE_PUBLIC'})) {
  619. errmsg("Error options! Please specify either -m or -t");
  620. exit(1);
  621. }
  622. # if neither is official build machine, nor assign -t in command line,
  623. # or if is official build machine, but assign -m in command line,
  624. #
  625. # we will only munge public symbols
  626. #
  627. if (((!exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
  628. (!defined $COPT{'NEED_ALL'})) ||
  629. ((exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
  630. (defined $COPT{'NEED_MUNGE_PUBLIC'}))) {
  631. @SOPT{qw(NEED_MUNGE_PUBLIC
  632. NEED_CREATE_SYMBOLCD_TXT
  633. NEED_CREATE_MAKE_FILE
  634. NEED_CREATE_SYMBOLCAT
  635. NEED_CREATE_SYMBOLCAB
  636. NEED_SIGN_FILES)} = (1, undef, undef, undef, undef, undef);
  637. }
  638. # if ($SOPT{'NEED_CLEAN_BUILD'}) {
  639. # rmtree([@SDIR{qw(FULL_DDF FULL_CD FULL_CAB UPDATE_DDF UPDATE_CD UPDATE_CAB)}]);
  640. # }
  641. }
  642. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  643. #
  644. # Prepare_Reference_Files
  645. # - prepare the files we referenced in the program or for symbol testing
  646. # - we prepare below files
  647. # exclude.txt, symbolswithtypes.txt, symdontship.txt, symbad.txt
  648. #
  649. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  650. sub Prepare_Reference_Files
  651. {
  652. my ($exclude, $filename, @filelist, @filelist2);
  653. my ($symlistwithtypes, $symdontship, $symbad);
  654. # Make paths
  655. mkpath([values %SDIR]);
  656. # If GOLD build
  657. if ( ) {
  658. $ENV{'TEMP'} = "$ARCH\\symbolcd";
  659. mkpath([$ENV{'TEMP'}]);
  660. }
  661. return;
  662. # Exclude.txt
  663. if (!-e $SFS{'EXCLUDE'}) {
  664. $exclude = new IO::File $SFS{'EXCLUDE'}, 'w';
  665. copy($RazzleToolPath . '\\symdontship.txt', $exclude) or errmsg("copy symdontship.txt to $SFS{'EXCLUDE'} failed.");
  666. autoflush $exclude 1;
  667. copy($RazzleToolPath . '\\symbolswithtypes.txt', $exclude) or errmsg("copy symbolswithtypes.txt to $SFS{'EXCLUDE'} failed.");
  668. $exclude->close();
  669. }
  670. # SymbolsWithTypes.txt
  671. $symlistwithtypes = new IO::File "$RazzleToolPath\\symbolswithtypes.txt";
  672. chomp(@filelist = <$symlistwithtypes>);
  673. $symlistwithtypes->close();
  674. $symlistwithtypes = new IO::File $SFS{'WITHTYPES'}, 'w';
  675. for $filename (@filelist) {
  676. print $symlistwithtypes $NTPostBld . '\\' . $filename . "\n";
  677. }
  678. $symlistwithtypes->close();
  679. # SymDontShip.txt
  680. copy("$RazzleToolPath\\SymDontShip.txt", $SFS{'DONTSHIP'});
  681. $symdontship = new IO::File "$RazzleToolPath\\SymDontShip.txt", 'r';
  682. chomp(@filelist = <$symdontship>);
  683. @filelist2 = map({s/\s*\;.*$//;($_ eq '')?():lc$_;} @filelist);
  684. $symdontship->close();
  685. @DontShip{@filelist2} = (1) x ($#filelist2 + 1);
  686. # SymBad.txt
  687. copy("$RazzleToolPath\\SymBad.txt", $SFS{'BAD'});
  688. $symbad = new IO::File $SFS{'BAD'}, 'r';
  689. chomp(@filelist=<$symbad>);
  690. @filelist2 = map({s/\s*\;.*$//;($_ eq '')?():lc$_;} @filelist);
  691. $symbad->close();
  692. @SymBad{@filelist2} = (1) x ($#filelist2 + 1);
  693. # QFEnum.txt
  694. # we put current build number into the symbol install directory for the Customer Support CD
  695. # we could use it to determine the which build the symbols CD belong to
  696. # copy("$NTPostBld\\congeal_scripts\\__qfenum__", $SFS{'BLDNUM'}) if (-e "$NTPostBld\\congeal_scripts\\__qfenum__");
  697. if (-e $SFS{'SYMUPD'}) {
  698. $SOPT{'USE_SYMLIST'} = undef;
  699. } elsif (-e $SFS{'LIST'}) {
  700. $SOPT{'USE_SYMLIST'} = 'yes';
  701. } elsif ($SOPT{'NEED_CREATE_MAKE_FILE'}) {
  702. logmsg("Either $SFS{'SYMUPD'} or $SFS{'LIST'} need to be provided.");
  703. logmsg("No update. exit.");
  704. exit;
  705. }
  706. }
  707. ####################################################################################
  708. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  709. #
  710. # Small Subroutine
  711. #
  712. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  713. #
  714. # IsSymchkFailed($binary, $symbol, $extraopt)
  715. # - call symchk.exe to verify $binary matches with $symbol
  716. #
  717. sub IsSymchkFailed {
  718. my ($binary, $symbol, $extraopt) = @_;
  719. my ($fh, $record_error, $record_log, $result);
  720. local $_;
  721. if (defined $extraopt) {
  722. if ($extraopt =~ /2\>/) {
  723. $record_error = 1;
  724. }
  725. if ($extraopt =~ /[^2]\>/) {
  726. $record_log = 1;
  727. }
  728. $extraopt =~ s/2?\>.*$//g;
  729. }
  730. $fh = new IO::File "$ST{'CHECK'} /t $binary /s $symbol $extraopt |";
  731. while (<$fh>) {
  732. chomp;
  733. $result = $1 if /FAILED files = (\d+)/;
  734. logmsg($_) if ($record_log);
  735. logmsg($_) if (($record_error) && (/^ERROR/i));
  736. }
  737. undef $fh;
  738. return $result;
  739. }
  740. #
  741. # SymbolPath($root, $subdir, $filename)
  742. # - return the symbol path for the binary
  743. #
  744. sub SymbolPath
  745. {
  746. my ($root, $subdir, $filename) = @_;
  747. $root .= "\\$subdir" if (!$SOPT{'FLAT_SYMBOL_PATH'});
  748. if (defined $filename) {
  749. $filename =~ /\.([^\.]+)$/;
  750. $root .= "\\$1\\$`";
  751. return "$root\.pdb" if (-e "$root\.pdb");
  752. return "$root\.dbg" if (-e "$root\.dbg");
  753. $root .= ".pdb";
  754. }
  755. return $root;
  756. }
  757. #
  758. # Full_Package_Path($root, $myarch, $mytype)
  759. # - for compatible reason, we create a function to construct the path of the symbols.exe of the full package
  760. #
  761. sub Full_Package_Path
  762. {
  763. my ($root, $myarch, $mytype) = @_;
  764. $mytype =~ s/fre/retail/ig;
  765. $mytype =~ s/chk/debug/ig;
  766. return "$root\\$myarch\\$mytype"; # temporary
  767. }
  768. #
  769. # Update_Package_Path($root, $myarch, $mytype)
  770. # - for compatible reason, we create a function to construct the path of the symbols.exe of the update package
  771. #
  772. sub Update_Package_Path
  773. {
  774. my ($root, $myarch, $mytype) = @_;
  775. return $root; # \\$myarch\\$mytype"; # temporary
  776. }
  777. #
  778. # IsVC7PDB($pdbspec)
  779. # - because the MD5 hash value is 0000-0000-0000-000000000000 for the symbols built by VC6 or older
  780. # - we can use it to determine the pdb is VC7 or not
  781. #
  782. sub IsVC7PDB {
  783. my ($pdbspec) = shift;
  784. my $fh = new IO::File "$ST{'DUMP'} $pdbspec hdr |";
  785. local $_;
  786. while (<$fh>) {
  787. return 0 if /0000-0000-0000-000000000000/i;
  788. }
  789. return 1;
  790. }
  791. #
  792. # Check_Exist_File($filename, $logfile)
  793. # - this is a function generator, which generates a function for checking the $filename exist or not
  794. # - it also check if the $logfile has 'ERROR:' in it
  795. #
  796. sub Check_Exist_File
  797. {
  798. my ($filename, $logfile) = @_;
  799. return sub {
  800. if (-e $filename) {
  801. return 1;
  802. } else {
  803. my $fh = new IO::File $logfile;
  804. for (<$fh>) {
  805. chomp;
  806. next if (!/.+ERROR\: /i);
  807. errmsg("Error - $'");
  808. }
  809. $fh->close();
  810. logmsg("$filename did not get created.");
  811. return 0;
  812. }
  813. };
  814. }
  815. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  816. #
  817. # Common Subroutine
  818. #
  819. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  820. sub FileParse
  821. {
  822. my ($name, $path, $ext) = fileparse(shift, '\.[^\.]+$');
  823. $ext =~ s/^\.//;
  824. return $name, $path, $ext;
  825. }
  826. sub IsUSA
  827. {
  828. # return (lc$ENV{'lang'} eq 'usa');
  829. return 1;
  830. }
  831. sub Exists
  832. {
  833. my @list = glob(shift);
  834. return (wantarray)?@list:$#list + 1;
  835. }
  836. 1;
  837. __END__