|
1 #! /usr/bin/perl |
|
2 # Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # This script scans a directory and determines the category of all exported |
|
16 # files which would be produced if all bld.inf files present were built. |
|
17 # Note that EPOCROOT needs to be set for this to resolve the destination of |
|
18 # the exports correctly in most cases. |
|
19 # |
|
20 # |
|
21 |
|
22 use KitStandardLocations; |
|
23 my $localEpocRoot = "$OutputDir\\generic\\"; |
|
24 $pathToE32Variant = $localEpocRoot."epoc32\\tools"; |
|
25 unshift (@INC, $pathToE32Variant); # add this to the @INC list of library paths |
|
26 |
|
27 # set up environment for E32Variant initialisation & preserve old value |
|
28 my $oldEpocRoot = $ENV{EPOCROOT}; |
|
29 $ENV{EPOCROOT} = $localEpocRoot; |
|
30 require E32Variant; |
|
31 # restore environment |
|
32 $ENV{EPOCROOT} = $oldEpocRoot; |
|
33 |
|
34 |
|
35 $noSource = 0; # Set to 1 to run with only .inf files and DISTRIBUTION.POLICY files present |
|
36 $noMissing = 0; # Set to 1 to ignore errors about missing source files (only valid if $noSource is 0, obviously) - to ignore broken bld.inf files |
|
37 |
|
38 # Discriminate between '-options' and 'parameters' |
|
39 my @parms = grep(!/^-/,@ARGV); |
|
40 my @options = grep(/^-/,@ARGV); |
|
41 |
|
42 $bldinf = 0; |
|
43 $restrict = 0; |
|
44 $cats = {}; |
|
45 $export = 0; |
|
46 $zorcdrive = 0; |
|
47 my $sourceRoot; |
|
48 my $option; |
|
49 my $path; |
|
50 my $script; |
|
51 |
|
52 # Parse options first |
|
53 my $index=0; |
|
54 while ($index < scalar(@ARGV)) |
|
55 { |
|
56 $option = $ARGV[$index]; |
|
57 |
|
58 if (lc($option) =~ /^-c/) |
|
59 { |
|
60 # Categories - record each category entered |
|
61 if (lc($option) eq "-c") |
|
62 { |
|
63 $index++; |
|
64 if ($index < scalar(@ARGV)) |
|
65 { |
|
66 $option = $ARGV[$index]; |
|
67 } |
|
68 else |
|
69 { |
|
70 die "Option '-c' has missing parameters\n"; |
|
71 } |
|
72 |
|
73 if ($option =~ /^-/) |
|
74 { |
|
75 die "Option '-c' has missing parameters\n"; |
|
76 } |
|
77 } |
|
78 else |
|
79 { |
|
80 $option =~ s/^-c//i; |
|
81 } |
|
82 |
|
83 foreach my $char (split(//,$option)) |
|
84 { |
|
85 if ($char =~ /[ABCDEFGXIOT]/) |
|
86 { |
|
87 $cats->{lc($char)} = 1; |
|
88 } |
|
89 else |
|
90 { |
|
91 die "Category $char from '$option' is not a valid IPR category\n"; |
|
92 } |
|
93 } |
|
94 } |
|
95 elsif (lc($option) eq "-bldinf") |
|
96 { |
|
97 # Report bldinfs |
|
98 $bldinf = 1; |
|
99 } |
|
100 elsif (lc($option) eq "-export") |
|
101 { |
|
102 # Include export restricted files |
|
103 $export = 1; |
|
104 } |
|
105 elsif (lc($option) eq "-restricted") |
|
106 { |
|
107 # Include only export restricted files |
|
108 $restrict = 1; |
|
109 } |
|
110 elsif (lc($option) =~ /^-src/) |
|
111 { |
|
112 # Source path |
|
113 if (lc($option) eq "-src") |
|
114 { |
|
115 $index++; |
|
116 if ($index < scalar(@ARGV)) |
|
117 { |
|
118 $option = $ARGV[$index]; |
|
119 } |
|
120 else |
|
121 { |
|
122 die "Option '-src' is missing its parameter\n"; |
|
123 } |
|
124 |
|
125 if ($option =~ /^-/) |
|
126 { |
|
127 die "Option '-src' is missing its parameter\n"; |
|
128 } |
|
129 } |
|
130 else |
|
131 { |
|
132 $option =~ s/^-src//i; |
|
133 } |
|
134 |
|
135 $sourceRoot = $option; |
|
136 } |
|
137 elsif (lc($option) =~ /^-genbuild/) |
|
138 { |
|
139 # Genbuild compatible script |
|
140 if (lc($option) eq "-genbuild") |
|
141 { |
|
142 $index++; |
|
143 if ($index < scalar(@ARGV)) |
|
144 { |
|
145 $option = $ARGV[$index]; |
|
146 } |
|
147 else |
|
148 { |
|
149 die "Option '-genbuild' is missing its parameter\n"; |
|
150 } |
|
151 |
|
152 if ($option =~ /^-/) |
|
153 { |
|
154 die "Option '-genbuild' is missing its parameter\n"; |
|
155 } |
|
156 } |
|
157 else |
|
158 { |
|
159 $option =~ s/^-genbuild//i; |
|
160 } |
|
161 |
|
162 $script = $option; |
|
163 } |
|
164 elsif (lc($option) =~ /^-/) |
|
165 { |
|
166 help(); |
|
167 print "\nOption \"$option\" not recognised.\n"; |
|
168 exit(0); |
|
169 } |
|
170 else |
|
171 { |
|
172 if (defined($path)) |
|
173 { |
|
174 die "Only one path can be scanned at a time (not '$path' and '$option')\n"; |
|
175 } |
|
176 else |
|
177 { |
|
178 $path = $option; |
|
179 } |
|
180 } |
|
181 |
|
182 $index++; |
|
183 } |
|
184 |
|
185 if ($export && $restrict) |
|
186 { |
|
187 # -restricted overrides -export |
|
188 $export = 0; |
|
189 } |
|
190 |
|
191 if (!defined ($sourceRoot)) |
|
192 { |
|
193 help(); |
|
194 print "\nexportipr.pl expects a source path to the source tree as a parameter\n"; |
|
195 exit(0); |
|
196 } |
|
197 |
|
198 if (defined($path) && defined($script)) |
|
199 { |
|
200 help(); |
|
201 print "\nexportipr.pl can only scan a path or parse a script, not both\n"; |
|
202 exit(0); |
|
203 } |
|
204 |
|
205 # read in macros defined in this build |
|
206 my $variantMacros = ""; |
|
207 foreach my $macro (E32Variant::Variant_GetMacroList()) |
|
208 { |
|
209 $macro =~ s/\s+$//; # strip trailing spaces |
|
210 $variantMacros = $variantMacros . " -D" . $macro ; |
|
211 } |
|
212 |
|
213 if (defined($script)) |
|
214 { |
|
215 parse($script, $sourceRoot, $variantMacros); |
|
216 } |
|
217 else |
|
218 { |
|
219 $path =~ s/[\/\\]+$//; |
|
220 |
|
221 scan($path, $sourceRoot, $variantMacros); |
|
222 } |
|
223 |
|
224 exit(1); |
|
225 |
|
226 # Recursively check a path for bld.inf files and process them. |
|
227 sub scan($$$) |
|
228 { |
|
229 my ($aPath, $aRoot, $variantMacros) = @_; |
|
230 |
|
231 opendir(DIR, $aRoot."/".$aPath) or die "Path $aRoot/$aPath not found!\n"; |
|
232 |
|
233 foreach my $entry (readdir(DIR)) |
|
234 { |
|
235 if (($entry ne ".") and ($entry ne "..")) |
|
236 { |
|
237 if (-d $aRoot."/".$aPath."/".$entry) |
|
238 { scan($aPath."/".$entry, $aRoot, $variantMacros); } |
|
239 elsif (lc($entry) eq "bld.inf") |
|
240 { |
|
241 getExports($aPath."/".$entry, $aRoot, $variantMacros); |
|
242 } |
|
243 } |
|
244 } |
|
245 |
|
246 closedir(DIR); |
|
247 } |
|
248 |
|
249 # Scan a genbuild script file for bld.inf files and process them. |
|
250 sub parse($$$) |
|
251 { |
|
252 my ($aScript, $aRoot, $variantMacros) = @_; |
|
253 |
|
254 open(SCRIPT, $aScript) or die "Genbuild script '$aScript' not found\n"; |
|
255 |
|
256 foreach my $line (<SCRIPT>) |
|
257 { |
|
258 chomp($line); |
|
259 |
|
260 $line =~ s/#.*$//; # Remove comments |
|
261 $line =~ s/^\s+//; # Remove preceding space |
|
262 |
|
263 if ($line ne "") |
|
264 { |
|
265 if ($line =~ /^</) |
|
266 { |
|
267 # Ignore <option> or <special> |
|
268 } |
|
269 elsif ($line =~ /^\s*([\S]+)\s+([\S]+)\s*$/) |
|
270 { |
|
271 my ($component,$path) = ($1,$2); |
|
272 |
|
273 getExports($path."\\bld.inf", $aRoot, $variantMacros); |
|
274 } |
|
275 else |
|
276 { |
|
277 die "Line '$line' not recognised in script.\n"; |
|
278 } |
|
279 } |
|
280 } |
|
281 |
|
282 close(SCRIPT); |
|
283 } |
|
284 |
|
285 # Process a bld.inf file to get all exported files and their category |
|
286 sub getExports($) |
|
287 { |
|
288 my ($aFile, $aSourceRoot, $variantMacros) = @_; |
|
289 |
|
290 my $sourceRoot = $aSourceRoot; |
|
291 $sourceRoot =~ s/[\/\\]+$//; |
|
292 |
|
293 # There are lots of references to this so put it in a variable. |
|
294 my $bifile = $ENV{TEMP}."/bld.inf"; |
|
295 |
|
296 # Remove cpp output file in case cpp fails and an old one is left |
|
297 unlink $bifile if -e $bifile ; |
|
298 |
|
299 # Preprocess (via cpp), die if there are problems. System has negative |
|
300 # logic so 'and die' is correct. |
|
301 system("cpp ".$variantMacros." -undef $sourceRoot/$aFile $bifile") and die "Error: 'cpp ".$variantMacros." $sourceRoot/$aFile $bifile' failed.\n"; |
|
302 # The macro 'arm' is automatically defined by gcc. This replaces 'arm' in the bld.inf with ' 1 ', hence use of -undef when calling cpp. |
|
303 |
|
304 open(FILE, $bifile ) or die "Error: CPP output not accessible\n"; |
|
305 |
|
306 my $exports = 0; |
|
307 |
|
308 # Pretend the cwd (working dir) is the location of the original bld.inf |
|
309 my $cwd = $aFile; |
|
310 $cwd =~ s/[^\/\\]+$//; # Remove any preceding slashes |
|
311 |
|
312 foreach my $line (<FILE>) |
|
313 { |
|
314 chomp $line; |
|
315 $line =~ s/^\s+//; # Strip spaces, before, |
|
316 $line =~ s/\s+$//; # and after. |
|
317 |
|
318 if (lc($line) eq "prj_exports") |
|
319 { |
|
320 # Start of exports declaration |
|
321 $exports = 1; |
|
322 } |
|
323 elsif (lc($line) =~ /^prj/) |
|
324 { |
|
325 # Start of any other section (end of exports decl) |
|
326 $exports = 0; |
|
327 } |
|
328 elsif ($line=~/^# (\d+) "(.*)"( \d+)?/o) |
|
329 { |
|
330 # Included bld.inf file; paths now relative to this |
|
331 { |
|
332 $cwd=$2; |
|
333 $cwd=~s-\\\\-\\-go; # Reduce escaped backslashes |
|
334 $cwd=~s/[^\/\\]+$//; # Strip preceding slashes |
|
335 } |
|
336 } |
|
337 elsif ($exports) |
|
338 { |
|
339 # Line is in PRJ_EXPORTS declaration |
|
340 if ($line ne "") |
|
341 { |
|
342 my ($source, $dest) = split_parms($line); |
|
343 |
|
344 # Parse destination path |
|
345 if (($dest =~ /[\/\\]$/) || (!defined($dest))) |
|
346 { |
|
347 # Filename omitted |
|
348 my $file = $source; # Take source filename |
|
349 $file =~ s/^.*[\/\\]//; # Strip path |
|
350 $dest = $dest.$file; # Put in epoc32\include |
|
351 } |
|
352 |
|
353 if ($dest =~ /^[ZC]:[\/\\]/i) |
|
354 { |
|
355 # This export is using the emulated C: or Z: drive, |
|
356 # replace [C/Z]: by \epoc32\data\[C/Z] |
|
357 $dest =~ s/^([ZC]):/\\epoc32\\data\\$1/i; |
|
358 $zorcdrive = 1; |
|
359 } |
|
360 elsif ($dest =~ /^[^\/\\]/) |
|
361 { |
|
362 # if target starts by +\ or +/ replace + by \epoc32 |
|
363 if ($dest =~ /^\+[\/\\]/) |
|
364 { |
|
365 $dest =~ s/^\+/\\epoc32/; |
|
366 } |
|
367 else |
|
368 { |
|
369 # Path relative (to epoc32\include) |
|
370 $dest = "\\epoc32\\include\\$dest"; |
|
371 } |
|
372 } |
|
373 if ($dest =~ /^[\/\\]epoc32/) |
|
374 { |
|
375 # Destination under epoc32 |
|
376 $dest =~ s/^[\/\\]//; |
|
377 $dest = $ENV{EPOCROOT}.$dest; # Put under EPOCROOT |
|
378 } |
|
379 |
|
380 # Parse source path |
|
381 if ($source =~ /^[\/\\]/) |
|
382 { |
|
383 # Source relative to source root |
|
384 $source =~ s/^[\/\\]+//; |
|
385 $source = $sourceRoot."\\".$source; |
|
386 } |
|
387 else |
|
388 { |
|
389 # Truly relative source path |
|
390 $source = $cwd.$source; |
|
391 } |
|
392 |
|
393 if (-e $source || $noSource) |
|
394 { |
|
395 # Get source category |
|
396 my ($cat, $restricted) = getExportCategory($source); |
|
397 |
|
398 if ( $export # Include irrespective of export restrictions |
|
399 || ($restrict && $restricted) # Include only if restricted |
|
400 || ((!$restrict) && (!$restricted)) # Include only if not restricted |
|
401 ) |
|
402 { |
|
403 if ((scalar(keys(%$cats)) == 0) || ($cats->{lc($cat)})) |
|
404 { |
|
405 if( $export && $zorcdrive && ($cat =~ /^[ABCI]$/)) |
|
406 { |
|
407 print STDERR "WARNING: cat $cat resource file not categorised : $dest \n"; |
|
408 } |
|
409 if (scalar(keys(%$cats)) == 0) |
|
410 { |
|
411 # No category specified - display category |
|
412 print STDOUT $cat." "; |
|
413 if ($export && $restricted) |
|
414 { |
|
415 print STDOUT "(export restricted) "; |
|
416 } |
|
417 } |
|
418 |
|
419 print STDOUT "$dest"; |
|
420 |
|
421 if ($bldinf) |
|
422 { |
|
423 # Display bld.inf file |
|
424 print STDOUT " ".$aFile; |
|
425 } |
|
426 |
|
427 print STDOUT "\n"; |
|
428 } |
|
429 } |
|
430 } |
|
431 elsif (!$noMissing) |
|
432 { |
|
433 print "Error: $aFile: Export file '$source' not found\n"; |
|
434 } |
|
435 } |
|
436 } |
|
437 $zorcdrive = 0; |
|
438 } |
|
439 close(FILE); |
|
440 # Remove cpp output file so nothing else can try to use it. |
|
441 unlink $bifile or die "Error: Could not delete $bifile.\n"; |
|
442 } |
|
443 |
|
444 # Identify IPR category for a given file |
|
445 sub getExportCategory($) |
|
446 { |
|
447 my ($aSource) = @_; |
|
448 |
|
449 my $sdir = $aSource; |
|
450 $sdir =~ s/[\/\\][^\/\\]+$//; |
|
451 my $cat = "X"; # Default if no DISTRIBUTION.POLICY |
|
452 my $restricted = 0; |
|
453 |
|
454 if (open(DISTPOL,"$sdir/DISTRIBUTION.POLICY")) |
|
455 { |
|
456 foreach my $line (<DISTPOL>) |
|
457 { |
|
458 chomp($line); |
|
459 if ($line =~ /^\s*CATEGORY\s+(\w)\s*$/i) |
|
460 { |
|
461 $cat = $1; |
|
462 } |
|
463 elsif ($line =~ /^\s*export\s+restricted\s*$/i) |
|
464 { |
|
465 $restricted = 1; |
|
466 } |
|
467 } |
|
468 close(DISTPOL); |
|
469 } |
|
470 return ($cat, $restricted); |
|
471 } |
|
472 |
|
473 # Takes a space separated list of parameters (spaces may be double quoted) and |
|
474 # returns a perl list. |
|
475 sub split_parms($) |
|
476 { |
|
477 my ($aLine) = @_; |
|
478 |
|
479 my $line = $aLine; |
|
480 my @parms; |
|
481 my $parm; |
|
482 |
|
483 while ($line !~ /^\s*$/) |
|
484 { |
|
485 #Remove preceding spaces |
|
486 $line =~ s/^\s+//; |
|
487 |
|
488 if ($line =~ /^"/) |
|
489 { |
|
490 # Split on quote |
|
491 if ($line =~ m/^"([^"]*)"(.*)$/) |
|
492 { |
|
493 push @parms, $1; |
|
494 $line = $2; |
|
495 } |
|
496 } |
|
497 else |
|
498 { |
|
499 # Split on space |
|
500 if ($line =~ m/^([^\s]*)\s+(.*)$/) |
|
501 { |
|
502 push @parms, $1; |
|
503 $line = $2; |
|
504 } |
|
505 else |
|
506 { |
|
507 # No spaces present |
|
508 push @parms, $line; |
|
509 $line = ""; |
|
510 } |
|
511 } |
|
512 } |
|
513 |
|
514 return @parms; |
|
515 } |
|
516 |
|
517 sub help() |
|
518 { |
|
519 print "Syntax: [perl ]exportipr.pl -src sourcepath [-bldinf] [-c...] [path | -genbuild filename]\n"; |
|
520 print "\n sourcepath is a path to a source tree\n"; |
|
521 print "\n EPOCROOT must be set for the destination of the exports to be\n"; |
|
522 print " reported accurately.\n"; |
|
523 print "\n Options:\n"; |
|
524 print " path : is a path (within the source tree) used if the whole source tree\n"; |
|
525 print " is not to be scanned\n"; |
|
526 print " -genbuild filename : points to a genbuild compatible file, used if the whole"; |
|
527 print " source tree is not to be scanned\n"; |
|
528 print " -bldinf : reports the bld.inf file which exports each file\n"; |
|
529 print " -c... : restricts the output to specific categories (e.g. -cFG)\n"; |
|
530 print " -export : includes files irrespective of export restrictions\n"; |
|
531 print " -restricted : only includes files with export restrictions\n"; |
|
532 print "By default export restricted files are not reported\n"; |
|
533 print "\nWith no -c option the category of each file is reported\n"; |
|
534 print "With the -export option additionally applied, export restricted files are indicated\n"; |
|
535 print "If a -c option is applied and -bldinf is not, a plain list of\n"; |
|
536 print "exports will be produced.\n"; |
|
537 } |