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