Alien-ROOT
view release on metacpan or search on metacpan
inc/inc_Module-Build/Module/Build/WithXSpp.pm view on Meta::CPAN
return 1;
}
sub _load_extra_typemap_modules {
my $self = shift;
require ExtUtils::Typemaps;
my $extra_modules = $self->extra_typemap_modules||{};
foreach my $module (keys %$extra_modules) {
my $str = $extra_modules->{$module}
? "$module $extra_modules->{$module}"
: $module;
if (not eval "use $str;1;") {
$self->log_warn(<<HERE);
ERROR: Required typemap module '$module' version $extra_modules->{$module} not found.
Error message:
$@
HERE
}
}
}
sub ACTION_generate_typemap {
my $self = shift;
$self->depends_on('create_buildarea');
require File::Spec;
my $files = $self->find_map_files;
$self->_load_extra_typemap_modules();
my $extra_modules = $self->extra_typemap_modules||{};
my $newest = $self->_calc_newest(
keys(%$files),
'Build.PL',
);
my $out_map_file = File::Spec->catfile($self->build_dir, 'typemap');
if (-f $out_map_file and -M $out_map_file < $newest) {
return 1;
}
$self->log_info("Processing XS typemap files...\n");
# merge all typemaps into 'buildtmp/typemap'
# creates empty typemap file if there are no files to merge
my $merged = ExtUtils::Typemaps->new;
$merged->merge(typemap => $_->new) for keys %$extra_modules;
foreach my $file (keys %$files) {
$merged->merge(typemap => ExtUtils::Typemaps->new(file => $file));
}
$merged->write(file => $out_map_file);
}
sub find_map_files {
my $self = shift;
my $files = $self->_find_file_by_type('map', 'lib');
my @extra_files = map glob($_),
map File::Spec->catfile($_, '*.map'),
(@{$self->extra_xs_dirs||[]});
$files->{$_} = $_ foreach map $self->localize_file_path($_),
@extra_files;
$files->{'typemap'} = 'typemap' if -f 'typemap';
return $files;
}
sub find_xsp_files {
my $self = shift;
my @extra_files = map glob($_),
map File::Spec->catfile($_, '*.xsp'),
(@{$self->extra_xs_dirs||[]});
my $files = $self->_find_file_by_type('xsp', 'lib');
$files->{$_} = $_ foreach map $self->localize_file_path($_),
@extra_files;
require File::Basename;
# XS++ typemaps aren't XSP files in this regard
foreach my $file (keys %$files) {
delete $files->{$file}
if File::Basename::basename($file) eq 'typemap.xsp';
}
return $files;
}
sub find_xsp_typemaps {
my $self = shift;
my $xsp_files = $self->_find_file_by_type('xsp', 'lib');
my $xspt_files = $self->_find_file_by_type('xspt', 'lib');
foreach (keys %$xsp_files) { # merge over 'typemap.xsp's
next unless File::Basename::basename($_) eq 'typemap.xsp';
$xspt_files->{$_} = $_
}
my @extra_files = grep -e $_,
map glob($_),
grep defined $_ && /\S/,
map { ( File::Spec->catfile($_, 'typemap.xsp'),
File::Spec->catfile($_, '*.xspt') ) }
@{$self->extra_xs_dirs||[]};
$xspt_files->{$_} = $_ foreach map $self->localize_file_path($_),
@extra_files;
return $xspt_files;
}
# This overrides the equivalent in the base class to add the buildtmp and
# the main directory
sub find_xs_files {
my $self = shift;
my $xs_files = $self->SUPER::find_xs_files;
my @extra_files = map glob($_),
map File::Spec->catfile($_, '*.xs'),
@{$self->extra_xs_dirs||[]};
$xs_files->{$_} = $_ foreach map $self->localize_file_path($_),
@extra_files;
my $auto_gen_file = File::Spec->catfile($self->build_dir, 'main.xs');
if (-e $auto_gen_file) {
$xs_files->{$auto_gen_file} = $self->localize_file_path($auto_gen_file);
}
return $xs_files;
}
# overridden from original. We really require
# EU::ParseXS, so the "if (eval{require EU::PXS})" is gone.
sub compile_xs {
my ($self, $file, %args) = @_;
$self->log_verbose("$file -> $args{outfile}\n");
require ExtUtils::ParseXS;
my $main_dir = Cwd::abs_path( Cwd::cwd() );
my $build_dir = Cwd::abs_path( $self->build_dir );
ExtUtils::ParseXS::process_file(
filename => $file,
prototypes => 0,
output => $args{outfile},
# not default:
'C++' => 1,
hiertype => 1,
typemap => File::Spec->catfile($build_dir, 'typemap'),
);
}
# modified from orinal M::B (FIXME: shouldn't do this with private methods)
# Changes from the original:
# - If we're looking at the "main.xs" file in the build
# directory, override the TARGET paths with the real
# module name.
# - In that case, also override the file basename for further
# build products (maybe this should only be done on installation
# into blib/.../?)
sub _infer_xs_spec {
my $self = shift;
my $file = shift;
my $cf = $self->{config};
my %spec;
my( $v, $d, $f ) = File::Spec->splitpath( $file );
my @d = File::Spec->splitdir( $d );
(my $file_base = $f) =~ s/\.[^.]+$//i;
my $build_folder = $self->build_dir;
if ($d =~ /\Q$build_folder\E/ && $file_base eq 'main') {
my $name = $self->module_name;
@d = split /::/, $name;
$file_base = $d[-1];
pop @d if @d;
}
else {
# the module name
shift( @d ) while @d && ($d[0] eq 'lib' || $d[0] eq '');
pop( @d ) while @d && $d[-1] eq '';
}
$spec{base_name} = $file_base;
$spec{src_dir} = File::Spec->catpath( $v, $d, '' );
$spec{module_name} = join( '::', (@d, $file_base) );
$spec{archdir} = File::Spec->catdir($self->blib, 'arch', 'auto',
@d, $file_base);
$spec{bs_file} = File::Spec->catfile($spec{archdir}, "${file_base}.bs");
$spec{lib_file} = File::Spec->catfile($spec{archdir},
"${file_base}.".$cf->get('dlext'));
$spec{c_file} = File::Spec->catfile( $spec{src_dir},
"${file_base}.c" );
$spec{obj_file} = File::Spec->catfile( $spec{src_dir},
"${file_base}".$cf->get('obj_ext') );
return \%spec;
}
__PACKAGE__->add_property( 'cpp_source_dirs' => ['src'] );
__PACKAGE__->add_property( 'build_dir' => 'buildtmp' );
__PACKAGE__->add_property( 'extra_xs_dirs' => [".", grep { -d $_ and /^xsp?$/i } glob("*")] );
__PACKAGE__->add_property( 'extra_typemap_modules' => {} );
__PACKAGE__->add_property( 'early_includes' => [] );
sub _merge_hashes {
my $self = shift;
my %h;
foreach my $m (@_) {
$h{$_} = $m->{$_} foreach keys %$m;
}
return \%h;
}
sub _calc_newest {
my $self = shift;
my $newest = 1.e99;
foreach my $file (@_) {
next if not defined $file;
my $age = -M $file;
$newest = $age if defined $age and $age < $newest;
}
return $newest;
}
1;
__END__
=head1 NAME
Module::Build::WithXSpp - XS++ enhanced flavour of Module::Build
=head1 SYNOPSIS
In F<Build.PL>:
use strict;
use warnings;
use 5.006001;
use Module::Build::WithXSpp;
my $build = Module::Build::WithXSpp->new(
# normal Module::Build arguments...
# optional: mix in some extra C typemaps:
extra_typemap_modules => {
'ExtUtils::Typemaps::ObjectMap' => '0',
},
);
$build->create_build_script;
=head1 DESCRIPTION
This subclass of L<Module::Build> adds some tools and
processes to make it easier to use for wrapping C++
using XS++ (L<ExtUtils::XSpp>).
There are a few minor differences from using C<Module::Build>
for an ordinary XS module and a few conventions that you
should be aware of as an XS++ module author. They are documented
( run in 1.835 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )