cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm CBuilder methods for OS/2
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm CBuilder methods for Unix
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm CBuilder methods for VMS
+cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm CBuilder methods for Windows
+cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm CBuilder methods for Windows
+cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm CBuilder methods for Windows
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm CBuilder methods for Windows
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm Compile and link C code for Perl modules
cpan/ExtUtils-CBuilder/t/00-have-compiler.t ExtUtils::CBuilder tests
cpan/ExtUtils-CBuilder/t/01-basic.t tests for ExtUtils::CBuilder
cpan/ExtUtils-CBuilder/t/02-link.t tests for ExtUtils::CBuilder
+cpan/ExtUtils-CBuilder/t/03-cplusplus.t tests for ExtUtils::CBuilder
cpan/ExtUtils-Command/lib/ExtUtils/Command.pm Utilities for Make on non-UNIX platforms
cpan/ExtUtils-Command/t/cp.t See if ExtUtils::Command works
cpan/ExtUtils-Command/t/eu_command.t See if ExtUtils::Command works
'ExtUtils::CBuilder' =>
{
'MAINTAINER' => 'kwilliams',
- 'DISTRIBUTION' => 'DAGOLDEN/ExtUtils-CBuilder-0.260301.tar.gz',
+ 'DISTRIBUTION' => 'DAGOLDEN/ExtUtils-CBuilder-0.27.tar.gz',
'FILES' => q[cpan/ExtUtils-CBuilder],
'CPAN' => 1,
'UPSTREAM' => 'cpan',
Revision history for Perl extension ExtUtils::CBuilder.
+0.27 - Thu Oct 29 21:29:56 EDT 2009
+
+ Other:
+ - Removed Build.PL to avoid creating a circular dependency
+ - Added version numbers to Windows compiler driver modules
+
+0.26_05 - Sun Oct 25 17:29:02 EDT 2009
+
+ Bugs fixed:
+ - Fixed t/02link.t failures on cygwin with Perl 5.8 [David Golden]
+
+ Other:
+ - Made have_compiler (and have_cplusplus) quiet without echoing
+ the test command to STDOUT [David Golden]
+
+0.26_04 - Mon Oct 19 21:57:46 EDT 2009
+
+ Enhancements:
+ - Added 'have_cplusplus()' method to check for C++ support
+ - Added patches for building Perl with mingw64 [Sisyphus]
+ - Allow CC environment variable to override $Config{cc}
+
+ Bugs fixed:
+ - Fixed link executable command for Win32 MSVC (RT#40819) [Cosimo
+ Streppone]
+ - Removed MSVC version check when embedding a manifest file
+ (RT #43002) [Steve Hay]
+
+ Other:
+ - Split Windows compiler driver packages into individual *.pm files
+
0.260301 - Sat Aug 29 11:04:41 EDT 2009
Bugs fixed:
use File::Basename ();
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
$VERSION = eval $VERSION;
# Okay, this is the brute-force method of finding out what kind of
link a sample C library. The sample will be compiled in the system
tempdir or, if that fails for some reason, in the current directory.
+=item have_cplusplus
+
+Just like have_compiler but for C++ instead of C.
+
=item compile
Compiles a C source file and produces an object file. The name of the
this is not possible, as a string containing all the arguments
together.
+=item C<C++>
+
+Specifies that the source file is a C++ source file and sets appropriate
+compiler flags
+
=back
The operation of this method is also affected by the
use IO::File;
use vars qw($VERSION);
-$VERSION = '0.260301';
+$VERSION = '0.27';
sub new {
my $class = shift;
while (my ($k,$v) = each %Config) {
$self->{config}{$k} = $v unless exists $self->{config}{$k};
}
+ $self->{config}{cc} = $ENV{CC} if exists $ENV{CC};
return $self;
}
my @extra_compiler_flags = $self->split_like_shell($args{extra_compiler_flags});
my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
my @ccflags = $self->split_like_shell($cf->{ccflags});
+ push @ccflags, qw/-x c++/ if $args{'C++'};
my @optimize = $self->split_like_shell($cf->{optimize});
my @flags = (@include_dirs, @defines, @cccdlflags, @extra_compiler_flags,
$self->arg_nolink,
}
sub have_compiler {
- my ($self) = @_;
+ my ($self, $is_cplusplus) = @_;
return $self->{have_compiler} if defined $self->{have_compiler};
my $result;
# don't clobber existing files (rare, but possible)
my $rand = int(rand(2**31));
my $tmpfile = File::Spec->catfile($dir, "compilet-$rand.c");
+ $tmpfile .= "c" if $is_cplusplus;
if ( -e $tmpfile ) {
redo DIR if $attempts--;
next DIR;
{
my $FH = IO::File->new("> $tmpfile") or die "Can't create $tmpfile: $!";
- print $FH "int boot_compilet() { return 1; }\n";
+ if ( $is_cplusplus ) {
+ print $FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
+ }
+ else {
+ print $FH "int boot_compilet() { return 1; }\n";
+ }
}
my ($obj_file, @lib_files);
eval {
local $^W = 0;
- $obj_file = $self->compile(source => $tmpfile);
+ local $self->{quiet} = 1;
+ $obj_file = $self->compile('C++' => $is_cplusplus, source => $tmpfile);
@lib_files = $self->link(objects => $obj_file, module_name => 'compilet');
};
$result = $@ ? 0 : 1;
return $self->{have_compiler} = $result;
}
+sub have_cplusplus {
+ push @_, 1;
+ goto &have_compiler;
+}
+
sub lib_file {
my ($self, $dl_file) = @_;
$dl_file =~ s/\.[^.]+$//;
use ExtUtils::CBuilder::Base;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Base);
sub link_executable {
use ExtUtils::CBuilder::Base;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Base);
use File::Spec::Functions qw(catfile catdir);
use IO::File;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Base);
+=begin comment
+
+The compiler-specific packages implement functions for generating properly
+formatted commandlines for the compiler being used. Each package
+defines two primary functions 'format_linker_cmd()' &
+'format_compiler_cmd()' that accepts a list of named arguments (a
+hash) and returns a list of formatted options suitable for invoking the
+compiler. By default, if the compiler supports scripting of its
+operation then a script file is built containing the options while
+those options are removed from the commandline, and a reference to the
+script is pushed onto the commandline in their place. Scripting the
+compiler in this way helps to avoid the problems associated with long
+commandlines under some shells.
+
+=end comment
+
+=cut
+
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
my $cf = $self->{config};
# Inherit from an appropriate compiler driver class
- unshift @ISA, "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
+ my $driver = "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
+ eval "require $driver" or die "Could not load compiler driver: $@";
+ unshift @ISA, $driver;
return $self;
}
1;
-########################################################################
-
-=begin comment
-
-The packages below implement functions for generating properly
-formatted commandlines for the compiler being used. Each package
-defines two primary functions 'format_linker_cmd()' &
-'format_compiler_cmd()' that accepts a list of named arguments (a
-hash) and returns a list of formatted options suitable for invoking the
-compiler. By default, if the compiler supports scripting of its
-operation then a script file is built containing the options while
-those options are removed from the commandline, and a reference to the
-script is pushed onto the commandline in their place. Scripting the
-compiler in this way helps to avoid the problems associated with long
-commandlines under some shells.
-
-=end comment
-
-=cut
-
-########################################################################
-package ExtUtils::CBuilder::Platform::Windows::MSVC;
-
-sub format_compiler_cmd {
- my ($self, %spec) = @_;
-
- foreach my $path ( @{ $spec{includes} || [] },
- @{ $spec{perlinc} || [] } ) {
- $path = '-I' . $path;
- }
-
- %spec = $self->write_compiler_script(%spec)
- if $spec{use_scripts};
-
- return [ grep {defined && length} (
- $spec{cc},'-nologo','-c',
- @{$spec{includes}} ,
- @{$spec{cflags}} ,
- @{$spec{optimize}} ,
- @{$spec{defines}} ,
- @{$spec{perlinc}} ,
- "-Fo$spec{output}" ,
- $spec{source} ,
- ) ];
-}
-
-sub write_compiler_script {
- my ($self, %spec) = @_;
-
- my $script = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.ccs' );
-
- $self->add_to_cleanup($script);
- print "Generating script '$script'\n" if !$self->{quiet};
-
- my $SCRIPT = IO::File->new( ">$script" )
- or die( "Could not create script '$script': $!" );
-
- print $SCRIPT join( "\n",
- map { ref $_ ? @{$_} : $_ }
- grep defined,
- delete(
- @spec{ qw(includes cflags optimize defines perlinc) } )
- );
-
- push @{$spec{includes}}, '@"' . $script . '"';
-
- return %spec;
-}
-
-sub format_linker_cmd {
- my ($self, %spec) = @_;
- my $cf = $self->{config};
-
- foreach my $path ( @{$spec{libpath}} ) {
- $path = "-libpath:$path";
- }
-
- my $output = $spec{output};
-
- $spec{def_file} &&= '-def:' . $spec{def_file};
- $spec{output} &&= '-out:' . $spec{output};
- $spec{manifest} &&= '-manifest ' . $spec{manifest};
- $spec{implib} &&= '-implib:' . $spec{implib};
- $spec{map_file} &&= '-map:' . $spec{map_file};
-
- %spec = $self->write_linker_script(%spec)
- if $spec{use_scripts};
-
- my @cmds; # Stores the series of commands needed to build the module.
-
- push @cmds, [ grep {defined && length} (
- $spec{ld} ,
- @{$spec{lddlflags}} ,
- @{$spec{libpath}} ,
- @{$spec{other_ldflags}} ,
- @{$spec{startup}} ,
- @{$spec{objects}} ,
- $spec{map_file} ,
- $spec{libperl} ,
- @{$spec{perllibs}} ,
- $spec{def_file} ,
- $spec{implib} ,
- $spec{output} ,
- ) ];
-
- # Embed the manifest file for VC 2005 (aka VC 8) or higher, but not for the 64-bit Platform SDK compiler
- if ($cf->{ivsize} == 4 && $cf->{cc} eq 'cl' and $cf->{ccversion} =~ /^(\d+)/ and $1 >= 14) {
- push @cmds, [
- 'if', 'exist', $spec{manifest}, 'mt', '-nologo', $spec{manifest}, '-outputresource:' . "$output;2"
- ];
- }
-
- return @cmds;
-}
-
-sub write_linker_script {
- my ($self, %spec) = @_;
-
- my $script = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.lds' );
-
- $self->add_to_cleanup($script);
-
- print "Generating script '$script'\n" if !$self->{quiet};
-
- my $SCRIPT = IO::File->new( ">$script" )
- or die( "Could not create script '$script': $!" );
-
- print $SCRIPT join( "\n",
- map { ref $_ ? @{$_} : $_ }
- grep defined,
- delete(
- @spec{ qw(lddlflags libpath other_ldflags
- startup objects libperl perllibs
- def_file implib map_file) } )
- );
-
- push @{$spec{lddlflags}}, '@"' . $script . '"';
-
- return %spec;
-}
-
-1;
-
-########################################################################
-package ExtUtils::CBuilder::Platform::Windows::BCC;
-
-sub format_compiler_cmd {
- my ($self, %spec) = @_;
-
- foreach my $path ( @{ $spec{includes} || [] },
- @{ $spec{perlinc} || [] } ) {
- $path = '-I' . $path;
- }
-
- %spec = $self->write_compiler_script(%spec)
- if $spec{use_scripts};
-
- return [ grep {defined && length} (
- $spec{cc}, '-c' ,
- @{$spec{includes}} ,
- @{$spec{cflags}} ,
- @{$spec{optimize}} ,
- @{$spec{defines}} ,
- @{$spec{perlinc}} ,
- "-o$spec{output}" ,
- $spec{source} ,
- ) ];
-}
-
-sub write_compiler_script {
- my ($self, %spec) = @_;
-
- my $script = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.ccs' );
-
- $self->add_to_cleanup($script);
-
- print "Generating script '$script'\n" if !$self->{quiet};
-
- my $SCRIPT = IO::File->new( ">$script" )
- or die( "Could not create script '$script': $!" );
-
- # XXX Borland "response files" seem to be unable to accept macro
- # definitions containing quoted strings. Escaping strings with
- # backslash doesn't work, and any level of quotes are stripped. The
- # result is is a floating point number in the source file where a
- # string is expected. So we leave the macros on the command line.
- print $SCRIPT join( "\n",
- map { ref $_ ? @{$_} : $_ }
- grep defined,
- delete(
- @spec{ qw(includes cflags optimize perlinc) } )
- );
-
- push @{$spec{includes}}, '@"' . $script . '"';
-
- return %spec;
-}
-
-sub format_linker_cmd {
- my ($self, %spec) = @_;
-
- foreach my $path ( @{$spec{libpath}} ) {
- $path = "-L$path";
- }
-
- push( @{$spec{startup}}, 'c0d32.obj' )
- unless ( $spec{starup} && @{$spec{startup}} );
-
- %spec = $self->write_linker_script(%spec)
- if $spec{use_scripts};
-
- return [ grep {defined && length} (
- $spec{ld} ,
- @{$spec{lddlflags}} ,
- @{$spec{libpath}} ,
- @{$spec{other_ldflags}} ,
- @{$spec{startup}} ,
- @{$spec{objects}} , ',',
- $spec{output} , ',',
- $spec{map_file} , ',',
- $spec{libperl} ,
- @{$spec{perllibs}} , ',',
- $spec{def_file}
- ) ];
-}
-
-sub write_linker_script {
- my ($self, %spec) = @_;
-
- # To work around Borlands "unique" commandline syntax,
- # two scripts are used:
-
- my $ld_script = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.lds' );
- my $ld_libs = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.lbs' );
-
- $self->add_to_cleanup($ld_script, $ld_libs);
-
- print "Generating scripts '$ld_script' and '$ld_libs'.\n" if !$self->{quiet};
-
- # Script 1: contains options & names of object files.
- my $LD_SCRIPT = IO::File->new( ">$ld_script" )
- or die( "Could not create linker script '$ld_script': $!" );
-
- print $LD_SCRIPT join( " +\n",
- map { @{$_} }
- grep defined,
- delete(
- @spec{ qw(lddlflags libpath other_ldflags startup objects) } )
- );
-
- # Script 2: contains name of libs to link against.
- my $LD_LIBS = IO::File->new( ">$ld_libs" )
- or die( "Could not create linker script '$ld_libs': $!" );
-
- print $LD_LIBS join( " +\n",
- (delete $spec{libperl} || ''),
- @{delete $spec{perllibs} || []},
- );
-
- push @{$spec{lddlflags}}, '@"' . $ld_script . '"';
- push @{$spec{perllibs}}, '@"' . $ld_libs . '"';
-
- return %spec;
-}
-
-1;
-
-########################################################################
-package ExtUtils::CBuilder::Platform::Windows::GCC;
-
-sub format_compiler_cmd {
- my ($self, %spec) = @_;
-
- foreach my $path ( @{ $spec{includes} || [] },
- @{ $spec{perlinc} || [] } ) {
- $path = '-I' . $path;
- }
-
- # split off any -arguments included in cc
- my @cc = split / (?=-)/, $spec{cc};
-
- return [ grep {defined && length} (
- @cc, '-c' ,
- @{$spec{includes}} ,
- @{$spec{cflags}} ,
- @{$spec{optimize}} ,
- @{$spec{defines}} ,
- @{$spec{perlinc}} ,
- '-o', $spec{output} ,
- $spec{source} ,
- ) ];
-}
-
-sub format_linker_cmd {
- my ($self, %spec) = @_;
-
- # The Config.pm variable 'libperl' is hardcoded to the full name
- # of the perl import library (i.e. 'libperl56.a'). GCC will not
- # find it unless the 'lib' prefix & the extension are stripped.
- $spec{libperl} =~ s/^(?:lib)?([^.]+).*$/-l$1/;
-
- unshift( @{$spec{other_ldflags}}, '-nostartfiles' )
- if ( $spec{startup} && @{$spec{startup}} );
-
- # From ExtUtils::MM_Win32:
- #
- ## one thing for GCC/Mingw32:
- ## we try to overcome non-relocateable-DLL problems by generating
- ## a (hopefully unique) image-base from the dll's name
- ## -- BKS, 10-19-1999
- File::Basename::basename( $spec{output} ) =~ /(....)(.{0,4})/;
- $spec{image_base} = sprintf( "0x%x0000", unpack('n', $1 ^ $2) );
-
- %spec = $self->write_linker_script(%spec)
- if $spec{use_scripts};
-
- foreach my $path ( @{$spec{libpath}} ) {
- $path = "-L$path";
- }
-
- my @cmds; # Stores the series of commands needed to build the module.
-
- push @cmds, [
- 'dlltool', '--def' , $spec{def_file},
- '--output-exp' , $spec{explib}
- ];
-
- # split off any -arguments included in ld
- my @ld = split / (?=-)/, $spec{ld};
-
- push @cmds, [ grep {defined && length} (
- @ld ,
- '-o', $spec{output} ,
- "-Wl,--base-file,$spec{base_file}" ,
- "-Wl,--image-base,$spec{image_base}" ,
- @{$spec{lddlflags}} ,
- @{$spec{libpath}} ,
- @{$spec{startup}} ,
- @{$spec{objects}} ,
- @{$spec{other_ldflags}} ,
- $spec{libperl} ,
- @{$spec{perllibs}} ,
- $spec{explib} ,
- $spec{map_file} ? ('-Map', $spec{map_file}) : ''
- ) ];
-
- push @cmds, [
- 'dlltool', '--def' , $spec{def_file},
- '--output-exp' , $spec{explib},
- '--base-file' , $spec{base_file}
- ];
-
- push @cmds, [ grep {defined && length} (
- @ld ,
- '-o', $spec{output} ,
- "-Wl,--image-base,$spec{image_base}" ,
- @{$spec{lddlflags}} ,
- @{$spec{libpath}} ,
- @{$spec{startup}} ,
- @{$spec{objects}} ,
- @{$spec{other_ldflags}} ,
- $spec{libperl} ,
- @{$spec{perllibs}} ,
- $spec{explib} ,
- $spec{map_file} ? ('-Map', $spec{map_file}) : ''
- ) ];
-
- return @cmds;
-}
-
-sub write_linker_script {
- my ($self, %spec) = @_;
-
- my $script = File::Spec->catfile( $spec{srcdir},
- $spec{basename} . '.lds' );
-
- $self->add_to_cleanup($script);
-
- print "Generating script '$script'\n" if !$self->{quiet};
-
- my $SCRIPT = IO::File->new( ">$script" )
- or die( "Could not create script '$script': $!" );
-
- print $SCRIPT ( 'SEARCH_DIR(' . $_ . ")\n" )
- for @{delete $spec{libpath} || []};
-
- # gcc takes only one startup file, so the first object in startup is
- # specified as the startup file and any others are shifted into the
- # beginning of the list of objects.
- if ( $spec{startup} && @{$spec{startup}} ) {
- print $SCRIPT 'STARTUP(' . shift( @{$spec{startup}} ) . ")\n";
- unshift @{$spec{objects}},
- @{delete $spec{startup} || []};
- }
-
- print $SCRIPT 'INPUT(' . join( ',',
- @{delete $spec{objects} || []}
- ) . ")\n";
-
- print $SCRIPT 'INPUT(' . join( ' ',
- (delete $spec{libperl} || ''),
- @{delete $spec{perllibs} || []},
- ) . ")\n";
-
- #it is important to keep the order 1.linker_script - 2.other_ldflags
- @{$spec{other_ldflags}} = ( '"' . $script . '"', @{$spec{other_ldflags}} );
-
- return %spec;
-}
-
-1;
-
__END__
=head1 NAME
--- /dev/null
+package ExtUtils::CBuilder::Platform::Windows::BCC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc}, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-o$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ # XXX Borland "response files" seem to be unable to accept macro
+ # definitions containing quoted strings. Escaping strings with
+ # backslash doesn't work, and any level of quotes are stripped. The
+ # result is is a floating point number in the source file where a
+ # string is expected. So we leave the macros on the command line.
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ push( @{$spec{startup}}, 'c0d32.obj' )
+ unless ( $spec{starup} && @{$spec{startup}} );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} , ',',
+ $spec{output} , ',',
+ $spec{map_file} , ',',
+ $spec{libperl} ,
+ @{$spec{perllibs}} , ',',
+ $spec{def_file}
+ ) ];
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ # To work around Borlands "unique" commandline syntax,
+ # two scripts are used:
+
+ my $ld_script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+ my $ld_libs = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lbs' );
+
+ $self->add_to_cleanup($ld_script, $ld_libs);
+
+ print "Generating scripts '$ld_script' and '$ld_libs'.\n" if !$self->{quiet};
+
+ # Script 1: contains options & names of object files.
+ my $LD_SCRIPT = IO::File->new( ">$ld_script" )
+ or die( "Could not create linker script '$ld_script': $!" );
+
+ print $LD_SCRIPT join( " +\n",
+ map { @{$_} }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags startup objects) } )
+ );
+
+ # Script 2: contains name of libs to link against.
+ my $LD_LIBS = IO::File->new( ">$ld_libs" )
+ or die( "Could not create linker script '$ld_libs': $!" );
+
+ print $LD_LIBS join( " +\n",
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $ld_script . '"';
+ push @{$spec{perllibs}}, '@"' . $ld_libs . '"';
+
+ return %spec;
+}
+
+1;
+
+
--- /dev/null
+package ExtUtils::CBuilder::Platform::Windows::GCC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ # split off any -arguments included in cc
+ my @cc = split / (?=-)/, $spec{cc};
+
+ return [ grep {defined && length} (
+ @cc, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ '-o', $spec{output} ,
+ $spec{source} ,
+ ) ];
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ # The Config.pm variable 'libperl' is hardcoded to the full name
+ # of the perl import library (i.e. 'libperl56.a'). GCC will not
+ # find it unless the 'lib' prefix & the extension are stripped.
+ $spec{libperl} =~ s/^(?:lib)?([^.]+).*$/-l$1/;
+
+ unshift( @{$spec{other_ldflags}}, '-nostartfiles' )
+ if ( $spec{startup} && @{$spec{startup}} );
+
+ # From ExtUtils::MM_Win32:
+ #
+ ## one thing for GCC/Mingw32:
+ ## we try to overcome non-relocateable-DLL problems by generating
+ ## a (hopefully unique) image-base from the dll's name
+ ## -- BKS, 10-19-1999
+ File::Basename::basename( $spec{output} ) =~ /(....)(.{0,4})/;
+ $spec{image_base} = sprintf( "0x%x0000", unpack('n', $1 ^ $2) );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ my $DLLTOOL = $cf->{dlltool} || 'dlltool';
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib}
+ ];
+
+ # split off any -arguments included in ld
+ my @ld = split / (?=-)/, $spec{ld};
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--base-file,$spec{base_file}" ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib},
+ '--base-file' , $spec{base_file}
+ ];
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT ( 'SEARCH_DIR(' . $_ . ")\n" )
+ for @{delete $spec{libpath} || []};
+
+ # gcc takes only one startup file, so the first object in startup is
+ # specified as the startup file and any others are shifted into the
+ # beginning of the list of objects.
+ if ( $spec{startup} && @{$spec{startup}} ) {
+ print $SCRIPT 'STARTUP(' . shift( @{$spec{startup}} ) . ")\n";
+ unshift @{$spec{objects}},
+ @{delete $spec{startup} || []};
+ }
+
+ print $SCRIPT 'INPUT(' . join( ',',
+ @{delete $spec{objects} || []}
+ ) . ")\n";
+
+ print $SCRIPT 'INPUT(' . join( ' ',
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ ) . ")\n";
+
+ #it is important to keep the order 1.linker_script - 2.other_ldflags
+ unshift @{$spec{other_ldflags}}, '"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
--- /dev/null
+package ExtUtils::CBuilder::Platform::Windows::MSVC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return "/OUT:$file";
+}
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc},'-nologo','-c',
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-Fo$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize defines perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-libpath:$path";
+ }
+
+ my $output = $spec{output};
+
+ $spec{def_file} &&= '-def:' . $spec{def_file};
+ $spec{output} &&= '-out:' . $spec{output};
+ $spec{manifest} &&= '-manifest ' . $spec{manifest};
+ $spec{implib} &&= '-implib:' . $spec{implib};
+ $spec{map_file} &&= '-map:' . $spec{map_file};
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ push @cmds, [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ $spec{map_file} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{def_file} ,
+ $spec{implib} ,
+ $spec{output} ,
+ ) ];
+
+ # Embed the manifest file if it exists
+ push @cmds, [
+ 'if', 'exist', $spec{manifest}, 'mt', '-nologo', $spec{manifest}, '-outputresource:' . "$output;2"
+ ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags
+ startup objects libperl perllibs
+ def_file implib map_file) } )
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
use File::Spec;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub need_prelink { 1 }
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+# TODO: If a specific exe_file name is requested, if the exe created
+# doesn't have that name, we might want to rename it. Apparently asking
+# for an exe of "foo" might result in "foo.exe". Alternatively, we should
+# make sure the return value is correctly "foo.exe".
+# C.f http://rt.cpan.org/Public/Bug/Display.html?id=41003
sub link_executable {
my $self = shift;
- # $Config{ld} is okay. Circumvent the Unix ld=cc override in the superclass.
- local $self->{config}{cc} = $self->{config}{ld};
return $self->SUPER::link_executable(@_);
}
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub compile {
use vars qw($VERSION @ISA);
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
-$VERSION = '0.260301';
+$VERSION = '0.27';
sub link_executable {
my $self = shift;
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub need_prelink { 1 }
}
}
-plan tests => 4;
+plan tests => 6;
require_ok "ExtUtils::CBuilder";
my $b = eval { ExtUtils::CBuilder->new(quiet => 1) };
ok( $b, "got CBuilder object" ) or diag $@;
+my $bogus_path = 'djaadjfkadjkfajdf';
+my $run_perl = "$perl -e1 --";
# test missing compiler
-$b->{config}{cc} = 'djaadjfkadjkfajdf';
-$b->{config}{ld} = 'djaadjfkadjkfajdf';
+$b->{config}{cc} = $bogus_path;
+$b->{config}{ld} = $bogus_path;
+
+$b->{have_compiler} = undef;
is( $b->have_compiler, 0, "have_compiler: fake missing cc" );
+$b->{have_compiler} = undef;
+is( $b->have_cplusplus, 0, "have_cplusplus: fake missing c++" );
# test found compiler
+$b->{config}{cc} = $run_perl;
+$b->{config}{ld} = $run_perl;
$b->{have_compiler} = undef;
-$b->{config}{cc} = "$perl -e1 --";
-$b->{config}{ld} = "$perl -e1 --";
is( $b->have_compiler, 1, "have_compiler: fake present cc" );
+$b->{have_compiler} = undef;
+is( $b->have_cplusplus, 1, "have_cpp_compiler: fake present c++" );
-
+# test missing cpp compiler
use strict;
use Test::More;
-BEGIN {
+BEGIN {
if ($^O eq 'VMS') {
# So we can get the return value of system()
require vmsish;
plan skip_all => "no compiler available for testing";
}
else {
- plan tests => 7;
+ plan tests => 8;
}
ok $b, "created EU::CB object";
# Link
SKIP: {
- skip "error compiling source", 3
+ skip "error compiling source", 4
unless -e $object_file;
my @temps;
eval { ($exe_file, @temps) = $b->link_executable(objects => $object_file) };
is $@, q{}, "no exception from linking";
ok -e $exe_file, "found executable file";
+ ok -x $exe_file, "executable file appears to be executable";
if ($^O eq 'os2') { # Analogue of LDLOADPATH...
# Actually, not needed now, since we do not link with the generated DLL
# Try the executable
my $ec = my_system($exe_file);
- is $ec, 11, "got expected exit code from executable"
- or print( $? == -1 ? "# Could not run '$exe_file'\n"
- : "# Unexpected exit code '$ec'\n");
+ is( $ec, 11, "got expected exit code from executable" )
+ or diag( $ec == -1 ? "Could not run '$exe_file': $!\n"
+ : "Unexpected exit code '$ec'\n");
}
# Clean up
sub my_system {
my $cmd = shift;
+ my $ec;
if ($^O eq 'VMS') {
- return system("mcr $cmd");
+ $ec = system("mcr $cmd");
}
- return system($cmd) >> 8;
+ $ec = system($cmd);
+ return $ec == -1 ? -1 : $ec >> 8;
}
--- /dev/null
+#! perl -w
+
+use strict;
+use Test::More;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use ExtUtils::CBuilder;
+use File::Spec;
+
+# TEST doesn't like extraneous output
+my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
+my ($source_file, $object_file, $lib_file);
+
+my $b = ExtUtils::CBuilder->new(quiet => $quiet);
+
+# test plan
+if ( ! $b->have_cplusplus ) {
+ plan skip_all => "no compiler available for testing";
+}
+else {
+ plan tests => 7;
+}
+
+ok $b, "created EU::CB object";
+
+ok $b->have_cplusplus, "have_cplusplus";
+
+$source_file = File::Spec->catfile('t', 'compilet.cc');
+{
+ local *FH;
+ open FH, "> $source_file" or die "Can't create $source_file: $!";
+ print FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
+ close FH;
+}
+ok -e $source_file, "source file '$source_file' created";
+
+$object_file = $b->object_file($source_file);
+ok 1;
+
+is $object_file, $b->compile(source => $source_file, 'C++' => 1);
+
+$lib_file = $b->lib_file($object_file);
+ok 1;
+
+my ($lib, @temps) = $b->link(objects => $object_file,
+ module_name => 'compilet');
+$lib =~ tr/"'//d;
+is $lib_file, $lib;
+
+for ($source_file, $object_file, $lib_file) {
+ tr/"'//d;
+ 1 while unlink;
+}
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+