Alien-ROOT

 view release on metacpan or  search on metacpan

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


  if ($self->dist_name ne 'Module-Build-WithXSpp'
      and $self->auto_configure_requires)
  {
    if (not exists $p->{configure_requires}{'Module::Build::WithXSpp'}) {
      (my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only
      $self->_add_prereq('configure_requires', 'Module::Build::WithXSpp', $ver);
    }
    if (not exists $p->{configure_requires}{'ExtUtils::CppGuess'}) {
      (my $ver = $ExtUtils::CppGuess::VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only
      $self->_add_prereq('configure_requires', 'ExtUtils::CppGuess', $ver);
    }
    if (not exists $p->{build_requires}{'ExtUtils::CppGuess'}
        and eval("require ExtUtils::XSpp;")
        and defined $ExtUtils::XSpp::VERSION)
    {
      (my $ver = $ExtUtils::XSpp::VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only
      $self->_add_prereq('build_requires', 'ExtUtils::XSpp', $ver);
    }
  }

  $self->SUPER::auto_require();

  return;
}

sub ACTION_create_buildarea {
  my $self = shift;
  mkdir($self->build_dir);
  $self->add_to_cleanup($self->build_dir);
}

sub ACTION_code {
  my $self = shift;
  $self->depends_on('create_buildarea');
  $self->depends_on('generate_typemap');
  $self->depends_on('generate_main_xs');

  my $files = {};
  foreach my $ext (qw(c cc cxx cpp C)) {
    foreach my $dir (@{$self->cpp_source_dirs||[]}) {
      my $this = $self->_find_file_by_type($ext, $dir);
      $files = $self->_merge_hashes($files, $this);
    }
  }

  my @objects;
  foreach my $file (keys %$files) {
    my $obj = $self->compile_c($file);
    push @objects, $obj;
    $self->add_to_cleanup($obj);
  }

  $self->{properties}{objects} ||= [];
  push @{$self->{properties}{objects}}, @objects;

  return $self->SUPER::ACTION_code(@_);
}

# I guess I should use a module here.
sub _naive_shell_escape {
  my $s = shift;
  $s =~ s/\\/\\\\/g;
  $s =~ s/"/\\"/g;
  $s
}

sub ACTION_generate_main_xs {
  my $self = shift;

  my $xs_files = $self->find_xs_files;
  my $main_xs_file = File::Spec->catfile($self->build_dir, 'main.xs');

  if (keys(%$xs_files) > 1) {
    # user knows what she's doing, do not generate XS
    $self->log_info("Found custom XS files. Not auto-generating main XS file...\n");
    return 1;
  }

  my $xsp_files = $self->find_xsp_files;
  my $xspt_files = $self->find_xsp_typemaps;

  my $newest = $self->_calc_newest(
    keys(%$xsp_files),
    keys(%$xspt_files),
    'Build.PL',
    File::Spec->catdir($self->build_dir, 'typemap'),
  );

  if (keys(%$xs_files) == 1
      && (values(%$xs_files))[0] =~ /\Q$main_xs_file\E$/)
  {
    # is main xs file still current?
    if (-M $main_xs_file < $newest) {
      return 1;
    }
  }

  $self->log_info("Generating main XS file...\n");

  my $early_includes = join "\n",
                       map {
                         s/^\s*#\s*include\s*//i;
                         /^"/ or $_ = "<$_>";
                         "#include $_"
                       }
                       @{ $self->early_includes || [] };

  my $module_name = $self->module_name;
  my $xs_code = <<"HERE";
/*
 * WARNING: This file was auto-generated. Changes will be lost!
 */

$early_includes

#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#undef do_open
#undef do_close
#ifdef __cplusplus
}
#endif

MODULE = $module_name	PACKAGE = $module_name

HERE

  my $typemap_args = '';
  $typemap_args .= '-t "' . _naive_shell_escape(Cwd::abs_path($_)) . '" ' foreach keys %$xspt_files;

  foreach my $xsp_file (keys %$xsp_files) {
    my $full_path_file = _naive_shell_escape( Cwd::abs_path($xsp_file) );
    my $cmd = qq{INCLUDE_COMMAND: \$^X -MExtUtils::XSpp::Cmd -e xspp -- $typemap_args "$full_path_file"\n\n};
    $xs_code .= $cmd;
  }

  my $outfile = File::Spec->catdir($self->build_dir, 'main.xs');
  open my $fh, '>', $outfile
    or die "Could not open '$outfile' for writing: $!";
  print $fh $xs_code;
  close $fh;

  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;



( run in 1.227 second using v1.01-cache-2.11-cpan-62a16548d74 )