|
1 # Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 # All rights reserved. |
|
3 # This component and the accompanying materials are made available |
|
4 # under the terms of "Eclipse Public License v1.0" |
|
5 # which accompanies this distribution, and is available |
|
6 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 # |
|
8 # Initial Contributors: |
|
9 # Nokia Corporation - initial contribution. |
|
10 # |
|
11 # Contributors: |
|
12 # |
|
13 # Description: |
|
14 # Module which wraps the dependency information provided the preprocessor when invoked with certain switches |
|
15 # so that dependency information rather than preprocessing information is produced. |
|
16 # |
|
17 # |
|
18 |
|
19 package Makdeps; |
|
20 require Exporter; |
|
21 @ISA=qw(Exporter); |
|
22 @EXPORT=qw( |
|
23 Deps_InitL |
|
24 Deps_SetVerbose |
|
25 Deps_SetUserHdrsOnly |
|
26 Deps_SetNoDependencies |
|
27 Deps_SetSysIncPaths |
|
28 Deps_SetUserIncPaths |
|
29 Deps_SetPlatMacros |
|
30 Deps_SetStdIncSysIncPaths |
|
31 Deps_GenDependsL |
|
32 Deps_SetPrefixFile |
|
33 Deps_GetNoDependencies |
|
34 Deps_SetNoDependenciesStatus |
|
35 Deps_GetOSVariantFile |
|
36 Deps_SetOSVariantFile |
|
37 ); |
|
38 |
|
39 use strict; |
|
40 use Checkgcc; |
|
41 use Pathutl; |
|
42 use Preprocessor; |
|
43 |
|
44 |
|
45 my $ChopSysDecoyPath; |
|
46 my $EPOCIncPath; |
|
47 my @StdPaths; |
|
48 my %Mode; |
|
49 my @PlatMacros; |
|
50 my $SysDecoyPath; |
|
51 my @SysFlags; |
|
52 my @SysPaths; |
|
53 my @UserFlags; |
|
54 my @UserPaths; |
|
55 my $PrefixFileOption = ""; |
|
56 my $VariantFile=&main::VariantFile(); |
|
57 |
|
58 # special variable used in pattern-matching - special characters nullified |
|
59 my $S_SysDecoyPath; |
|
60 |
|
61 BEGIN { # NB don't initialise essential items to be provided later by calling module, then will cause errors with undef |
|
62 $Mode{'Verbose'}=0; |
|
63 $Mode{'UserHdrsOnly'}=0; |
|
64 $Mode{'NoDependencies'}=0; |
|
65 @PlatMacros=(); |
|
66 # note -MG option assumes missing user headers live in 1st userincpath and missing sys headers in 1st sysdir |
|
67 @SysPaths=(); |
|
68 @UserPaths=(); |
|
69 @StdPaths=(); |
|
70 @SysFlags=(); |
|
71 @UserFlags=(); |
|
72 # Use random number to ensure DecoyPath is unique (ish) |
|
73 srand(); |
|
74 my $randnum=int(rand(100)); |
|
75 if (defined $ENV{PBUILDPID}) { |
|
76 $SysDecoyPath=&Path_WorkPath."TEMPMAK$ENV{PBUILDPID}SYSDECOY$randnum\\"; |
|
77 } else { |
|
78 $SysDecoyPath=&Path_WorkPath."TEMPMAKSYSDECOY$randnum\\"; |
|
79 } |
|
80 $S_SysDecoyPath=quotemeta($SysDecoyPath); |
|
81 $ChopSysDecoyPath=&Path_Chop($SysDecoyPath); |
|
82 } |
|
83 |
|
84 sub Deps_InitL ($@) { # abs Generated Hdr dir, StdIncsysdir (with drive letter if required) |
|
85 # set up a decoy system include path, and set which path will contain generated headers, eg .RSG files, and which |
|
86 # paths are the standard system include paths for the compiler used - eg \MSDEV\INCLUDE |
|
87 ($EPOCIncPath,@StdPaths)=@_; |
|
88 |
|
89 # remove the decoy directory then try to make it again - if it contains files rmdir won't work, so mkdir won't |
|
90 # work and the user will have to sort it out. If it doesn't contain files and has been left lying around |
|
91 # because someone has killed the program half-way through, then rmdir will remove it and mkdir will work OK |
|
92 rmdir $ChopSysDecoyPath if -d $ChopSysDecoyPath; |
|
93 mkdir $ChopSysDecoyPath,2 or die "ERROR: Can't make temp dir \"$ChopSysDecoyPath\"\nIf it already exists, please remove it\n"; |
|
94 } |
|
95 sub Deps_SetVerbose { |
|
96 $Mode{'Verbose'}=1; |
|
97 } |
|
98 |
|
99 sub Deps_SetUserHdrsOnly { |
|
100 # allow calling program to dictate that only listings of user headers, not system headers, be produced |
|
101 $Mode{'UserHdrsOnly'}=1; |
|
102 } |
|
103 |
|
104 sub Deps_SetNoDependencies { |
|
105 # Ensure that we do not create a list of dependencies. |
|
106 $Mode{'NoDependencies'}=1; |
|
107 } |
|
108 |
|
109 sub Deps_GetNoDependencies { |
|
110 # Get the status of NoDependencies. |
|
111 return $Mode{'NoDependencies'}; |
|
112 } |
|
113 |
|
114 sub Deps_SetNoDependenciesStatus($) { |
|
115 # Ensure that we do not create a list of dependencies. |
|
116 $Mode{'NoDependencies'}=shift; |
|
117 } |
|
118 |
|
119 sub Deps_GetOSVariantFile() { |
|
120 # Return the variant .hrh file currently defined |
|
121 return $VariantFile; |
|
122 } |
|
123 |
|
124 sub Deps_SetOSVariantFile($) { |
|
125 # Override the variant .hrh file currently defined |
|
126 $VariantFile=shift; |
|
127 } |
|
128 |
|
129 sub Deps_SetSysIncPaths (@) { # takes list abs paths |
|
130 # set the system include paths where we'll look for system included files, and |
|
131 # for user included files if these are not found in the user include directories |
|
132 return unless @_; |
|
133 @SysPaths=@_; |
|
134 @SysFlags=&Path_Chop(@SysPaths); # newer gcc doesn't like trailing backslash |
|
135 @SysFlags=&Path_PrefixWithDriveAndQuote(@SysFlags); |
|
136 my $Flag; |
|
137 foreach $Flag (@SysFlags) { |
|
138 $Flag=~s/^(.*)$/-I $1/o; |
|
139 } |
|
140 } |
|
141 sub Deps_SetUserIncPaths (@) { # takes list of abs paths |
|
142 # set the user include paths to find user included files in |
|
143 return unless @_; |
|
144 @UserPaths=@_; |
|
145 @UserFlags=&Path_Chop(@UserPaths); # newer gcc doesn't like trailing backslash |
|
146 @UserFlags=&Path_PrefixWithDriveAndQuote(@UserFlags); |
|
147 my $Flag; |
|
148 foreach $Flag (@UserFlags) { |
|
149 $Flag=~s/^(.*)$/-I $1/o; |
|
150 } |
|
151 } |
|
152 sub Deps_SetPlatMacros (@) { |
|
153 # set the macros to be defined by the preprocessor |
|
154 return unless @_; |
|
155 @PlatMacros=@_; |
|
156 my $Flag; |
|
157 foreach $Flag (@PlatMacros) { |
|
158 if($Flag =~ m/\\\"/) { |
|
159 $Flag =~ s/\\\"/\"/g ; |
|
160 } |
|
161 $Flag=~s/^(.*)$/-D$1/o; |
|
162 } |
|
163 } |
|
164 |
|
165 sub Deps_SetPrefixFile($) { |
|
166 my ($file) = @_; |
|
167 $PrefixFileOption = " -include $file "; |
|
168 } |
|
169 |
|
170 sub Deps_GenDependsL ($@) { # takes abs source filepath and list of Build Macros |
|
171 |
|
172 if ( $Mode{'NoDependencies'} ) { |
|
173 # no need build a dependency list. |
|
174 return; |
|
175 } |
|
176 |
|
177 # Set any more macros the preprocessor needs to be defined for the source file |
|
178 # to be preprocessed. |
|
179 # Call preprocessor and produce the dependency listing. |
|
180 |
|
181 my ($Src,@BldMacros)=@_; |
|
182 |
|
183 if (not -e $Src) { |
|
184 warn "WARNING: \"",$Src,"\" not found!\n"; |
|
185 return; |
|
186 } |
|
187 |
|
188 # Always put the source path at the head of the user path list |
|
189 # and take it out at the end of this function |
|
190 unshift @UserPaths, &Path_Split('Path', lc $Src); |
|
191 |
|
192 my $ChopSysDecoyPath=&Path_Chop($SysDecoyPath); # newer gcc doesn't like trailing backslash |
|
193 my $MacroFlag; |
|
194 foreach $MacroFlag (@BldMacros) { |
|
195 $MacroFlag=~s/^(.*)$/-D$1/o; |
|
196 } |
|
197 undef $MacroFlag; |
|
198 |
|
199 my $ChopSrcPath=&Path_Chop(&Path_Split('Path',$Src)); # newer gcc doesn't like trailing backslash |
|
200 my $ProductVariantFlag = ""; |
|
201 if($VariantFile){ |
|
202 $ProductVariantFlag = "-include " . &Path_PrefixWithDriveAndQuote($VariantFile); |
|
203 } |
|
204 my $VariantIncludePath; |
|
205 if (defined &main::PMPrefixFile) |
|
206 { |
|
207 $VariantIncludePath = &main::PMPrefixFile; |
|
208 $VariantIncludePath =~ s/"//g; |
|
209 $VariantIncludePath = Path_Split("path", $VariantIncludePath); |
|
210 |
|
211 $VariantIncludePath = Path_Chop($VariantIncludePath); |
|
212 $VariantIncludePath = Path_PrefixWithDriveAndQuote($VariantIncludePath); |
|
213 } |
|
214 my $CPPCommand; |
|
215 my $exe = &PreprocessorToUseExe(); |
|
216 $CPPCommand = "$exe -undef -M -MG -nostdinc $PrefixFileOption"; |
|
217 $CPPCommand .= " -I $VariantIncludePath" if $VariantIncludePath; |
|
218 $CPPCommand .= " -I ".&Path_PrefixWithDriveAndQuote($ChopSrcPath)." @UserFlags -I- -I ".&Path_PrefixWithDriveAndQuote($ChopSysDecoyPath)." @SysFlags @PlatMacros @BldMacros $ProductVariantFlag ".&Path_PrefixWithDriveAndQuote($Src); |
|
219 |
|
220 if ($Mode{'Verbose'}) { |
|
221 print "$CPPCommand\n" |
|
222 } |
|
223 open CPPPIPE,"$CPPCommand |" or die "ERROR: Can't invoke $exe.EXE\n"; |
|
224 |
|
225 # XYZ.CPP.o: \ |
|
226 # ..\..\..\base\bafl\src\xyz.cpp \ |
|
227 # ..\..\..\EPOC32\INCLUDE\E32DES16.H ..\..\..\EPOC32\INCLUDE\E32STD.INL \ |
|
228 # ..\..\..\EPOC32\INCLUDE\E32BASE.INL \ |
|
229 # ..\..\..\base\bafl\inc\bautil.h \ |
|
230 # ..\..\..\awkward\ name\bafl\inc\bautil.h \ |
|
231 # ..\..\..\lastthing.h |
|
232 |
|
233 my @RTWDepList; |
|
234 while (<CPPPIPE>) { |
|
235 s/ \\$//oi; # remove trailing continuation character |
|
236 s/\\ /;/go; # convert embedded spaces (\<space>) into semicolon which can't occur in filenames |
|
237 # avoid the target of the rule by requiring whitespace in front of each element |
|
238 while (/\s(\S+)/go) { |
|
239 my $dep = $1; |
|
240 $dep =~ s/;/ /go; # spaces were turned into semicolon, so convert back again here |
|
241 $dep =~ s-/-\\-go; # replace forward slashes with backward slashes |
|
242 $dep =~ s/^.\://; |
|
243 $dep =~ s/\s+$//; # remove trailing spaces |
|
244 push @RTWDepList,$dep; |
|
245 } |
|
246 } |
|
247 close CPPPIPE or die "ERROR: $exe.EXE failure\n"; |
|
248 |
|
249 # drop the first dependent, which is the source file itself |
|
250 shift @RTWDepList; |
|
251 |
|
252 # make all paths absolute |
|
253 my @DepList=&Path_AbsToWork(@RTWDepList); |
|
254 undef @RTWDepList; |
|
255 |
|
256 # test the dependencies |
|
257 eval { @DepList=&TestDepends($Src,@DepList); }; |
|
258 die $@ if $@; |
|
259 |
|
260 my @SortedDepList; |
|
261 # get just those headers found in the user include path if user headers only specified |
|
262 if (not $Mode{'UserHdrsOnly'}) { |
|
263 @SortedDepList=sort @DepList; |
|
264 } |
|
265 else { |
|
266 my @UserDepList=(); |
|
267 my $Dep; |
|
268 my $UserPath; |
|
269 DEPLOOP: foreach $Dep (@DepList) { |
|
270 foreach $UserPath (@UserPaths) { |
|
271 if ($UserPath eq &Path_Split('Path',$Dep)) { |
|
272 push @UserDepList, $Dep; |
|
273 next DEPLOOP; |
|
274 } |
|
275 } |
|
276 } |
|
277 @SortedDepList=sort @UserDepList; |
|
278 } |
|
279 |
|
280 # take the source path out of the user path list |
|
281 shift @UserPaths; |
|
282 |
|
283 @SortedDepList; |
|
284 } |
|
285 |
|
286 |
|
287 sub TestDepends (@) { # takes source list of absolute dependencies - called by GenDepends |
|
288 # check that the dependencies exist or are to be generated later, because gcc with the -MG switch |
|
289 # will assume that missing system headers live in the first system include path specified (the decoy |
|
290 # directory in our case), and the missing user headers live in the current working directory |
|
291 |
|
292 my ($Src,@DepList)=@_; |
|
293 |
|
294 my @BadSysList; |
|
295 my @BadUserList; |
|
296 my $Dep; |
|
297 my @GoodList; |
|
298 my $SrcPath=&Path_Split('Path', $Src); |
|
299 |
|
300 my $Path; |
|
301 my $File; |
|
302 DEPLOOP: foreach $Dep (@DepList) { # system dependencies not found |
|
303 $Path=&Path_Split('Path', lc $Dep); |
|
304 if ($Dep=~/^$S_SysDecoyPath(.*)$/o) { # allow things like "#include <sys\stats.h>" |
|
305 # any files listed as existing in the system decoy directory will be missing system include files |
|
306 $File=$1; |
|
307 # change any missing generated header entries so that they are thought to be in $EPOCIncPath, where they will be generated to |
|
308 if ($File=~/\.(RSG|MBG)$/oi) { |
|
309 push @GoodList, "$EPOCIncPath$File"; |
|
310 next DEPLOOP; |
|
311 } |
|
312 # remove missing system include files from the list if they actually exist in standard directories - since the makefiles can't handle |
|
313 # files which may be on a different drive - we don't mind this because if we're using MSVC then we can assume |
|
314 # the MSVC include files will exist |
|
315 my $LR; |
|
316 foreach $LR (@StdPaths) { # tackle MSDEV include dir on diff drive |
|
317 if (-e "$LR$File") { # don't put MSDEV includes in dep list - drive letter would end up in makefile |
|
318 next DEPLOOP; |
|
319 } |
|
320 } |
|
321 # put any other missing system files on the bad list after checking that they really don't exist on the system paths |
|
322 # at this point in time. This check is applied in an attempt to avoid sporadic warnings in the build where system |
|
323 # headers have been listed in the system decoy directory, and hence flagged as missing, when they do seem to have |
|
324 # been present at this time post-build... |
|
325 foreach $Path (@SysPaths) { |
|
326 if (-e "$Path$File") { |
|
327 next DEPLOOP; |
|
328 } |
|
329 } |
|
330 push @BadSysList, $File; |
|
331 next DEPLOOP; |
|
332 } |
|
333 # preprocessor lists any missing user headers as existing in the current directory, |
|
334 # and, if no userinclude paths are specified, |
|
335 # searches to path containing the source file for user headers by default |
|
336 if ($Path eq lc &Path_WorkPath) { # possible missing user headers |
|
337 $File=&Path_Split('File',$Dep); |
|
338 # does the userinclude path contain the current working directory? |
|
339 my $LoopPath; |
|
340 my $WorkPathInUserPaths=0; |
|
341 foreach $LoopPath (@UserPaths) { |
|
342 if ( (lc $LoopPath) eq (lc &Path_WorkPath) ) { |
|
343 $WorkPathInUserPaths=1; |
|
344 next; |
|
345 } |
|
346 } |
|
347 if ($WorkPathInUserPaths) { # the user include path contains the current working directory |
|
348 if (-e $Dep) { |
|
349 push @GoodList,$Dep; # file found in specified userinclude path, OK |
|
350 next DEPLOOP; |
|
351 } |
|
352 } |
|
353 push @BadUserList, $File; # file not found in specified userinclude path, bad |
|
354 next DEPLOOP; |
|
355 } |
|
356 push @GoodList, $Dep; |
|
357 } |
|
358 |
|
359 my $Bad; |
|
360 if (@BadSysList) { |
|
361 warn "\nWARNING: Can't find following headers in System Include Path\n"; |
|
362 foreach $Bad (@BadSysList) { |
|
363 print STDERR " <$Bad>"; |
|
364 } |
|
365 print STDERR "\n(Sys Inc Paths"; |
|
366 foreach $Path (@SysPaths,@StdPaths) { |
|
367 print STDERR " \"$Path\""; |
|
368 } |
|
369 warn |
|
370 ")\nDependency list for \"$Src\" may be incomplete\n", |
|
371 "\n" |
|
372 ; |
|
373 } |
|
374 if (@BadUserList) { |
|
375 warn "\nWARNING: Can't find following headers in User or System Include Paths\n"; |
|
376 my $GenHdr=0; |
|
377 foreach $Bad (@BadUserList) { |
|
378 print STDERR " \"$Bad\""; |
|
379 if ($File=~/\.(RSG|MBG)$/o) { |
|
380 $GenHdr=1; |
|
381 } |
|
382 } |
|
383 print STDERR "\n(User Inc Paths"; |
|
384 foreach $Path (@UserPaths) { |
|
385 print STDERR " \"$Path\""; |
|
386 } |
|
387 warn |
|
388 ")\nDependency list for \"$Src\" may be incomplete\n", |
|
389 "\n" |
|
390 ; |
|
391 if ($GenHdr) { |
|
392 warn |
|
393 "Note that generated headers should be system-included with angle brackets <>\n", |
|
394 "\n" |
|
395 ; |
|
396 } |
|
397 } |
|
398 |
|
399 @GoodList; |
|
400 } |
|
401 |
|
402 |
|
403 END { |
|
404 # remove the dependency decoy directories |
|
405 if (-d "$ChopSysDecoyPath") { |
|
406 rmdir "$ChopSysDecoyPath" or warn "Please remove temp dir \"$ChopSysDecoyPath\"\n"; |
|
407 } |
|
408 } |
|
409 |
|
410 1; |