#$Id: Gcc.pm 46153 2007-10-19 00:26:07Z wsnyder $
######################################################################
#
# This program is Copyright 2002-2007 by Wilson Snyder.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of either the GNU General Public License or the
# Perl Artistic License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
######################################################################
package Make::Cache::Gcc;
use Make::Cache::Obj;
use Carp;
use strict;
use vars qw(@ISA $Debug);
@ISA=qw(Make::Cache::Obj);
*Debug = \$Make::Cache::Obj::Debug; # "Import" $Debug
our $VERSION = '1.043';
#######################################################################
## Methods that superclasses are likely to override
sub is_legal_cmd {
my $self = shift;
my @cmds = @_;
(my $prog = $cmds[0]) =~ s!.*/!!;
return "gnu" if $self->{force_gcc};
return "gnu" if ($prog =~ /^g\+\+/ || $prog =~ /^gcc/);
return "ghs" if ($prog eq "cxppc");
return undef;
}
#######################################################################
# Overrides of base classes
sub parse_cmds {
my $self = shift;
# Parse the program and arguments. Die if parsing trouble
# Else, load self with necessary info
my @params = $self->cmds_lcl;
my $wholeParams = join(' ',@params);
$params[0] or die "objcache: %Error: Not passed any program on command line\n";
if ($self->{wrapper}) {
# Add wrapper to execution
{
my $sw = $params[0];
shift @params;
push @{$self->{cmds_lcl_cpp_run}}, $sw;
push @{$self->{cmds_lcl_cex_run}}, $sw;
$self->flags_lcl($sw); # Hash it too
}
# Skip arguments up to next wrapper
while (1) {
my $sw = $params[0];
if ($sw =~ /^-/) {
push @{$self->{cmds_lcl_cpp_run}}, $sw;
push @{$self->{cmds_lcl_cex_run}}, $sw;
$self->flags_lcl($sw); # Hash it too
shift @params; # Drop switched argument
} if (!defined $sw) {
die "objcache: %Error: Not passed any program on command line after wrapper name\n";
} else {
last;
}
}
}
my $ccType = $self->is_legal_cmd(@params)
or die "objcache: %Error: Unknown program $params[0] (Or use --help)\n";
# Parse cc's arguments
my $lastsw;
my @tgtfiles;
my @srcfiles;
# It's faster and safer to use the output of the preprocessor
# as that prevents files that change in the middle of the compile
# run from messing things up
$self->{use_preproc_output} = 1 unless $ccType eq "ghs";
my $cmd = shift @params;
$self->{cmds_exec} = $cmd; # Compiler executable name
$self->flags_lcl($cmd);
$self->{cmds_lcl_cpp_run} = [$cmd]; # Commands for preprocessor
$self->{cmds_lcl_cex_run} = [$cmd]; # Commands for compiler
my $dbo;
foreach my $sw (@params) {
if ($sw =~ /^-/) {
$lastsw = $sw;
$dbo=1 if ($sw eq "-G" || $sw eq "-g") && $ccType eq "ghs";
if ($sw ne "-o" # Args for compile only, no cpp
&& $sw ne "-v") {
push @{$self->{cmds_lcl_cpp_run}}, $sw;
}
if ($sw ne "-o"
&& $sw ne "-MP"
&& $sw ne "-MD"
&& $sw ne "-MMD") {
push @{$self->{cmds_lcl_cex_run}}, $sw;
}
if ($sw !~ /^-[DUI]/) { # Skip defines and include path switches in hashing
$self->flags_lcl($sw);
}
} elsif ($lastsw eq "-o") {
push @tgtfiles, $sw;
$self->flags_lcl($sw);
$lastsw = '';
} elsif ($lastsw eq "-x") { # Arguments to pass through to both stages
push @{$self->{cmds_lcl_cpp_run}}, $sw;
push @{$self->{cmds_lcl_cex_run}}, $sw;
$self->flags_lcl($sw);
$lastsw = '';
} else {
push @srcfiles, $sw;
push @{$self->{cmds_lcl_cpp_run}}, $sw;
$self->flags_lcl($sw);
}
}
push @{$self->{cmds_lcl_cpp_run}}, "-E";
if ($Debug) {
print " OrigCmd: ",join(' ',$self->cmds_lcl),"\n";
print " CppCmd: ",join(' ',@{$self->{cmds_lcl_cpp_run}}),"\n";
print " CexeCmd: ",join(' ',@{$self->{cmds_lcl_cex_run}}),"\n";
print " HashCmd: ",join(' ',$self->flags_lcl),"\n";
print " HashGbl: ",join(' ',$self->flags_gbl),"\n";
}
(defined $srcfiles[0]) or die "objcache: %Error: No source filename: $wholeParams\n";
my $no_tgts = !defined $tgtfiles[0];
my $num_tgts = 0;
foreach my $src (@srcfiles) {
($src =~ /\.(c|cc|cpp)$/)
or die "objcache: %Error: Strange source filename: $src: $wholeParams\n";
# Multiple targets aren't cached properly, because we'd need to
# preprocess each source file separately, then pass them all onto gcc.
# Otherwise, they'd just get concatenated which isn't the same thing
# with #defines, or with local static's of the same name.
(++$num_tgts == 1)
or die "objcache: %Error: Multiple source filenames not supported: $src: $wholeParams\n";
$self->deps_lcl($src);
if ($no_tgts) { # Gcc presumes given baz/foo.c that output goes to PWD/foo.o
((my $ofile = $src) =~ s/\.(c|cc|cpp)$/.o/)
or die "objcache: %Error: Strange source filename: $src: $wholeParams\n";
$ofile =~ s%.*[\/\\]%%; # Output goes to PWD, not source's location
push @tgtfiles, $ofile;
}
if ($dbo) { # Ghs presumes given baz/foo.c that output goes to PWD/foo.o
((my $dbofile = $tgtfiles[0]) =~ s/\.(o)$/.dbo/)
or die "objcache: %Error: Strange .o filename: $tgtfiles[0]: $wholeParams\n";
# Output goes to same dir as .o file
push @tgtfiles, $dbofile;
#?? $dbo = 0;
}
}
foreach my $tgt (@tgtfiles) {
$self->tgts_lcl($tgt);
}
}
sub preproc_cmds {
my $self = shift;
my @cmds = @{$self->{cmds_lcl_cpp_run}};
return @cmds;
}
sub compile_cmds {
my $self = shift;
my @cmds;
if ($self->{use_preproc_output}) {
@cmds = @{$self->{cmds_lcl_cex_run}};
push @cmds, $self->temp_filename;
my @tgt = $self->tgts_lcl;
push @cmds, "-o", $tgt[0]; # User may not have specified a -o, and don't want to go to tempfile
} else {
@cmds = @{$self->{cmds_lcl}};
}
return @cmds;
}
######################################################################
1;
__END__
=pod
=head1 NAME
Make::Cache::Gcc - ObjCache specialization for GCC/G++
=head1 DESCRIPTION
Make::Cache::Gcc is a superclass of Make::Cache::Obj with methods
specialized for parsing GCC command lines.
Make::Cache::Gcc will run a GCC in pre-process mode to create a single
source file. This file is then hashed with Make::Cache::Obj, and hits
detected. On misses, GCC is run again to create the targets.
=head1 FUNCTIONS, etc
See L<Make::Cache::Obj>
=head1 DISTRIBUTION
The latest version is available from CPAN and from L<http://www.veripool.com/>.
Copyright 2000-2007 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License or the Perl Artistic License.
=head1 AUTHORS
Wilson Snyder <wsnyder@wsnyder.org>
=head1 SEE ALSO
L<objcache>, L<Make::Cache>, L<Make::Cache::Obj>
=cut
######################################################################
syntax highlighted by Code2HTML, v. 0.9.1