sbsv1_os/e32toolp/makmake/makdeps.pm
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     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;