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-CBuilder/t/04-base.t tests for ExtUtils::CBuilder
cpan/ExtUtils-Constant/lib/ExtUtils/Constant/Base.pm generate XS code to import C header constants
cpan/ExtUtils-Constant/lib/ExtUtils/Constant.pm generate XS code to import C header constants
cpan/ExtUtils-Constant/lib/ExtUtils/Constant/ProxySubs.pm generate XS code for proxy constants
'ExtUtils::CBuilder' =>
{
'MAINTAINER' => 'kwilliams',
- 'DISTRIBUTION' => 'DAGOLDEN/ExtUtils-CBuilder-0.2703.tar.gz',
+ 'DISTRIBUTION' => 'DAGOLDEN/ExtUtils-CBuilder-0.2800.tar.gz',
'FILES' => q[cpan/ExtUtils-CBuilder],
'UPSTREAM' => 'cpan',
},
Revision history for Perl extension ExtUtils::CBuilder.
+0.2800 - Mon Dec 6 16:05:46 EST 2010
+
+ - No changes from 0.27_07
+
+0.27_07 - Wed Sep 29 21:48:55 EDT 2010
+
+ Fixed:
+
+ - Fixed t/02-link.t on perl < 5.8
+
+0.27_06 - Mon Sep 27 15:29:54 EDT 2010
+
+ Fixed:
+
+ - Preserves exit status on VMS [Craig Berry]
+
+ - Fix Win32 split_like_shell escaping [Christian Walde]
+
+0.27_05 - Wed Jul 28 15:29:59 EDT 2010
+
+ Fixed:
+
+ - Tests no longer fail if user has set the CC environment variable
+
+0.27_04 - Mon Jul 26 22:41:43 EDT 2010
+
+ Added:
+ - handle c compiler and c++ compiler separately
+ (adds requirement for IPC::Cmd) [Jens Rehsack]
+
+ Others:
+ - rely on File::Temp::tempfile and File::Spec::tmpdir to
+ get unique file name for checking for compiler
+ [Jens Rehsack]
+
+ - Code base modernization and substantial code coverage improvments
+ [Jim Keenan]
+
0.2703 - Tue Mar 16 17:10:55 EDT 2010
Bugs fixed:
- Various parts of the code were looking for the CORE/ directory in
$Config{archlib}, $Config{installarchlib}, and $Config{archlibexp}.
- Only the latter is correct, so we use that everywhere now.
+ Only the latter is correct, so we use that everywhere now.
[Curt Tilmes]
- For Unix-ish platforms, link_executable() will now prefer
use File::Basename ();
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
$VERSION = eval $VERSION;
# Okay, this is the brute-force method of finding out what kind of
use Config;
use Text::ParseWords;
use IO::File;
+use Data::Dumper;$Data::Dumper::Indent=1;
+use IPC::Cmd qw(can_run);
+use File::Temp qw(tempfile);
use vars qw($VERSION);
-$VERSION = '0.2703_01';
+$VERSION = '0.2800';
+
+# More details about C/C++ compilers:
+# http://developers.sun.com/sunstudio/documentation/product/compiler.jsp
+# http://gcc.gnu.org/
+# http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp
+# http://msdn.microsoft.com/en-us/vstudio/default.aspx
+
+my %cc2cxx = (
+ # first line order is important to support wrappers like in pkgsrc
+ cc => [ 'c++', 'CC', 'aCC', 'cxx', ], # Sun Studio, HP ANSI C/C++ Compilers
+ gcc => [ 'g++' ], # GNU Compiler Collection
+ xlc => [ 'xlC' ], # IBM C/C++ Set, xlc without thread-safety
+ xlc_r => [ 'xlC_r' ], # IBM C/C++ Set, xlc with thread-safety
+ cl => [ 'cl' ], # Microsoft Visual Studio
+);
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};
+ $self->{config}{cc} = $ENV{CC} if defined $ENV{CC};
+ $self->{config}{ccflags} = $ENV{CFLAGS} if defined $ENV{CFLAGS};
+ $self->{config}{cxx} = $ENV{CXX} if defined $ENV{CXX};
+ $self->{config}{cxxflags} = $ENV{CXXFLAGS} if defined $ENV{CXXFLAGS};
+ $self->{config}{ld} = $ENV{LD} if defined $ENV{LD};
+ $self->{config}{ldflags} = $ENV{LDFLAGS} if defined $ENV{LDFLAGS};
+
+ unless ( exists $self->{config}{cxx} ) {
+ my ($ccpath, $ccbase, $ccsfx ) = fileparse($self->{config}{cc}, qr/\.[^.]*/);
+ foreach my $cxx (@{$cc2cxx{$ccbase}}) {
+ if( can_run( File::Spec->catfile( $ccpath, $cxx, $ccsfx ) ) ) {
+ $self->{config}{cxx} = File::Spec->catfile( $ccpath, $cxx, $ccsfx );
+ last;
+ }
+ if( can_run( File::Spec->catfile( $cxx, $ccsfx ) ) ) {
+ $self->{config}{cxx} = File::Spec->catfile( $cxx, $ccsfx );
+ last;
+ }
+ if( can_run( $cxx ) ) {
+ $self->{config}{cxx} = $cxx;
+ last;
+ }
+ }
+ unless ( exists $self->{config}{cxx} ) {
+ $self->{config}{cxx} = $self->{config}{cc};
+ my $cflags = $self->{config}{cflags};
+ $self->{config}{cxxflags} = '-x c++';
+ $self->{config}{cxxflags} .= " $cflags" if defined $cflags;
+ }
+ }
+
return $self;
}
my $perl;
File::Spec->file_name_is_absolute($perl = $^X)
or -f ($perl = $Config::Config{perlpath})
- or ($perl = $^X);
+ or ($perl = $^X); # XXX how about using IPC::Cmd::can_run here?
return $perl;
}
}
}
+sub get_config {
+ return %{ $_[0]->{config} };
+}
+
sub object_file {
my ($self, $filename) = @_;
die "Missing 'source' argument to compile()" unless defined $args{source};
my $cf = $self->{config}; # For convenience
-
- $args{object_file} ||= $self->object_file($args{source});
-
- $args{include_dirs} = [ $args{include_dirs} ]
- if exists($args{include_dirs}) && ref($args{include_dirs}) ne "ARRAY";
-
- my @include_dirs = $self->arg_include_dirs
- (@{$args{include_dirs} || []},
- $self->perl_inc());
+
+ my $object_file = $args{object_file}
+ ? $args{object_file}
+ : $self->object_file($args{source});
+
+ my $include_dirs_ref =
+ (exists($args{include_dirs}) && ref($args{include_dirs}) ne "ARRAY")
+ ? [ $args{include_dirs} ]
+ : $args{include_dirs};
+ my @include_dirs = $self->arg_include_dirs(
+ @{ $include_dirs_ref || [] },
+ $self->perl_inc(),
+ );
my @defines = $self->arg_defines( %{$args{defines} || {}} );
- my @extra_compiler_flags = $self->split_like_shell($args{extra_compiler_flags});
+ 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 @ccflags = $self->split_like_shell($args{'C++'} ? $cf->{cxxflags} : $cf->{ccflags});
my @optimize = $self->split_like_shell($cf->{optimize});
- my @flags = (@include_dirs, @defines, @cccdlflags, @extra_compiler_flags,
- $self->arg_nolink,
- @ccflags, @optimize,
- $self->arg_object_file($args{object_file}),
- );
-
- my @cc = $self->split_like_shell($cf->{cc});
+ my @flags = (
+ @include_dirs,
+ @defines,
+ @cccdlflags,
+ @extra_compiler_flags,
+ $self->arg_nolink,
+ @ccflags,
+ @optimize,
+ $self->arg_object_file($object_file),
+ );
+ my @cc = $self->split_like_shell($args{'C++'} ? $cf->{cxx} : $cf->{cc});
$self->do_system(@cc, @flags, $args{source})
- or die "error building $args{object_file} from '$args{source}'";
+ or die "error building $object_file from '$args{source}'";
- return $args{object_file};
+ return $object_file;
}
sub have_compiler {
my ($self, $is_cplusplus) = @_;
- return $self->{have_compiler} if defined $self->{have_compiler};
+ my $have_compiler_flag = $is_cplusplus ? "have_cxx" : "have_cc";
+ my $suffix = $is_cplusplus ? ".cc" : ".c";
+ return $self->{$have_compiler_flag} if defined $self->{$have_compiler_flag};
my $result;
my $attempts = 3;
# tmpdir has issues for some people so fall back to current dir
- DIR: for my $dir ( File::Spec->tmpdir, '.' ) {
-
- # 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: $!";
- if ( $is_cplusplus ) {
- print $FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
- }
- else {
- print $FH "int boot_compilet() { return 1; }\n";
- }
- }
+ # don't clobber existing files (rare, but possible)
+ my ( $FH, $tmpfile ) = tempfile( "compilet-XXXXX", SUFFIX => $suffix );
+ binmode $FH;
- my ($obj_file, @lib_files);
- eval {
- local $^W = 0;
- 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;
-
- foreach (grep defined, $tmpfile, $obj_file, @lib_files) {
- 1 while unlink;
- }
- last DIR if $result;
+ 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;
+ 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;
+
+ foreach (grep defined, $tmpfile, $obj_file, @lib_files) {
+ 1 while unlink;
}
- return $self->{have_compiler} = $result;
+ return $self->{$have_compiler_flag} = $result;
}
sub have_cplusplus {
sub prelink {
my ($self, %args) = @_;
-
- ($args{dl_file} = $args{dl_name}) =~ s/.*::// unless $args{dl_file};
-
+
+ my ($dl_file_out, $mksymlists_args) = _prepare_mksymlists_args(\%args);
+
require ExtUtils::Mksymlists;
- ExtUtils::Mksymlists::Mksymlists( # dl. abbrev for dynamic library
- DL_VARS => $args{dl_vars} || [],
- DL_FUNCS => $args{dl_funcs} || {},
- FUNCLIST => $args{dl_func_list} || [],
- IMPORTS => $args{dl_imports} || {},
- NAME => $args{dl_name}, # Name of the Perl module
- DLBASE => $args{dl_base}, # Basename of DLL file
- FILE => $args{dl_file}, # Dir + Basename of symlist file
- VERSION => (defined $args{dl_version} ? $args{dl_version} : '0.0'),
- );
-
+ # dl. abbrev for dynamic library
+ ExtUtils::Mksymlists::Mksymlists( %{ $mksymlists_args } );
+
# Mksymlists will create one of these files
- return grep -e, map "$args{dl_file}.$_", qw(ext def opt);
+ return grep -e, map "$dl_file_out.$_", qw(ext def opt);
+}
+
+sub _prepare_mksymlists_args {
+ my $args = shift;
+ ($args->{dl_file} = $args->{dl_name}) =~ s/.*::// unless $args->{dl_file};
+
+ my %mksymlists_args = (
+ DL_VARS => $args->{dl_vars} || [],
+ DL_FUNCS => $args->{dl_funcs} || {},
+ FUNCLIST => $args->{dl_func_list} || [],
+ IMPORTS => $args->{dl_imports} || {},
+ NAME => $args->{dl_name}, # Name of the Perl module
+ DLBASE => $args->{dl_base}, # Basename of DLL file
+ FILE => $args->{dl_file}, # Dir + Basename of symlist file
+ VERSION => (defined $args->{dl_version} ? $args->{dl_version} : '0.0'),
+ );
+ return ($args->{dl_file}, \%mksymlists_args);
}
sub link {
my @temp_files;
@temp_files =
- $self->prelink(%args,
- dl_name => $args{module_name}) if $args{lddl} && $self->need_prelink;
+ $self->prelink(%args, dl_name => $args{module_name})
+ if $args{lddl} && $self->need_prelink;
- my @linker_flags = ($self->split_like_shell($args{extra_linker_flags}),
- $self->extra_link_args_after_prelink(%args, dl_name => $args{module_name},
- prelink_res => \@temp_files));
+ my @linker_flags = (
+ $self->split_like_shell($args{extra_linker_flags}),
+ $self->extra_link_args_after_prelink(
+ %args, dl_name => $args{module_name}, prelink_res => \@temp_files
+ )
+ );
- my @output = $args{lddl} ? $self->arg_share_object_file($out) : $self->arg_exec_file($out);
+ my @output = $args{lddl}
+ ? $self->arg_share_object_file($out)
+ : $self->arg_exec_file($out);
my @shrp = $self->split_like_shell($cf->{shrpenv});
my @ld = $self->split_like_shell($cf->{ld});
$string =~ s/^\s+|\s+$//g;
return () unless length($string);
+ # Text::ParseWords replaces all 'escaped' characters with themselves, which completely
+ # breaks paths under windows. As such, we forcibly replace backwards slashes with forward
+ # slashes on windows.
+ $string =~ s@\\@/@g if $^O eq 'MSWin32';
+
return Text::ParseWords::shellwords($string);
}
# Try up to 5 levels upwards
for (0..10) {
if (
- -f File::Spec->catfile($dir,"config_h.SH")
- &&
- -f File::Spec->catfile($dir,"perl.h")
- &&
- -f File::Spec->catfile($dir,"lib","Exporter.pm")
- ) {
+ -f File::Spec->catfile($dir,"config_h.SH")
+ &&
+ -f File::Spec->catfile($dir,"perl.h")
+ &&
+ -f File::Spec->catfile($dir,"lib","Exporter.pm")
+ ) {
return Cwd::realpath( $dir );
}
}
1;
+
+# vim: ts=2 sw=2 et:
use ExtUtils::CBuilder::Base;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Base);
sub link_executable {
use ExtUtils::CBuilder::Base;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Base);
use File::Spec::Functions qw(catfile catdir);
use IO::File;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Base);
=begin comment
builddir => $srcdir,
basename => $basename,
source => $args{source},
- output => File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
+ output => $args{object_file} || File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
cc => $cf->{cc},
cflags => [
$self->split_like_shell($cf->{ccflags}),
package ExtUtils::CBuilder::Platform::Windows::BCC;
use vars qw($VERSION);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
sub format_compiler_cmd {
my ($self, %spec) = @_;
package ExtUtils::CBuilder::Platform::Windows::GCC;
use vars qw($VERSION);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
sub format_compiler_cmd {
my ($self, %spec) = @_;
package ExtUtils::CBuilder::Platform::Windows::MSVC;
use vars qw($VERSION);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
sub arg_exec_file {
my ($self, $file) = @_;
use File::Spec;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub need_prelink { 1 }
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
# TODO: If a specific exe_file name is requested, if the exe created
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub compile {
use vars qw($VERSION @ISA);
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
sub link_executable {
my $self = shift;
use ExtUtils::CBuilder::Platform::Unix;
use vars qw($VERSION @ISA);
-$VERSION = '0.2703';
+$VERSION = '0.2800';
@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
sub need_prelink { 1 }
}
}
-plan tests => 6;
+plan tests => 7;
require_ok "ExtUtils::CBuilder";
$b->{config}{cc} = $bogus_path;
$b->{config}{ld} = $bogus_path;
-$b->{have_compiler} = undef;
+$b->{have_cc} = undef;
is( $b->have_compiler, 0, "have_compiler: fake missing cc" );
-$b->{have_compiler} = undef;
+$b->{have_cxx} = 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}{cxx} = $run_perl;
+$b->{have_cc} = undef;
is( $b->have_compiler, 1, "have_compiler: fake present cc" );
-$b->{have_compiler} = undef;
+$b->{have_cxx} = undef;
is( $b->have_cplusplus, 1, "have_cpp_compiler: fake present c++" );
# test missing cpp compiler
+
+# test one non-exported subroutine
+{
+ my $type = ExtUtils::CBuilder::os_type();
+ if ($type) {
+ pass( "OS type $type located for $^O" );
+ }
+ else {
+ pass( "OS type not yet listed for $^O" );
+ }
+}
use ExtUtils::CBuilder;
use File::Spec;
-# TEST doesn't like extraneous output
+# TEST does not like extraneous output
my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
my ($source_file, $object_file, $lib_file);
use ExtUtils::CBuilder;
use File::Spec;
-# TEST doesn't like extraneous output
+# TEST does not like extraneous output
my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
my ($source_file, $object_file, $exe_file);
$source_file = File::Spec->catfile('t', 'compilet.c');
{
- local *FH;
- open FH, "> $source_file" or die "Can't create $source_file: $!";
- print FH "int main(void) { return 11; }\n";
- close FH;
+ open my $FH, "> $source_file" or die "Can't create $source_file: $!";
+ print $FH "int main(void) { return 11; }\n";
+ close $FH;
}
ok -e $source_file, "generated '$source_file'";
my $cmd = shift;
my $ec;
if ($^O eq 'VMS') {
- # Preserve non-posixified status and don't bit shift the result.
- use vmsish 'status';
+ # Preserve non-posixified status and don't bit shift the result
+ # because we're running under "use vmsish";
$ec = system("mcr $cmd");
return $ec;
}
- $ec = system($cmd);
- return $ec == -1 ? -1 : $ec >> 8;
+ else {
+ $ec = system($cmd);
+ return $ec == -1 ? -1 : $ec >> 8;
+ }
}
use ExtUtils::CBuilder;
use File::Spec;
-# TEST doesn't like extraneous output
+# TEST does not like extraneous output
my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
my ($source_file, $object_file, $lib_file);
$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;
+ open my $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";
--- /dev/null
+#! perl -w
+
+use strict;
+use Test::More tests => 58;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use Config;
+use Cwd;
+use File::Path qw( mkpath );
+use File::Temp qw( tempdir );
+use ExtUtils::CBuilder::Base;
+
+# XXX protect from user CC as we mock everything here
+local $ENV{CC};
+
+my ( $base, $phony, $cwd );
+my ( $source_file, $object_file, $lib_file );
+
+$base = ExtUtils::CBuilder::Base->new();
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+{
+ $phony = 'foobar';
+ $base = ExtUtils::CBuilder::Base->new(
+ config => { cc => $phony },
+ );
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( $base->{config}->{cc}, $phony,
+ "Got expected value when 'config' argument passed to new()" );
+}
+
+{
+ $phony = 'barbaz';
+ local $ENV{CC} = $phony;
+ $base = ExtUtils::CBuilder::Base->new();
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( $base->{config}->{cc}, $phony,
+ "Got expected value \$ENV{CC} set" );
+}
+
+{
+ my $path_to_perl = File::Spec->catfile( '', qw| usr bin perl | );
+ local $^X = $path_to_perl;
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $path_to_perl,
+ "find_perl_interpreter() returned expected absolute path"
+ );
+}
+
+{
+ my $path_to_perl = 'foobar';
+ local $^X = $path_to_perl;
+ # %Config is read-only. We cannot assign to it and we therefore cannot
+ # simulate the condition that would occur were its value something other
+ # than an existing file.
+ if ( !$ENV{PERL_CORE} and $Config::Config{perlpath}) {
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $Config::Config{perlpath},
+ "find_perl_interpreter() returned expected file"
+ );
+ }
+ else {
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $path_to_perl,
+ "find_perl_interpreter() returned expected name"
+ );
+ }
+}
+
+{
+ $cwd = cwd();
+ my $tdir = tempdir();
+ chdir $tdir;
+ $base = ExtUtils::CBuilder::Base->new();
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( scalar keys %{$base->{files_to_clean}}, 0,
+ "No files needing cleaning yet" );
+
+ my $file_for_cleaning = File::Spec->catfile( $tdir, 'foobar' );
+ open my $IN, '>', $file_for_cleaning
+ or die "Unable to open dummy file: $!";
+ print $IN "\n";
+ close $IN or die "Unable to close dummy file: $!";
+
+ $base->add_to_cleanup( $file_for_cleaning );
+ is( scalar keys %{$base->{files_to_clean}}, 1,
+ "One file needs cleaning" );
+
+ $base->cleanup();
+ ok( ! -f $file_for_cleaning, "File was cleaned up" );
+
+ chdir $cwd;
+}
+
+# fake compiler is perl and will always succeed
+$base = ExtUtils::CBuilder::Base->new(
+ config => {
+ cc => File::Spec->rel2abs($^X) . " -e1 --",
+ ld => File::Spec->rel2abs($^X) . " -e1 --",
+ }
+);
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+eval {
+ $base->compile(foo => 'bar');
+};
+like(
+ $@,
+ qr/Missing 'source' argument to compile/,
+ "Got expected error message when lacking 'source' argument to compile()"
+);
+
+$base = ExtUtils::CBuilder::Base->new( quiet => 1 );
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+create_c_source_file($source_file);
+ok(-e $source_file, "source file '$source_file' created");
+
+# object filename automatically assigned
+my $obj_ext = $base->{config}{obj_ext};
+is( $base->object_file($source_file),
+ File::Spec->catfile('t', "compilet$obj_ext"),
+ "object_file(): got expected automatically assigned name for object file"
+);
+
+# object filename explicitly assigned
+$object_file = File::Spec->catfile('t', 'my_special_compilet.o' );
+is( $object_file,
+ $base->compile(
+ source => $source_file,
+ object_file => $object_file,
+ ),
+ "compile(): returned object file with specified name"
+);
+
+$lib_file = $base->lib_file($object_file);
+ok( $lib_file, "lib_file() returned true value" );
+
+my ($lib, @temps);
+($lib, @temps) = $base->link(
+ objects => $object_file,
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+($lib, @temps) = $base->link(
+ objects => [ $object_file ],
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+($lib, @temps) = $base->link(
+ lib_file => $lib_file,
+ objects => [ $object_file ],
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+$lib = $base->link(
+ objects => $object_file,
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+{
+ local $ENV{PERL_CORE} = '' unless $ENV{PERL_CORE};
+ my $include_dir = $base->perl_inc();
+ ok( $include_dir, "perl_inc() returned true value" );
+ ok( -d $include_dir, "perl_inc() returned directory" );
+}
+
+#
+$base = ExtUtils::CBuilder::Base->new( quiet => 1 );
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+create_c_source_file($source_file);
+ok(-e $source_file, "source file '$source_file' created");
+$object_file = File::Spec->catfile('t', 'my_special_compilet.o' );
+is( $object_file,
+ $base->compile(
+ source => $source_file,
+ object_file => $object_file,
+ defines => { alpha => 'beta', gamma => 'delta' },
+ ),
+ "compile() completed when 'defines' provided; returned object file with specified name"
+);
+
+my $exe_file = $base->exe_file($object_file);
+my $ext = $base->{config}{_exe};
+my $expected = File::Spec->catfile('t', qq|my_special_compilet$ext| );
+is(
+ $exe_file,
+ $expected,
+ "exe_file(): returned expected name of executable"
+);
+
+my %args = ();
+my @defines = $base->arg_defines( %args );
+ok( ! @defines, "Empty hash passed to arg_defines() returns empty list" );
+
+%args = ( alpha => 'beta', gamma => 'delta' );
+my $defines_seen_ref = { map { $_ => 1 } $base->arg_defines( %args ) };
+is_deeply(
+ $defines_seen_ref,
+ { '-Dalpha=beta' => 1, '-Dgamma=delta' => 1 },
+ "arg_defines(): got expected defines",
+);
+
+my $include_dirs_seen_ref =
+ { map {$_ => 1} $base->arg_include_dirs( qw| alpha beta gamma | ) };
+is_deeply(
+ $include_dirs_seen_ref,
+ { '-Ialpha' => 1, '-Ibeta' => 1, '-Igamma' => 1 },
+ "arg_include_dirs(): got expected include_dirs",
+);
+
+is( '-c', $base->arg_nolink(), "arg_nolink(): got expected value" );
+
+my $seen_ref =
+ { map {$_ => 1} $base->arg_object_file('alpha') };
+is_deeply(
+ $seen_ref,
+ { '-o' => 1, 'alpha' => 1 },
+ "arg_object_file(): got expected option flag and value",
+);
+
+$seen_ref = { map {$_ => 1} $base->arg_share_object_file('alpha') };
+my %exp = map {$_ => 1} $base->split_like_shell($base->{config}{lddlflags});
+$exp{'-o'} = 1;
+$exp{'alpha'} = 1;
+
+is_deeply(
+ $seen_ref,
+ \%exp,
+ "arg_share_object_file(): got expected option flag and value",
+);
+
+$seen_ref =
+ { map {$_ => 1} $base->arg_exec_file('alpha') };
+is_deeply(
+ $seen_ref,
+ { '-o' => 1, 'alpha' => 1 },
+ "arg_exec_file(): got expected option flag and value",
+);
+
+ok(! $base->split_like_shell(undef),
+ "split_like_shell(): handled undefined argument as expected" );
+
+my $array_ref = [ qw| alpha beta gamma | ];
+my %split_seen = map { $_ => 1 } $base->split_like_shell($array_ref);
+%exp = ( alpha => 1, beta => 1, gamma => 1 );
+is_deeply( \%split_seen, \%exp,
+ "split_like_shell(): handled array ref as expected" );
+
+{
+ $cwd = cwd();
+ my $tdir = tempdir();
+ my $subdir = File::Spec->catdir(
+ $tdir, qw| alpha beta gamma delta epsilon
+ zeta eta theta iota kappa lambda |
+ );
+ mkpath($subdir, { mode => 0711 } );
+ chdir $subdir
+ or die "Unable to change to temporary directory for testing";
+ local $ENV{PERL_CORE} = 1;
+ my $capture = q{};
+ local $SIG{__WARN__} = sub { $capture = $_[0] };
+ my $expected_message =
+ qr/PERL_CORE is set but I can't find your perl source!/; #'
+ my $rv;
+
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $config = File::Spec->catfile( $subdir, 'config_h.SH' );
+ touch_file($config);
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $perlh = File::Spec->catfile( $subdir, 'perl.h' );
+ touch_file($perlh);
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $libsubdir = File::Spec->catdir( $subdir, 'lib' );
+ mkpath($libsubdir, { mode => 0711 } );
+ my $exporter = File::Spec->catfile( $libsubdir, 'Exporter.pm' );
+ touch_file($exporter);
+ $rv = $base->perl_src();
+ ok( -d $rv, "perl_src(): returned a directory" );
+ is( $rv, Cwd::realpath($subdir), "perl_src(): identified directory" );
+ is( $capture, q{}, "perl_src(): no warning, as expected" );
+
+ chdir $cwd
+ or die "Unable to change from temporary directory after testing";
+}
+
+my ($dl_file_out, $mksymlists_args);
+my $dlf = 'Kappa';
+%args = (
+ dl_vars => [ qw| alpha beta gamma | ],
+ dl_funcs => {
+ 'Homer::Iliad' => [ qw(trojans greeks) ],
+ 'Homer::Odyssey' => [ qw(travellers family suitors) ],
+ },
+ dl_func_list => [ qw| delta epsilon | ],
+ dl_imports => { zeta => 'eta', theta => 'iota' },
+ dl_name => 'Tk::Canvas',
+ dl_base => 'Tk::Canvas.ext',
+ dl_file => $dlf,
+ dl_version => '7.7',
+);
+($dl_file_out, $mksymlists_args) =
+ ExtUtils::CBuilder::Base::_prepare_mksymlists_args(\%args);
+is( $dl_file_out, $dlf, "_prepare_mksymlists_args(): Got expected name for dl_file" );
+is_deeply( $mksymlists_args,
+ {
+ DL_VARS => [ qw| alpha beta gamma | ],
+ DL_FUNCS => {
+ 'Homer::Iliad' => [ qw(trojans greeks) ],
+ 'Homer::Odyssey' => [ qw(travellers family suitors) ],
+ },
+ FUNCLIST => [ qw| delta epsilon | ],
+ IMPORTS => { zeta => 'eta', theta => 'iota' },
+ NAME => 'Tk::Canvas',
+ DLBASE => 'Tk::Canvas.ext',
+ FILE => $dlf,
+ VERSION => '7.7',
+ },
+ "_prepare_mksymlists_args(): got expected arguments for Mksymlists",
+);
+
+$dlf = 'Canvas';
+%args = (
+ dl_name => 'Tk::Canvas',
+ dl_base => 'Tk::Canvas.ext',
+);
+($dl_file_out, $mksymlists_args) =
+ ExtUtils::CBuilder::Base::_prepare_mksymlists_args(\%args);
+is( $dl_file_out, $dlf, "_prepare_mksymlists_args(): got expected name for dl_file" );
+is_deeply( $mksymlists_args,
+ {
+ DL_VARS => [],
+ DL_FUNCS => {},
+ FUNCLIST => [],
+ IMPORTS => {},
+ NAME => 'Tk::Canvas',
+ DLBASE => 'Tk::Canvas.ext',
+ FILE => $dlf,
+ VERSION => '0.0',
+ },
+ "_prepare_mksymlists_args(): got expected arguments for Mksymlists",
+);
+
+#####
+
+for ($source_file, $object_file, $lib_file) {
+ tr/"'//d; #"
+ 1 while unlink;
+}
+
+pass("Completed all tests in $0");
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+
+sub create_c_source_file {
+ my $source_file = shift;
+ open my $FH, '>', $source_file or die "Can't create $source_file: $!";
+ print $FH "int boot_compilet(void) { return 1; }\n";
+ close $FH;
+}
+
+sub touch_file {
+ my $f = shift;
+ open my $FH, '>', $f or die "Can't create $f: $!";
+ print $FH "\n";
+ close $FH;
+ return $f;
+}
=item *
+C<ExtUtils::CBuilder> has been upgraded from 0.2703 to 0.2800
+
+=item *
+
C<if> has been upgraded from 0.06 to 0.0601.
=item *