Acme-Sort-Sleep

 view release on metacpan or  search on metacpan

local/lib/perl5/Module/Build/Base.pm  view on Meta::CPAN

             $self->install_sets($self->installdirs)->{$type} )
         ) ? 1 : 0;
}

sub _is_ActivePerl {
#  return 0;
  my $self = shift;
  unless (exists($self->{_is_ActivePerl})) {
    $self->{_is_ActivePerl} = (eval { require ActivePerl::DocTools; } || 0);
  }
  return $self->{_is_ActivePerl};
}

sub _is_ActivePPM {
#  return 0;
  my $self = shift;
  unless (exists($self->{_is_ActivePPM})) {
    $self->{_is_ActivePPM} = (eval { require ActivePerl::PPM; } || 0);
  }
  return $self->{_is_ActivePPM};
}

sub ACTION_manpages {
  my $self = shift;

  return unless $self->_mb_feature('manpage_support');

  $self->depends_on('code');

  my %extra_manify_args = $self->{properties}{'extra_manify_args'} ? %{ $self->{properties}{'extra_manify_args'} } : ();

  foreach my $type ( qw(bin lib) ) {
    next unless ( $self->invoked_action eq 'manpages' || $self->_is_default_installable("${type}doc"));
    my $files = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
                                   exclude => [ $self->file_qr('\.bat$') ] );
    next unless %$files;

    my $sub = $self->can("manify_${type}_pods");
    $self->$sub( %extra_manify_args ) if defined( $sub );
  }
}

sub manify_bin_pods {
  my $self    = shift;
  my %podman_args = (section =>  1, @_); # binaries go in section 1

  my $files   = $self->_find_pods( $self->{properties}{bindoc_dirs},
                                   exclude => [ $self->file_qr('\.bat$') ] );
  return unless keys %$files;

  my $mandir = File::Spec->catdir( $self->blib, 'bindoc' );
  File::Path::mkpath( $mandir, 0, oct(777) );

  require Pod::Man;
  foreach my $file (sort keys %$files) {
    # Pod::Simple based parsers only support one document per instance.
    # This is expected to change in a future version (Pod::Simple > 3.03).
    my $parser  = Pod::Man->new( %podman_args );
    my $manpage = $self->man1page_name( $file ) . '.' .
                  $self->config( 'man1ext' );
    my $outfile = File::Spec->catfile($mandir, $manpage);
    next if $self->up_to_date( $file, $outfile );
    $self->log_verbose("Manifying $file -> $outfile\n");
    eval { $parser->parse_from_file( $file, $outfile ); 1 }
      or $self->log_warn("Error creating '$outfile': $@\n");
    $files->{$file} = $outfile;
  }
}

sub manify_lib_pods {
  my $self    = shift;
  my %podman_args = (section => 3, @_); # libraries go in section 3

  my $files   = $self->_find_pods($self->{properties}{libdoc_dirs});
  return unless keys %$files;

  my $mandir = File::Spec->catdir( $self->blib, 'libdoc' );
  File::Path::mkpath( $mandir, 0, oct(777) );

  require Pod::Man;
  foreach my $file (sort keys %$files) {
    # Pod::Simple based parsers only support one document per instance.
    # This is expected to change in a future version (Pod::Simple > 3.03).
    my $parser  = Pod::Man->new( %podman_args );
    my $manpage = $self->man3page_name( $files->{$file} ) . '.' .
                  $self->config( 'man3ext' );
    my $outfile = File::Spec->catfile( $mandir, $manpage);
    next if $self->up_to_date( $file, $outfile );
    $self->log_verbose("Manifying $file -> $outfile\n");
    eval { $parser->parse_from_file( $file, $outfile ); 1 }
      or $self->log_warn("Error creating '$outfile': $@\n");
    $files->{$file} = $outfile;
  }
}

sub _find_pods {
  my ($self, $dirs, %args) = @_;
  my %files;
  foreach my $spec (@$dirs) {
    my $dir = $self->localize_dir_path($spec);
    next unless -e $dir;

    FILE: foreach my $file ( @{ $self->rscan_dir( $dir ) } ) {
      foreach my $regexp ( @{ $args{exclude} } ) {
        next FILE if $file =~ $regexp;
      }
      $file = $self->localize_file_path($file);
      $files{$file} = File::Spec->abs2rel($file, $dir) if $self->contains_pod( $file )
    }
  }
  return \%files;
}

sub contains_pod {
  my ($self, $file) = @_;
  return '' unless -T $file;  # Only look at text files

  open(my $fh, '<', $file ) or die "Can't open $file: $!";
  while (my $line = <$fh>) {
    return 1 if $line =~ /^\=(?:head|pod|item)/;
  }

  return '';
}

sub ACTION_html {
  my $self = shift;

  return unless $self->_mb_feature('HTML_support');

  $self->depends_on('code');

  foreach my $type ( qw(bin lib) ) {
    next unless ( $self->invoked_action eq 'html' || $self->_is_default_installable("${type}html"));
    $self->htmlify_pods( $type );
  }
}

# 1) If it's an ActiveState perl install, we need to run
#    ActivePerl::DocTools->UpdateTOC;
# 2) Links to other modules are not being generated
sub htmlify_pods {
  my $self = shift;
  my $type = shift;
  my $htmldir = shift || File::Spec->catdir($self->blib, "${type}html");

  $self->add_to_cleanup('pod2htm*');

  my $pods = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
                                exclude => [ $self->file_qr('\.(?:bat|com|html)$') ] );
  return unless %$pods;  # nothing to do

  unless ( -d $htmldir ) {
    File::Path::mkpath($htmldir, 0, oct(755))
      or die "Couldn't mkdir $htmldir: $!";
  }

  my @rootdirs = ($type eq 'bin') ? qw(bin) :
      $self->installdirs eq 'core' ? qw(lib) : qw(site lib);
  my $podroot = $ENV{PERL_CORE}
              ? File::Basename::dirname($ENV{PERL_CORE})
              : $self->original_prefix('core');

  my $htmlroot = $self->install_sets('core')->{libhtml};
  my $podpath;
  unless (defined $self->args('html_links') and !$self->args('html_links')) {
    my @podpath = ( (map { File::Spec->abs2rel($_ ,$podroot) } grep { -d  }
                     ( $self->install_sets('core', 'lib'), # lib
                       $self->install_sets('core', 'bin'), # bin
                       $self->install_sets('site', 'lib'), # site/lib
                     ) ), File::Spec->rel2abs($self->blib) );

    $podpath = $ENV{PERL_CORE}
      ? File::Spec->catdir($podroot, 'lib')
        : join(":", map { tr,:\\,|/,; $_ } @podpath);
  }

  my $blibdir = join('/', File::Spec->splitdir(
    (File::Spec->splitpath(File::Spec->rel2abs($htmldir),1))[1]),''
  );

  my ($with_ActiveState, $htmltool);

  if ( $with_ActiveState = $self->_is_ActivePerl
    && eval { require ActivePerl::DocTools::Pod; 1 }
  ) {
    my $tool_v = ActiveState::DocTools::Pod->VERSION;
    $htmltool = "ActiveState::DocTools::Pod";
    $htmltool .= " $tool_v" if $tool_v && length $tool_v;
  }
  else {
      require Module::Build::PodParser;
      require Pod::Html;
    $htmltool = "Pod::Html " .  Pod::Html->VERSION;
  }
  $self->log_verbose("Converting Pod to HTML with $htmltool\n");

  my $errors = 0;

  POD:
  foreach my $pod ( sort keys %$pods ) {

    my ($name, $path) = File::Basename::fileparse($pods->{$pod},
      $self->file_qr('\.(?:pm|plx?|pod)$')
    );
    my @dirs = File::Spec->splitdir( File::Spec->canonpath( $path ) );
    pop( @dirs ) if scalar(@dirs) && $dirs[-1] eq File::Spec->curdir;

    my $fulldir = File::Spec->catdir($htmldir, @rootdirs, @dirs);
    my $tmpfile = File::Spec->catfile($fulldir, "${name}.tmp");
    my $outfile = File::Spec->catfile($fulldir, "${name}.html");
    my $infile  = File::Spec->abs2rel($pod);

    next if $self->up_to_date($infile, $outfile);

    unless ( -d $fulldir ){
      File::Path::mkpath($fulldir, 0, oct(755))
        or die "Couldn't mkdir $fulldir: $!";
    }

    $self->log_verbose("HTMLifying $infile -> $outfile\n");
    if ( $with_ActiveState ) {
      my $depth = @rootdirs + @dirs;
      my %opts = ( infile => $infile,
        outfile => $tmpfile,
        ( defined($podpath) ? (podpath => $podpath) : ()),
        podroot => $podroot,
        index => 1,
        depth => $depth,
      );
      eval {
        ActivePerl::DocTools::Pod::pod2html(map { ($_, $opts{$_}) } sort keys %opts);
        1;
      } or $self->log_warn("[$htmltool] pod2html (" .
        join(", ", map { "q{$_} => q{$opts{$_}}" } (sort keys %opts)) . ") failed: $@");
    } else {
      my $path2root = File::Spec->catdir((File::Spec->updir) x @dirs);
      open(my $fh, '<', $infile) or die "Can't read $infile: $!";
      my $abstract = Module::Build::PodParser->new(fh => $fh)->get_abstract();

      my $title = join( '::', (@dirs, $name) );
      $title .= " - $abstract" if $abstract;

      my @opts = (
        "--title=$title",
        ( defined($podpath) ? "--podpath=$podpath" : ()),
        "--infile=$infile",
        "--outfile=$tmpfile",
        "--podroot=$podroot",
        ($path2root ? "--htmlroot=$path2root" : ()),
      );

      unless ( eval{Pod::Html->VERSION(1.12)} ) {
        push( @opts, ('--flush') ); # caching removed in 1.12
      }

      if ( eval{Pod::Html->VERSION(1.12)} ) {
        push( @opts, ('--header', '--backlink') );
      } elsif ( eval{Pod::Html->VERSION(1.03)} ) {
        push( @opts, ('--header', '--backlink=Back to Top') );
      }

      $self->log_verbose("P::H::pod2html @opts\n");
      {
        my $orig = Cwd::getcwd();
        eval { Pod::Html::pod2html(@opts); 1 }
          or $self->log_warn("[$htmltool] pod2html( " .
          join(", ", map { "q{$_}" } @opts) . ") failed: $@");
        chdir($orig);
      }
    }
    # We now have to cleanup the resulting html file
    if ( ! -r $tmpfile ) {
      $errors++;
      next POD;
    }
    open(my $fh, '<', $tmpfile) or die "Can't read $tmpfile: $!";
    my $html = join('',<$fh>);
    close $fh;
    if (!$self->_is_ActivePerl) {
      # These fixups are already done by AP::DT:P:pod2html
      # The output from pod2html is NOT XHTML!
      # IE6+ will display content that is not valid for DOCTYPE
      $html =~ s#^<!DOCTYPE .*?>#<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">#im;
      $html =~ s#<html xmlns="http://www.w3.org/1999/xhtml">#<html>#i;

      # IE6+ will not display local HTML files with strict
      # security without this comment
      $html =~ s#<head>#<head>\n<!-- saved from url=(0017)http://localhost/ -->#i;
    }
    # Fixup links that point to our temp blib
    $html =~ s/\Q$blibdir\E//g;

    open($fh, '>', $outfile) or die "Can't write $outfile: $!";
    print $fh $html;
    close $fh;
    unlink($tmpfile);
  }

  return ! $errors;

}

# Adapted from ExtUtils::MM_Unix
sub man1page_name {
  my $self = shift;
  return File::Basename::basename( shift );
}

# Adapted from ExtUtils::MM_Unix and Pod::Man
# Depending on M::B's dependency policy, it might make more sense to refactor
# Pod::Man::begin_pod() to extract a name() methods, and use them...
#    -spurkis
sub man3page_name {
  my $self = shift;
  my ($vol, $dirs, $file) = File::Spec->splitpath( shift );
  my @dirs = File::Spec->splitdir( File::Spec->canonpath($dirs) );

  # Remove known exts from the base name
  $file =~ s/\.p(?:od|m|l)\z//i;

  return join( $self->manpage_separator, @dirs, $file );
}

sub manpage_separator {
  return '::';
}

# For systems that don't have 'diff' executable, should use Algorithm::Diff
sub ACTION_diff {
  my $self = shift;
  $self->depends_on('build');
  my $local_lib = File::Spec->rel2abs('lib');
  my @myINC = grep {$_ ne $local_lib} @INC;

  # The actual install destination might not be in @INC, so check there too.
  push @myINC, map $self->install_destination($_), qw(lib arch);

  my @flags = @{$self->{args}{ARGV}};
  @flags = $self->split_like_shell($self->{args}{flags} || '') unless @flags;

  my $installmap = $self->install_map;
  delete $installmap->{read};
  delete $installmap->{write};

  my $text_suffix = $self->file_qr('\.(pm|pod)$');

  foreach my $localdir (sort keys %$installmap) {
    my @localparts = File::Spec->splitdir($localdir);
    my $files = $self->rscan_dir($localdir, sub {-f});

    foreach my $file (@$files) {
      my @parts = File::Spec->splitdir($file);
      @parts = @parts[@localparts .. $#parts]; # Get rid of blib/lib or similar

local/lib/perl5/Module/Build/Base.pm  view on Meta::CPAN

  my ($self) = @_;

  my $p = $self->{properties};
  return $p->{_have_c_compiler} if defined $p->{_have_c_compiler};

  $self->log_verbose("Checking if compiler tools configured... ");
  my $b = $self->cbuilder;
  my $have = $b && eval { $b->have_compiler };
  $self->log_verbose($have ? "ok.\n" : "failed.\n");
  return $p->{_have_c_compiler} = $have;
}

sub compile_c {
  my ($self, $file, %args) = @_;

  if ( ! $self->have_c_compiler ) {
    die "Error: no compiler detected to compile '$file'.  Aborting\n";
  }

  my $b = $self->cbuilder;
  my $obj_file = $b->object_file($file);
  $self->add_to_cleanup($obj_file);
  return $obj_file if $self->up_to_date($file, $obj_file);

  $b->compile(source => $file,
              defines => $args{defines},
              object_file => $obj_file,
              include_dirs => $self->include_dirs,
              extra_compiler_flags => $self->extra_compiler_flags,
             );

  return $obj_file;
}

sub link_c {
  my ($self, $spec) = @_;
  my $p = $self->{properties}; # For convenience

  $self->add_to_cleanup($spec->{lib_file});

  my $objects = $p->{objects} || [];

  return $spec->{lib_file}
    if $self->up_to_date([$spec->{obj_file}, @$objects],
                         $spec->{lib_file});

  my $module_name = $spec->{module_name} || $self->module_name;

  $self->cbuilder->link(
    module_name => $module_name,
    objects     => [$spec->{obj_file}, @$objects],
    lib_file    => $spec->{lib_file},
    extra_linker_flags => $self->extra_linker_flags );

  return $spec->{lib_file};
}

sub compile_xs {
  my ($self, $file, %args) = @_;

  $self->log_verbose("$file -> $args{outfile}\n");

  if (eval {require ExtUtils::ParseXS; 1}) {

    ExtUtils::ParseXS::process_file(
                                    filename => $file,
                                    prototypes => 0,
                                    output => $args{outfile},
                                   );
  } else {
    # Ok, I give up.  Just use backticks.

    my $xsubpp = Module::Metadata->find_module_by_name('ExtUtils::xsubpp')
      or die "Can't find ExtUtils::xsubpp in INC (@INC)";

    my @typemaps;
    push @typemaps, Module::Metadata->find_module_by_name(
        'ExtUtils::typemap', \@INC
    );
    my $lib_typemap = Module::Metadata->find_module_by_name(
        'typemap', [File::Basename::dirname($file), File::Spec->rel2abs('.')]
    );
    push @typemaps, $lib_typemap if $lib_typemap;
    @typemaps = map {+'-typemap', $_} @typemaps;

    my $cf = $self->{config};
    my $perl = $self->{properties}{perl};

    my @command = ($perl, "-I".$cf->get('installarchlib'), "-I".$cf->get('installprivlib'), $xsubpp, '-noprototypes',
                   @typemaps, $file);

    $self->log_info("@command\n");
    open(my $fh, '>', $args{outfile}) or die "Couldn't write $args{outfile}: $!";
    print {$fh} $self->_backticks(@command);
    close $fh;
  }
}

sub split_like_shell {
  my ($self, $string) = @_;

  return () unless defined($string);
  return @$string if ref $string eq 'ARRAY';
  $string =~ s/^\s+|\s+$//g;
  return () unless length($string);

  return Text::ParseWords::shellwords($string);
}

sub oneliner {
  # Returns a string that the shell can evaluate as a perl command.
  # This should be avoided whenever possible, since "the shell" really
  # means zillions of shells on zillions of platforms and it's really
  # hard to get it right all the time.

  # Some of this code is stolen with permission from ExtUtils::MakeMaker.

  my($self, $cmd, $switches, $args) = @_;
  $switches = [] unless defined $switches;
  $args = [] unless defined $args;

  # Strip leading and trailing newlines
  $cmd =~ s{^\n+}{};
  $cmd =~ s{\n+$}{};

  my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter;
  return $self->_quote_args($perl, @$switches, '-e', $cmd, @$args);
}

sub run_perl_script {
  my ($self, $script, $preargs, $postargs) = @_;
  foreach ($preargs, $postargs) {
    $_ = [ $self->split_like_shell($_) ] unless ref();
  }
  return $self->run_perl_command([@$preargs, $script, @$postargs]);
}

sub run_perl_command {
  # XXX Maybe we should accept @args instead of $args?  Must resolve
  # this before documenting.
  my ($self, $args) = @_;
  $args = [ $self->split_like_shell($args) ] unless ref($args);
  my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter;

  # Make sure our local additions to @INC are propagated to the subprocess
  local $ENV{PERL5LIB} = join $self->config('path_sep'), $self->_added_to_INC;

  return $self->do_system($perl, @$args);
}

# Infer various data from the path of the input filename
# that is needed to create output files.
# The input filename is expected to be of the form:
#   lib/Module/Name.ext or Module/Name.ext
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;

  $spec{base_name} = $file_base;

  $spec{src_dir} = File::Spec->catpath( $v, $d, '' );

  # the module name
  shift( @d ) while @d && ($d[0] eq 'lib' || $d[0] eq '');
  pop( @d ) while @d && $d[-1] eq '';
  $spec{module_name} = join( '::', (@d, $file_base) );

  $spec{archdir} = File::Spec->catdir($self->blib, 'arch', 'auto',
                                      @d, $file_base);

  $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') );

  require DynaLoader;
  my $modfname = defined &DynaLoader::mod2fname ? DynaLoader::mod2fname([@d, $file_base]) : $file_base;

  $spec{bs_file} = File::Spec->catfile($spec{archdir}, "$modfname.bs");

  $spec{lib_file} = File::Spec->catfile($spec{archdir}, "$modfname.".$cf->get('dlext'));

  return \%spec;
}

sub process_xs {
  my ($self, $file) = @_;

  my $spec = $self->_infer_xs_spec($file);

  # File name, minus the suffix
  (my $file_base = $file) =~ s/\.[^.]+$//;

  # .xs -> .c
  $self->add_to_cleanup($spec->{c_file});

  unless ($self->up_to_date($file, $spec->{c_file})) {
    $self->compile_xs($file, outfile => $spec->{c_file});
  }

  # .c -> .o
  my $v = $self->dist_version;
  $self->compile_c($spec->{c_file},
                   defines => {VERSION => qq{"$v"}, XS_VERSION => qq{"$v"}});

  # archdir
  File::Path::mkpath($spec->{archdir}, 0, oct(777)) unless -d $spec->{archdir};

  # .xs -> .bs
  $self->add_to_cleanup($spec->{bs_file});
  unless ($self->up_to_date($file, $spec->{bs_file})) {
    require ExtUtils::Mkbootstrap;
    $self->log_info("ExtUtils::Mkbootstrap::Mkbootstrap('$spec->{bs_file}')\n");
    ExtUtils::Mkbootstrap::Mkbootstrap($spec->{bs_file});  # Original had $BSLOADLIBS - what's that?
    open(my $fh, '>>', $spec->{bs_file});  # create
    utime((time)x2, $spec->{bs_file});  # touch
  }

  # .o -> .(a|bundle)
  $self->link_c($spec);
}

sub do_system {
  my ($self, @cmd) = @_;
  $self->log_verbose("@cmd\n");

  # Some systems proliferate huge PERL5LIBs, try to ameliorate:
  my %seen;
  my $sep = $self->config('path_sep');
  local $ENV{PERL5LIB} =
    ( !exists($ENV{PERL5LIB}) ? '' :
      length($ENV{PERL5LIB}) < 500
      ? $ENV{PERL5LIB}
      : join $sep, grep { ! $seen{$_}++ and -d $_ } split($sep, $ENV{PERL5LIB})
    );

  my $status = system(@cmd);
  if ($status and $! =~ /Argument list too long/i) {
    my $env_entries = '';
    foreach (sort keys %ENV) { $env_entries .= "$_=>".length($ENV{$_})."; " }
    warn "'Argument list' was 'too long', env lengths are $env_entries";
  }
  return !$status;
}

sub copy_if_modified {
  my $self = shift;
  my %args = (@_ > 3
              ? ( @_ )
              : ( from => shift, to_dir => shift, flatten => shift )
             );
  $args{verbose} = !$self->quiet
    unless exists $args{verbose};

  my $file = $args{from};
  unless (defined $file and length $file) {
    die "No 'from' parameter given to copy_if_modified";
  }



( run in 0.674 second using v1.01-cache-2.11-cpan-99c4e6809bf )