diff -r 22486c9c7b15 -r 378360dbbdba sbsv1/abld/makmake/makdeps.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbsv1/abld/makmake/makdeps.pm Wed Jun 30 11:35:58 2010 +0800 @@ -0,0 +1,409 @@ +# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# Module which wraps the dependency information provided the preprocessor when invoked with certain switches +# so that dependency information rather than preprocessing information is produced. +# +# + +package Makdeps; +require Exporter; +@ISA=qw(Exporter); +@EXPORT=qw( + Deps_InitL + Deps_SetVerbose + Deps_SetUserHdrsOnly + Deps_SetNoDependencies + Deps_SetSysIncPaths + Deps_SetUserIncPaths + Deps_SetPlatMacros + Deps_SetStdIncSysIncPaths + Deps_GenDependsL + Deps_SetPrefixFile + Deps_GetNoDependencies + Deps_SetNoDependenciesStatus + Deps_GetOSVariantFile + Deps_SetOSVariantFile +); + +use Checkgcc; +use Pathutl; +use Preprocessor; + + +my $ChopSysDecoyPath; +my $EPOCIncPath; +my @StdPaths; +my %Mode; +my @PlatMacros; +my $SysDecoyPath; +my @SysFlags; +my @SysPaths; +my @UserFlags; +my @UserPaths; +my $PrefixFileOption = ""; +my $VariantFile=&main::VariantFile(); + +# special variable used in pattern-matching - special characters nullified +my $S_SysDecoyPath; + +BEGIN { # NB don't initialise essential items to be provided later by calling module, then will cause errors with undef + $Mode{'Verbose'}=0; + $Mode{'UserHdrsOnly'}=0; + $Mode{'NoDependencies'}=0; + @PlatMacros=(); + # note -MG option assumes missing user headers live in 1st userincpath and missing sys headers in 1st sysdir + @SysPaths=(); + @UserPaths=(); + @StdPaths=(); + @SysFlags=(); + @UserFlags=(); + # Use random number to ensure DecoyPath is unique (ish) + srand(); + my $randnum=int(rand(100)); + if (defined $ENV{PBUILDPID}) { + $SysDecoyPath=&Path_WorkPath."TEMPMAK$ENV{PBUILDPID}SYSDECOY$randnum\\"; + } else { + $SysDecoyPath=&Path_WorkPath."TEMPMAKSYSDECOY$randnum\\"; + } + $S_SysDecoyPath=quotemeta($SysDecoyPath); + $ChopSysDecoyPath=&Path_Chop($SysDecoyPath); +} + +sub Deps_InitL ($@) { # abs Generated Hdr dir, StdIncsysdir (with drive letter if required) +# set up a decoy system include path, and set which path will contain generated headers, eg .RSG files, and which +# paths are the standard system include paths for the compiler used - eg \MSDEV\INCLUDE + ($EPOCIncPath,@StdPaths)=@_; + +# remove the decoy directory then try to make it again - if it contains files rmdir won't work, so mkdir won't +# work and the user will have to sort it out. If it doesn't contain files and has been left lying around +# because someone has killed the program half-way through, then rmdir will remove it and mkdir will work OK + rmdir $ChopSysDecoyPath if -d $ChopSysDecoyPath; + mkdir $ChopSysDecoyPath,2 or die "ERROR: Can't make temp dir \"$ChopSysDecoyPath\"\nIf it already exists, please remove it\n"; +} +sub Deps_SetVerbose { + $Mode{'Verbose'}=1; +} + +sub Deps_SetUserHdrsOnly { +# allow calling program to dictate that only listings of user headers, not system headers, be produced + $Mode{'UserHdrsOnly'}=1; +} + +sub Deps_SetNoDependencies { +# Ensure that we do not create a list of dependencies. + $Mode{'NoDependencies'}=1; +} + +sub Deps_GetNoDependencies { +# Get the status of NoDependencies. + return $Mode{'NoDependencies'}; +} + +sub Deps_SetNoDependenciesStatus($) { +# Ensure that we do not create a list of dependencies. + $Mode{'NoDependencies'}=shift; +} + +sub Deps_GetOSVariantFile() { +# Return the variant .hrh file currently defined + return $VariantFile; +} + +sub Deps_SetOSVariantFile($) { +# Override the variant .hrh file currently defined + $VariantFile=shift; +} + +sub Deps_SetSysIncPaths (@) { # takes list abs paths +# set the system include paths where we'll look for system included files, and +# for user included files if these are not found in the user include directories + return unless @_; + @SysPaths=@_; + @SysFlags=&Path_Chop(@SysPaths); # newer gcc doesn't like trailing backslash + @SysFlags=&Path_PrefixWithDriveAndQuote(@SysFlags); + my $Flag; + foreach $Flag (@SysFlags) { + $Flag=~s/^(.*)$/-I $1/o; + } +} +sub Deps_SetUserIncPaths (@) { # takes list of abs paths +# set the user include paths to find user included files in + return unless @_; + @UserPaths=@_; + @UserFlags=&Path_Chop(@UserPaths); # newer gcc doesn't like trailing backslash + @UserFlags=&Path_PrefixWithDriveAndQuote(@UserFlags); + my $Flag; + foreach $Flag (@UserFlags) { + $Flag=~s/^(.*)$/-I $1/o; + } +} +sub Deps_SetPlatMacros (@) { +# set the macros to be defined by the preprocessor + return unless @_; + @PlatMacros=@_; + my $Flag; + foreach $Flag (@PlatMacros) { + if($Flag =~ m/\\\"/) { + $Flag =~ s/\\\"/\"/g ; + } + $Flag=~s/^(.*)$/-D$1/o; + } +} + +sub Deps_SetPrefixFile($) { + my ($file) = @_; + $PrefixFileOption = " -include $file "; +} + +sub Deps_GenDependsL ($@) { # takes abs source filepath and list of Build Macros + + if ( $Mode{'NoDependencies'} ) { + # no need build a dependency list. + return; + } + +# Set any more macros the preprocessor needs to be defined for the source file +# to be preprocessed. +# Call preprocessor and produce the dependency listing. + + my ($Src,@BldMacros)=@_; + + if (not -e $Src) { + warn "WARNING: \"",$Src,"\" not found!\n"; + return; + } + +# Always put the source path at the head of the user path list +# and take it out at the end of this function + unshift @UserPaths, &Path_Split('Path', lc $Src); + + my $ChopSysDecoyPath=&Path_Chop($SysDecoyPath); # newer gcc doesn't like trailing backslash + my $MacroFlag; + foreach $MacroFlag (@BldMacros) { + $MacroFlag=~s/^(.*)$/-D$1/o; + } + undef $MacroFlag; + + my $ChopSrcPath=&Path_Chop(&Path_Split('Path',$Src)); # newer gcc doesn't like trailing backslash + my $ProductVariantFlag = ""; + if($VariantFile){ + $ProductVariantFlag = "-include " . &Path_PrefixWithDriveAndQuote($VariantFile); + } + my $VariantIncludePath; + if (defined &main::PMPrefixFile) + { + $VariantIncludePath = &main::PMPrefixFile; + $VariantIncludePath =~ s/"//g; + $VariantIncludePath = Path_Split("path", $VariantIncludePath); + + $VariantIncludePath = Path_Chop($VariantIncludePath); + $VariantIncludePath = Path_PrefixWithDriveAndQuote($VariantIncludePath); + } + my $CPPCommand; + my $exe = &PreprocessorToUseExe(); + $CPPCommand = "$exe -undef -M -MG -nostdinc $PrefixFileOption"; + $CPPCommand .= " -I $VariantIncludePath" if $VariantIncludePath; + $CPPCommand .= " -I ".&Path_PrefixWithDriveAndQuote($ChopSrcPath)." @UserFlags -I- -I ".&Path_PrefixWithDriveAndQuote($ChopSysDecoyPath)." @SysFlags @PlatMacros @BldMacros $ProductVariantFlag ".&Path_PrefixWithDriveAndQuote($Src); + + if ($Mode{'Verbose'}) { + print "$CPPCommand\n" + } + open CPPPIPE,"$CPPCommand |" or die "ERROR: Can't invoke $exe.EXE\n"; + + # XYZ.CPP.o: \ + # ..\..\..\base\bafl\src\xyz.cpp \ + # ..\..\..\EPOC32\INCLUDE\E32DES16.H ..\..\..\EPOC32\INCLUDE\E32STD.INL \ + # ..\..\..\EPOC32\INCLUDE\E32BASE.INL \ + # ..\..\..\base\bafl\inc\bautil.h \ + # ..\..\..\awkward\ name\bafl\inc\bautil.h \ + # ..\..\..\lastthing.h + + my @RTWDepList; + while () { + s/ \\$//oi; # remove trailing continuation character + s/\\ /;/go; # convert embedded spaces (\) into semicolon which can't occur in filenames + # avoid the target of the rule by requiring whitespace in front of each element + while (/\s(\S+)/go) { + my $dep = $1; + $dep =~ s/;/ /go; # spaces were turned into semicolon, so convert back again here + $dep =~ s-/-\\-go; # replace forward slashes with backward slashes + $dep =~ s/^.\://; + $dep =~ s/\s+$//; # remove trailing spaces + push @RTWDepList,$dep; + } + } + close CPPPIPE or die "ERROR: $exe.EXE failure\n"; + + # drop the first dependent, which is the source file itself + shift @RTWDepList; + +# make all paths absolute + my @DepList=&Path_AbsToWork(@RTWDepList); + undef @RTWDepList; + +# test the dependencies + eval { @DepList=&TestDepends($Src,@DepList); }; + die $@ if $@; + + my @SortedDepList; +# get just those headers found in the user include path if user headers only specified + if (not $Mode{'UserHdrsOnly'}) { + @SortedDepList=sort @DepList; + } + else { + my @UserDepList=(); + my $Dep; + my $UserPath; + DEPLOOP: foreach $Dep (@DepList) { + foreach $UserPath (@UserPaths) { + if ($UserPath eq &Path_Split('Path',$Dep)) { + push @UserDepList, $Dep; + next DEPLOOP; + } + } + } + @SortedDepList=sort @UserDepList; + } + +# take the source path out of the user path list + shift @UserPaths; + + @SortedDepList; +} + + +sub TestDepends (@) { # takes source list of absolute dependencies - called by GenDepends +# check that the dependencies exist or are to be generated later, because gcc with the -MG switch +# will assume that missing system headers live in the first system include path specified (the decoy +# directory in our case), and the missing user headers live in the current working directory + + my ($Src,@DepList)=@_; + + my @BadSysList; + my @BadUserList; + my $Dep; + my @GoodList; + my $SrcPath=&Path_Split('Path', $Src); + + my $Path; + my $File; + DEPLOOP: foreach $Dep (@DepList) { # system dependencies not found + $Path=&Path_Split('Path', lc $Dep); + if ($Dep=~/^$S_SysDecoyPath(.*)$/o) { # allow things like "#include " +# any files listed as existing in the system decoy directory will be missing system include files + $File=$1; +# change any missing generated header entries so that they are thought to be in $EPOCIncPath, where they will be generated to + if ($File=~/\.(RSG|MBG)$/oi) { + push @GoodList, "$EPOCIncPath$File"; + next DEPLOOP; + } +# remove missing system include files from the list if they actually exist in standard directories - since the makefiles can't handle +# files which may be on a different drive - we don't mind this because if we're using MSVC then we can assume +# the MSVC include files will exist + my $LR; + foreach $LR (@StdPaths) { # tackle MSDEV include dir on diff drive + if (-e "$LR$File") { # don't put MSDEV includes in dep list - drive letter would end up in makefile + next DEPLOOP; + } + } +# put any other missing system files on the bad list after checking that they really don't exist on the system paths +# at this point in time. This check is applied in an attempt to avoid sporadic warnings in the build where system +# headers have been listed in the system decoy directory, and hence flagged as missing, when they do seem to have +# been present at this time post-build... + foreach $Path (@SysPaths) { + if (-e "$Path$File") { + next DEPLOOP; + } + } + push @BadSysList, $File; + next DEPLOOP; + } +# preprocessor lists any missing user headers as existing in the current directory, +# and, if no userinclude paths are specified, +# searches to path containing the source file for user headers by default + if ($Path eq lc &Path_WorkPath) { # possible missing user headers + $File=&Path_Split('File',$Dep); + # does the userinclude path contain the current working directory? + my $LoopPath; + my $WorkPathInUserPaths=0; + foreach $LoopPath (@UserPaths) { + if ( (lc $LoopPath) eq (lc &Path_WorkPath) ) { + $WorkPathInUserPaths=1; + next; + } + } + if ($WorkPathInUserPaths) { # the user include path contains the current working directory + if (-e $Dep) { + push @GoodList,$Dep; # file found in specified userinclude path, OK + next DEPLOOP; + } + } + push @BadUserList, $File; # file not found in specified userinclude path, bad + next DEPLOOP; + } + push @GoodList, $Dep; + } + + my $Bad; + if (@BadSysList) { + warn "\nWARNING: Can't find following headers in System Include Path\n"; + foreach $Bad (@BadSysList) { + print STDERR " <$Bad>"; + } + print STDERR "\n(Sys Inc Paths"; + foreach $Path (@SysPaths,@StdPaths) { + print STDERR " \"$Path\""; + } + warn + ")\nDependency list for \"$Src\" may be incomplete\n", + "\n" + ; + } + if (@BadUserList) { + warn "\nWARNING: Can't find following headers in User or System Include Paths\n"; + my $GenHdr=0; + foreach $Bad (@BadUserList) { + print STDERR " \"$Bad\""; + if ($File=~/\.(RSG|MBG)$/o) { + $GenHdr=1; + } + } + print STDERR "\n(User Inc Paths"; + foreach $Path (@UserPaths) { + print STDERR " \"$Path\""; + } + warn + ")\nDependency list for \"$Src\" may be incomplete\n", + "\n" + ; + if ($GenHdr) { + warn + "Note that generated headers should be system-included with angle brackets <>\n", + "\n" + ; + } + } + + @GoodList; +} + + +END { + # remove the dependency decoy directories + if (-d "$ChopSysDecoyPath") { + rmdir "$ChopSysDecoyPath" or warn "Please remove temp dir \"$ChopSysDecoyPath\"\n"; + } +} + +1;