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.

461 lines
14 KiB

  1. @REM -----------------------------------------------------------------
  2. @REM
  3. @REM PdbSrcStream.cmd - skupec
  4. @REM Adds source depot information to private PDBs.
  5. @REM
  6. @REM Copyright (c) Microsoft Corporation. All rights reserved.
  7. @REM
  8. @REM -----------------------------------------------------------------
  9. @perl -x "%~f0" %*
  10. @goto :EOF
  11. #!perl
  12. #line 13
  13. ################################################################################
  14. #
  15. # Required packages
  16. #
  17. ################################################################################
  18. use strict;
  19. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  20. use lib $ENV{RAZZLETOOLPATH};
  21. use PbuildEnv;
  22. use Logmsg qw(errmsg logmsg wrnmsg);
  23. use ParseArgs;
  24. use BuildName;
  25. use File::Spec;
  26. use File::Temp qw(tempfile);
  27. ################################################################################
  28. #
  29. # Global vars
  30. #
  31. ################################################################################
  32. sub TRUE {return(1);} # BOOLEAN TRUE
  33. sub FALSE {return(0);} # BOOLEAN FALSE
  34. # This program's base filename
  35. my $program;
  36. # Name of our lock file
  37. my $lock;
  38. # Generic loop vars
  39. my $lpCount = 0;
  40. my $i = 0;
  41. # Temp var for splitting strings into
  42. my @data;
  43. # Hash for processing nt.have file
  44. my %NtHave;
  45. # Path to recurse for processing symbols
  46. my $SymbolsPath;
  47. # Default nt.have file
  48. my $NT_HAVE = "$ENV{_NTPOSTBLD}\\build_logs\\sourcefilelists.txt";
  49. # Counting var for indexing server variables
  50. my $cnt = "00";
  51. # Hashes for mapping root->server<->var
  52. my %SERVER_TO_VAR;
  53. my %VAR_TO_SERVER;
  54. my %PATH_TO_SERVER;
  55. ################################################################################
  56. #
  57. # Create .tmp file so postbuild.cmd knows we're running.
  58. #
  59. ################################################################################
  60. BEGIN {
  61. # name of this script w/o the full path
  62. $program = substr($0, rindex($0, "\\")+1);
  63. $lock = substr($program, 0, rindex($program, ".")) . ".tmp";
  64. if (! open(hLogFile, ">$ENV{TEMP}\\$lock") ) {
  65. errmsg("Can't open $ENV{TEMP}\\$lock for writing: $! - Exiting");
  66. exit(-1);
  67. }
  68. print (hLogFile "1");
  69. close (hLogFile);
  70. }
  71. ################################################################################
  72. #
  73. # Unsure we always remove our temp file when exiting so postbuild.cmd knows the
  74. # script has finished
  75. #
  76. ################################################################################
  77. END {
  78. unlink ("$ENV{TEMP}\\$lock");
  79. }
  80. ################################################################################
  81. #
  82. # Script usage
  83. #
  84. ################################################################################
  85. sub Usage { print<<USAGE; exit(1) }
  86. Usage: $program [-l <language>] [<directory>]
  87. -l <language> - Optional. Default is USA. If a language other than USA
  88. is provided, the script exits because this process should only be done
  89. once per build.
  90. <directory> - Optional. The directory to recurse for processing symbols.
  91. Default is %_NTPOSTBLD%\\symbols.pri
  92. USAGE
  93. ################################################################################
  94. #
  95. # This script does nothing for incremental builds since we can't guarentee that
  96. # the source file lists were correctly updated first. Since the rebuilding of
  97. # a binary will cause the PDB to also be regenerated, we already know that the
  98. # PDB has an empty source stream. By not running, it'll stay empty which means
  99. # the streams for any build should never end up in an inconsistent state.
  100. #
  101. ################################################################################
  102. if ( -e "$ENV{_NTTREE}\\build_logs\\bindiff.txt" ) {
  103. logmsg("PdbSrcStreams are not incremental build capable.");
  104. exit(0);
  105. }
  106. ################################################################################
  107. #
  108. # Main code
  109. #
  110. ################################################################################
  111. ################################################################################
  112. #
  113. # Handle the command line options
  114. #
  115. ################################################################################
  116. for ($lpCount=0; $lpCount <= ($#ARGV); $lpCount++) {
  117. SWITCH: {
  118. # NOTE: PbuildEnv.pm handles the -l <lang> parameter
  119. if ((substr($ARGV[$lpCount],0,1) eq "-") or (substr($ARGV[$lpCount],0,1) eq "/")) {
  120. for ($i=1;$i<length($ARGV[$lpCount]);$i++) {
  121. exit(Usage()) if uc(substr($ARGV[$lpCount],$i,1)) eq "?";
  122. exit(Usage()) if uc(substr($ARGV[$lpCount],$i,1)) eq "H";
  123. }
  124. } else {
  125. $SymbolsPath = $ARGV[$lpCount];
  126. }
  127. 1; #Last line should do nothing
  128. }
  129. }
  130. ################################################################################
  131. #
  132. # Test for all conditions that require us to terminate early.
  133. #
  134. ################################################################################
  135. # nice exit if not defined
  136. if (! (defined $ENV{OFFICIAL_BUILD_MACHINE}||defined $ENV{PDB_SRC_STREAM}) ) {
  137. logmsg("PdbSrcStreams only runs on OFFICIAL_BUILD_MACHINES by default. ".
  138. "Set PDB_SRC_STREAM in your environment to override this behavior.\n");
  139. exit(0);
  140. }
  141. # Required env. vars that don't get a special error message
  142. foreach ( qw(_NTPOSTBLD) ) {
  143. if (! defined $ENV{$_} ) {
  144. errmsg("Missing required environment variable '$_'. Terminating.\n");
  145. exit(-1);
  146. }
  147. }
  148. # %LANG% is set by PBuildEnv.pm
  149. if ( defined $ENV{LANG} ) {
  150. if (uc $ENV{LANG} ne "USA") {
  151. logmsg("This script is only for US builds - Exiting");
  152. exit(0);
  153. }
  154. } else {
  155. # Assume %LANG%==USA
  156. }
  157. # allow default symbol path override
  158. if ($SymbolsPath eq "") {
  159. $SymbolsPath = "$ENV{_NTPOSTBLD}\\symbols.pri";
  160. }
  161. if (! -e "$SymbolsPath" ) {
  162. errmsg("$SymbolsPath doesn't exist! - exiting.");
  163. exit(-1);
  164. }
  165. ################################################################################
  166. #
  167. # Make hash to resolve directories to servers. Modifies globals.
  168. #
  169. ################################################################################
  170. GetNtSrv();
  171. ################################################################################
  172. #
  173. # Allow override of nt.have file
  174. #
  175. ################################################################################
  176. if (defined $ENV{NT_HAVE}) {
  177. $NT_HAVE = $ENV{NT_HAVE};
  178. }
  179. ################################################################################
  180. #
  181. # Slurp nt.have into a hash in memory
  182. #
  183. ################################################################################
  184. if ( ! open(hFILE, "$NT_HAVE") ) {
  185. errmsg("Can't open $NT_HAVE ($!) - exiting");
  186. exit(-1);
  187. }
  188. while (<hFILE>) {
  189. chomp;
  190. @data = split(/\s+-\s+/, $_);
  191. $NtHave{uc $data[1]} = $data[0];
  192. }
  193. close(hFILE);
  194. ################################################################################
  195. #
  196. # Process the PDBs
  197. #
  198. ################################################################################
  199. RecurseDirectoryTree("$SymbolsPath", \&StuffSrcIntoPdb);
  200. ################################################################################
  201. #
  202. # Subroutines - keep sorted by name!
  203. #
  204. ################################################################################
  205. # --------------------------------------------------------------------------
  206. # Populates globals with data about the SD servers
  207. # --------------------------------------------------------------------------
  208. sub GetNtSrv {
  209. RecurseDirectoryTree("$ENV{_NTPOSTBLD}\\build_logs\\sourcefilelists",
  210. \&GetServers);
  211. %VAR_TO_SERVER = reverse %SERVER_TO_VAR;
  212. }
  213. # --------------------------------------------------------------------------
  214. # Callback for GetNtSrv() directory recursion
  215. # --------------------------------------------------------------------------
  216. sub GetServers {
  217. my $file = shift;
  218. return unless (-e "$file");
  219. return if (-d "$file");
  220. return unless ($file =~ /\.txt$/);
  221. local *hFILE;
  222. open(hFILE, "$file");
  223. my $text = <hFILE>;
  224. close(hFILE);
  225. chomp($text);
  226. my $basename = substr($file, rindex($file, "\\")+1);
  227. $basename =~ s/\.txt$//i;
  228. my $root = "$ENV{SDXROOT}\\$basename";
  229. my ($domain, $server) = split(/\s+/, $text);
  230. # Root depot is a special case
  231. if ($root =~ /ROOT$/i) {
  232. $root =~ s/\\ROOT$//i;
  233. }
  234. # All fields must be defined
  235. if ( defined $domain && defined $server ) {
  236. if (! defined $SERVER_TO_VAR{lc $server}) {
  237. $server =~ /^(.*?)(depot)?\./i;
  238. my $var_name = "WIN_".uc($1);
  239. $SERVER_TO_VAR{lc $server} = "$var_name";
  240. }
  241. if (! defined $PATH_TO_SERVER{uc $root} ) {
  242. $PATH_TO_SERVER{uc $root} = lc $server;
  243. }
  244. } else {
  245. wrnmsg("can't parse $file - skipping.");
  246. }
  247. }
  248. # --------------------------------------------------------------------------
  249. # Recurses a directory tree and invokes the callback routine for
  250. # every file and directory found (except '.' and '..')
  251. # --------------------------------------------------------------------------
  252. sub RecurseDirectoryTree {
  253. # setup
  254. my $TreeRoot = shift;
  255. $TreeRoot =~ s/\\$//; # cut possible trailing '\'
  256. my $Function = shift;
  257. my $file;
  258. my @files;
  259. local *hDIR;
  260. if (!opendir(hDIR, "$TreeRoot") ) {
  261. errmsg("Cannot open $TreeRoot\n");
  262. return(0);
  263. }
  264. #
  265. # Loop through all entries
  266. #
  267. foreach $file ( readdir(hDIR) ) {
  268. next if ($file eq "."); # skip '.'
  269. next if ($file eq ".."); # skip '..'
  270. $file = "$TreeRoot\\$file"; # add parent path
  271. &$Function("$file"); # invoke callback
  272. if (-d "$file" ){ # recurse directories
  273. RecurseDirectoryTree("$file", \&$Function);
  274. }
  275. }
  276. # cleanup
  277. closedir(hDIR);
  278. }
  279. # --------------------------------------------------------------------------
  280. # Returns the file+sd_spec or empty array
  281. # --------------------------------------------------------------------------
  282. sub ResolveFileToSD {
  283. my @SD_SPEC;
  284. my $file = shift;
  285. if ( defined $NtHave{uc $file}) {
  286. @SD_SPEC = ($file, $NtHave{uc $file});
  287. } else {
  288. @SD_SPEC = ();
  289. }
  290. return(@SD_SPEC);
  291. }
  292. # --------------------------------------------------------------------------
  293. # Processes a single PDB
  294. # --------------------------------------------------------------------------
  295. sub StuffSrcIntoPdb {
  296. my $line;
  297. my $file = shift;
  298. return if ($file !~ /\.pdb$/i);
  299. return if (! -e "$file");
  300. return if ( -d "$file");
  301. return if (! -W "$file");
  302. my @lines_to_stuff = ();
  303. my %var_references = ();
  304. if (! open(hCV, "cvdump -sf $file|") ) {
  305. printf("WARN $0: Can't call cvdump! ($!)\n");
  306. return();
  307. }
  308. LOOP: while ( $line = <hCV> ) {
  309. last LOOP if ($line =~ /^\*\*\* SOURCE FILES/);
  310. }
  311. while ($line = <hCV>) {
  312. my @file_spec = ();
  313. chomp $line;
  314. next if ($line =~ m/^\s*$/);
  315. #
  316. # Translate the local file path to a source depot path and revision
  317. #
  318. @file_spec = ResolveFileToSD($line);
  319. #
  320. # Make sure an empty array wasn't returned
  321. #
  322. if (@file_spec && $#file_spec == 1) {
  323. #
  324. # Loop through the SD servers in reverse order until we find one
  325. # who's local root path matches the root path of the current file.
  326. #
  327. foreach (reverse sort keys %PATH_TO_SERVER) {
  328. if ($file_spec[0] =~ /^\Q$_\E/i) {
  329. #
  330. # Write the source line into the format:
  331. # <LocalPath>*<ServerVariable>*<SourceDepotPath>
  332. #
  333. my $sdvar = $SERVER_TO_VAR{lc $PATH_TO_SERVER{$_}};
  334. if (! defined $sdvar ) {
  335. $sdvar = $PATH_TO_SERVER{$_};
  336. }
  337. $file_spec[1] =~ /#(\d*)$/;
  338. my $vernum = $1;
  339. $file_spec[1] =~ s/#\d*$//;
  340. $file_spec[1] =~ s/^\/\/depot\///i;
  341. # second version of the SD string
  342. push(@lines_to_stuff, "$file_spec[0]*$sdvar*$file_spec[1]*$vernum");
  343. $var_references{$sdvar} = 1;
  344. @file_spec = ();
  345. }
  346. }
  347. }
  348. }
  349. close(hCV);
  350. #
  351. # Only write the stream if we found at least one file spec.
  352. #
  353. if ( @lines_to_stuff > 0 ) {
  354. #
  355. # Use a temp file to create the stream data
  356. #
  357. my $TempFile;
  358. (undef, $TempFile) = tempfile("PdbXXXXXX", SUFFIX=>".stream", OPEN => 0, DIR => "$ENV{TEMP}");
  359. if (! open(hTEMP, ">$TempFile") ) {
  360. logmsg("Can't open tempfile for $file ($!) - skipping\n");
  361. return(FALSE);
  362. }
  363. #
  364. # List each server
  365. #
  366. printf(hTEMP "SRCSRV: ini ------------------------------------------------\n");
  367. # version control system string to identify the system to the user
  368. printf(hTEMP "VERSION=1\n");
  369. printf(hTEMP "VERCTRL=Source Depot\n");
  370. printf(hTEMP "SRCSRV: variables ------------------------------------------\n");
  371. printf(hTEMP "SRCSRVTRG=%%targ%%\\%%var2%%\\%%fnbksl%%(%%var3%%)\\%%var4%%\\%%fnfile%%(%%var1%%)\n");
  372. printf(hTEMP "SRCSRVCMD=sd.exe -p %%fnvar%%(%%var2%%) print -o %%srcsrvtrg%% -q %%depot%%/%%var3%%#%%var4%%\n");
  373. printf(hTEMP "DEPOT=//depot\n");
  374. foreach (sort keys %VAR_TO_SERVER) {
  375. printf(hTEMP "$_=$VAR_TO_SERVER{$_}\n") if (defined $var_references{$_});
  376. }
  377. printf(hTEMP "SRCSRV: source files ---------------------------------------\n");
  378. #
  379. # Now write the file information
  380. #
  381. foreach (@lines_to_stuff) {
  382. printf(hTEMP "$_\n");
  383. }
  384. printf(hTEMP "SRCSRV: end ------------------------------------------------\n");
  385. close(hTEMP);
  386. system("pdbstr -w -i:$TempFile -p:$file -s:srcsrv");
  387. unlink("$TempFile");
  388. }
  389. }