Alien-ROOT

 view release on metacpan or  search on metacpan

inc/inc_Module-Build/Module/Build/WithXSpp.pm  view on Meta::CPAN

      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" );

inc/inc_Module-Build/Module/Build/WithXSpp.pm  view on Meta::CPAN

  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
in the L</"FEATURES AND CONVENTIONS"> section below. But if you
can't be bothered to read all that, you may choose skip it and
blindly follow the advice in L</"JUMP START FOR THE IMPATIENT">.

An example of a full distribution based on this build tool
can be found in the L<ExtUtils::XSpp> distribution under
F<examples/XSpp-Example>. Using that example as the basis
for your C<Module::Build::WithXSpp>-based distribution
is probably a good idea.

=head1 FEATURES AND CONVENTIONS

=head2 XS files

By default, C<Module::Build::WithXSpp> will automatically
generate a main XS file for your module which includes
all XS++ files and does the correct incantations to support
C++.

If C<Module::Build::WithXSpp> detects any XS files in your
module, it will skip the generation of this default file
and assume that you wrote a custom main XS file. If
that is not what you want, and wish to simply include
plain XS code, then you should put the XS in a verbatim
block of an F<.xsp> file. In case you need to use the plain-C
part of an XS file for C<#include> directives and other code,
then put your code into a header file and C<#include> it
from an F<.xsp> file:

In F<src/mystuff.h>:

  #include <something>
  using namespace some::thing;

In F<xsp/MyClass.xsp>

  #include "mystuff.h"
  
  %{
    ... verbatim XS here ...
  %}

Note that there is no guarantee about the order in which the
XS++ files are picked up.

=head2 Build directory

When building your XS++ based extension, a temporary
build directory F<buildtmp> is created for the byproducts.
It is automatically cleaned up by C<./Build clean>.

=head2 Source directories

A Perl module distribution typically has the module C<.pm> files
in its F<lib> subdirectory. In a C<Module::Build::WithXSpp> based



( run in 1.378 second using v1.01-cache-2.11-cpan-ceb78f64989 )