Updated ExtUtils::CBuilder to 0.27
David Golden [Fri, 30 Oct 2009 01:40:33 +0000 (21:40 -0400)]
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

19 files changed:
MANIFEST
Porting/Maintainers.pl
cpan/ExtUtils-CBuilder/Changes
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Base.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm [new file with mode: 0644]
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm [new file with mode: 0644]
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm [new file with mode: 0644]
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/aix.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/cygwin.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/darwin.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm
cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm
cpan/ExtUtils-CBuilder/t/00-have-compiler.t
cpan/ExtUtils-CBuilder/t/02-link.t
cpan/ExtUtils-CBuilder/t/03-cplusplus.t [new file with mode: 0644]

index 02c4c49..4f685b8 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -918,11 +918,15 @@ cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm  CBuilder method
 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
index 6a35023..e4794c3 100755 (executable)
@@ -559,7 +559,7 @@ use File::Glob qw(:case);
     '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',
index 776a05d..b86c638 100644 (file)
@@ -1,5 +1,36 @@
 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:
index 209afa8..7854e88 100644 (file)
@@ -5,7 +5,7 @@ use File::Path ();
 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
@@ -133,6 +133,10 @@ linker, false otherwise.  To determine this, we actually compile and
 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
@@ -161,6 +165,11 @@ given as a list reference containing the arguments individually, or if
 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
index ccd9692..28036c6 100644 (file)
@@ -9,7 +9,7 @@ use Text::ParseWords;
 use IO::File;
 
 use vars qw($VERSION);
-$VERSION = '0.260301';
+$VERSION = '0.27';
 
 sub new {
   my $class = shift;
@@ -21,6 +21,7 @@ sub new {
   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;
 }
 
@@ -98,6 +99,7 @@ sub compile {
   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,
@@ -114,7 +116,7 @@ sub compile {
 }
 
 sub have_compiler {
-  my ($self) = @_;
+  my ($self, $is_cplusplus) = @_;
   return $self->{have_compiler} if defined $self->{have_compiler};
 
   my $result;
@@ -125,6 +127,7 @@ sub have_compiler {
     # 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;
@@ -132,13 +135,19 @@ sub have_compiler {
 
     {
       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;
@@ -152,6 +161,11 @@ sub have_compiler {
   return $self->{have_compiler} = $result;
 }
 
+sub have_cplusplus {
+  push @_, 1;
+  goto &have_compiler;
+}
+
 sub lib_file {
   my ($self, $dl_file) = @_;
   $dl_file =~ s/\.[^.]+$//;
index 92efcc4..78ff244 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use ExtUtils::CBuilder::Base;
 
 use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
 @ISA = qw(ExtUtils::CBuilder::Base);
 
 sub link_executable {
index 5f58e39..35a2eba 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 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);
index a613073..f0b98db 100644 (file)
@@ -10,16 +10,36 @@ use ExtUtils::CBuilder::Base;
 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;
 }
@@ -238,423 +258,6 @@ sub perl_inc {
 
 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
diff --git a/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm b/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm
new file mode 100644 (file)
index 0000000..ee65c91
--- /dev/null
@@ -0,0 +1,130 @@
+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;
+
+
diff --git a/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm b/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm
new file mode 100644 (file)
index 0000000..132bf84
--- /dev/null
@@ -0,0 +1,151 @@
+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;
+
+
diff --git a/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm b/cpan/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm
new file mode 100644 (file)
index 0000000..7da1c9b
--- /dev/null
@@ -0,0 +1,131 @@
+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;
+
+
index c03dc6e..656e0dc 100644 (file)
@@ -5,7 +5,7 @@ use ExtUtils::CBuilder::Platform::Unix;
 use File::Spec;
 
 use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
 @ISA = qw(ExtUtils::CBuilder::Platform::Unix);
 
 sub need_prelink { 1 }
index 64a0c99..f865097 100644 (file)
@@ -5,13 +5,16 @@ use File::Spec;
 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(@_);
 }
 
index b187cb0..efc7934 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use ExtUtils::CBuilder::Platform::Unix;
 
 use vars qw($VERSION @ISA);
-$VERSION = '0.260301';
+$VERSION = '0.27';
 @ISA = qw(ExtUtils::CBuilder::Platform::Unix);
 
 sub compile {
index f4ca387..d07b71f 100644 (file)
@@ -6,7 +6,7 @@ use File::Spec;
 
 use vars qw($VERSION @ISA);
 @ISA = qw(ExtUtils::CBuilder::Platform::Unix);
-$VERSION = '0.260301';
+$VERSION = '0.27';
 
 sub link_executable {
   my $self = shift;
index a150e12..2815d58 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 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 }
index 245bce5..f20f891 100644 (file)
@@ -16,22 +16,30 @@ BEGIN {
   }
 }
 
-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
index 1e55f6a..76ab28c 100644 (file)
@@ -2,7 +2,7 @@
 
 use strict;
 use Test::More;
-BEGIN { 
+BEGIN {
   if ($^O eq 'VMS') {
     # So we can get the return value of system()
     require vmsish;
@@ -26,7 +26,7 @@ elsif ( ! $b->have_compiler ) {
   plan skip_all => "no compiler available for testing";
 }
 else {
-  plan tests => 7;
+  plan tests => 8;
 }
 
 ok $b, "created EU::CB object";
@@ -47,13 +47,14 @@ ok -e $object_file, "found object file";
 
 # 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
@@ -65,9 +66,9 @@ SKIP: {
 
   # 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
@@ -83,8 +84,10 @@ if ($^O eq 'VMS') {
 
 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;
 }
diff --git a/cpan/ExtUtils-CBuilder/t/03-cplusplus.t b/cpan/ExtUtils-CBuilder/t/03-cplusplus.t
new file mode 100644 (file)
index 0000000..4e13381
--- /dev/null
@@ -0,0 +1,64 @@
+#! 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';
+}
+