App-Build

 view release on metacpan or  search on metacpan

lib/App/Build.pm  view on Meta::CPAN

The following are additional standards of all App::Build
installations.

 * TBD

=head1 App::Build CONFIGURABILITY

Since App::Build uses App::Options, App::Options makes all the
of the --var=value options available via the global %App::options hash.
App::Build however does not remove the --var=value options from @ARGV.

This will be put to good use sometime in the future.

=head1 FIX-UPS

Module::Build complains if the PREFIX environment variable is
set.  App::Build doesn't.  It just ignores it.

The CPAN shell (for some reason I don't understand) runs Build.PL
as "perl Build.PL Build" and this fails.
App::Build just throws away the "Build" so that the default "build"
action is invoked.

Module::Build deprecated the PREFIX option to Makefile.PL
(i.e. "perl Makefile.PL PREFIX=/usr/foo").  App::Build just makes
the PREFIX option a synonym for "install_base", which does
essentially the same thing.

=cut

delete $ENV{PREFIX};   # Module::Build protests if this var is set

# Enable the continued use of the PREFIX=$PREFIX option
# (from Makefile.PL and ExtUtils::MakeMaker) by making it
# an alias for the "install_base" option of Module::Build.

######################################################################
# BUILD: enhancements to "perl Build.PL"
######################################################################

=head1 METHODS

The documentation of the methods below is not for users of the
App::Build module (who are writing Build.PL scripts), but for people
interested in the internals of how App::Build extends Module::Build.

It is also so that I can remember what I was doing so that if the
internals of Module::Build change, I can maintain this code.

=head2 new()

We override the new() method in order to enhance the install paths.

In the future, we may also download and unpack external perl 
distributions.

=cut

sub new {
    my ($class, %args) = @_;
    my $obj = $class->SUPER::new(%args);

    $obj->_enhance_install_paths() if $obj->_prefix;
    $obj->_get_supporting_software();

    return($obj);
}

=head2 read_config()

Overridden to transparently call C<_enhance_install_paths()>.

=cut

sub read_config {
    my ($self) = @_;

    $self->SUPER::read_config();
    $self->_enhance_install_paths() if $self->_prefix;
}

=head2 install_base()

Overridden to transparently call C<_enhance_install_paths()>.

=cut

sub install_base {
    my ($self, @args) = @_;

    my $ret = $self->SUPER::install_base(@args);
    $self->_enhance_install_paths() if $self->_prefix;

    return $ret;
}

=head2 _get_supporting_software()

Downloads supporting software (if necessary), unpacks it, compiles it,
and installs it.

=cut

sub _get_supporting_software {
    my ($self) = @_;

    my $tag = $self->_app_tag();

    my $url  = $App::options{"$tag.url"};   # check to see if there was software to download
    if ($url) {
        my $file = $App::options{"$tag.file"};
        if (!$file) {
            $file = $url;
            $file =~ s!.*/!!;
        }
        ($file) || die "File [$tag.file] does not exist";

        my $subdir = $App::options{"$tag.subdir"};
        if (!$subdir) {
            $subdir = $file;
            $subdir =~ s!\.tar.gz$!!;
            $subdir =~ s!\.tgz$!!;
        }
        ($subdir) || die "Subdir [$tag.subdir] does not exist";

        my $archive_dir = $App::options{archive_dir} || "archive";
        mkdir($archive_dir) if (! -d $archive_dir);

        my $archive = "$archive_dir/$file";

        (-d $archive_dir) || die "Archive Directory [$archive_dir] does not exist";
        (-w $archive_dir) || die "Archive Directory [$archive_dir] not writeable";

        $self->mirror($url, $archive);
        $self->unpack($archive, "unpack", $subdir);
    }
}

=head2 _app_tag()

This lowercase-ifies the dist_name, removes "app-build-" from the front,
and returns it as the "application tag".
Therefore, a distribution called "App-Build-Kwiki" would have an
"app_tag" of "kwiki".  An "app_tag" is used for looking up configuration
settings in the %App::options hash produced by App::Options.

=cut

sub _app_tag {
    my ($self) = @_;
    my $dist_name = $self->dist_name();

lib/App/Build.pm  view on Meta::CPAN


or (synonymously) ...

   perl Build.PL PREFIX=/usr/mycompany/prod

If the install_base was not supplied, the "prefix" out of perl's own
Config.pm is returned.  So if perl is installed in "/usr/local/bin", then
"/usr/local" is returned.
If perl is installed in "/usr/bin", then "/usr" is returned.

=cut

sub _prefix {
    my ($self) = @_;
    my $prefix = $self->{properties}{install_base} || $self->{config}{prefix};
    return($prefix);
}

=head2 _enhance_install_paths()

The install_sets (core, site, vendor) as set from values in perl's own
Config.pm are enhanced to include the absolute directories in which
the extra_dirs will be installed.

=cut

sub _enhance_install_paths {
    my ($self) = @_;
    my $properties = $self->{properties};
    my $install_sets = $properties->{install_sets};
    my @extra_dirs = $self->_get_extra_dirs();
    my $prefix = $self->_prefix();
    my $tag = $self->_app_tag();
    my ($path);
    foreach my $dir (@extra_dirs) {
        $path = $App::options{"$tag.$dir.dir"} || File::Spec->catdir($prefix, $dir);
        $install_sets->{core}{$dir}   = $path;
        $install_sets->{site}{$dir}   = $path;
        $install_sets->{vendor}{$dir} = $path;
    }
}

######################################################################
# BUILD: enhancements to "./Build"
######################################################################

=head2 ACTION_code()

We override ACTION_code() to copy additional directories of files
needed to install the application.

When you invoke "./Build", the method $self->ACTION_build() gets
called on this object.  This, in turn, calls $self->ACTION_code()
and $self->ACTION_docs().  Each of these methods copies files into
the "blib" subdirectory in preparation for installation.

=cut

sub ACTION_code {
    my ($self) = @_;
    $self->SUPER::ACTION_code(); # call this first (creates "blib" dir if necessary)
    $self->process_app_files();  # NEW. call this to copy "extra_dirs" to "blib"
}

=head2 _added_to_INC()

We override this method to ensure that "lib" (libraries to be installed)
is added to the front of @INC.
This is because we often want to use the (latest) enclosed module as
the installing module, even if it has already been installed.

=cut

sub _added_to_INC {
  my $self = shift;
  my %seen;
  $seen{$_}++ foreach $self->_default_INC;
  unshift(@INC,"lib");
  return grep !$seen{$_}++, @INC;
}

=head2 _get_extra_dirs()

Gets the list of extra_dirs to be installed.

The extra_dirs may be specified in the Build.PL in
a variety of ways.
It can be a scalar (comma-separated list of directories),
an array ref of directories, or a hash ref where the
keys are the directories.

If extra_dirs is specified with a hash ref, the hash values
are hashrefs of attributes. i.e.

   extra_dirs => {
       var => {
           dest_dir => "var",
       },
       htdocs => {
           dest_dir => "htdocs",
       },
       "cgi-bin" => {  # any dir ending in "bin" contains executable scripts
           dest_dir => "cgi-bin",
       },
       support => {
           dest_dir => "support",
           executable => 1,  # treat contents as executable scripts
       },
   },

So far, only the "dest_dir" attribute is defined.  The "dest_dir" attribute
can be overridden using the "--install_path" parameter.

=cut

sub _get_extra_dirs {
    my ($self) = @_;
    my $properties = $self->{properties};
    my @extra_dirs = ();
    if ($properties->{extra_dirs}) {
        if (ref($properties->{extra_dirs}) eq "ARRAY") {

lib/App/Build.pm  view on Meta::CPAN

    my $extra_dirs = $self->_get_extra_dirs_attributes();

    my $blib = $self->blib;
    my ($contains_executables, $result, $target_file);
    foreach my $dir (@extra_dirs) {
        if (-d $dir) {
            $contains_executables = $extra_dirs->{$dir}{executable};
            $contains_executables = ($dir =~ /bin$/) ? 1 : 0 if (!defined $contains_executables);
            $path = File::Spec->catfile($blib, $dir), 
            File::Path::mkpath($path);
            $files = $self->_find_all_files($dir);
            my ($should_be_executable);
            while (my ($file, $dest) = each %$files) {
                $target_file = File::Spec->catfile($blib, $dest);
                $result = $self->copy_if_modified(from => $file, to => $target_file) || "";
                if ($result && $contains_executables) {
                    $self->fix_shebang_line($result);
                    $self->make_executable($result)
                      if $self->_should_be_executable($result);
                }
            }
        }
    }
}

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

    # copied from Module::Build::Base::fix_shebang_line
    my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!";
    local $/ = "\n";
    chomp(my $line = <$FIXIN>);
    if ($line =~ /^\s*\#!\s*/) {
        return 1;
    } else {
        return 0;
    }
}

=head2 _find_all_files()

This is used by process_app_files() to get the list of files under "extra_dirs"
to copy to "blib".

=cut

sub _find_all_files {
    my ($self, $dir) = @_;
    return {} unless -d $dir;
    return { map { $_, $_ } @{ $self->rscan_dir($dir, sub { -f $_ }) } };
}

=head2 rscan_dir()

Don't include CVS, RCS, and SVN (*/.svn/*) files.

=cut

sub rscan_dir {
    my ($self, $dir, $pattern) = @_;
    my $files = $self->SUPER::rscan_dir($dir, $pattern);
    my @files = grep(!/[\/\\](CVS|RCS|\.svn)[\/\\]/, @$files);
    return \@files;
}

######################################################################
# INSTALL: enhancements to "./Build install"
######################################################################

=head2 packlist()

This creates the name of the "packlist" file that needs to be
written with the list of all of the files that get installed.

=cut

sub packlist {
    my ($self) = @_;
    # Write the packlist into the same place as ExtUtils::MakeMaker.
    my $archdir = $self->install_destination('arch');
    my @ext = $self->module_name ? split /::/, $self->module_name :
                                   $self->dist_name;
    my $packlist = File::Spec->catfile($archdir, 'auto', @ext, '.packlist');
    return($packlist);
}

=head2 install_map()

This method is only overridden in order to put in the fix so
that it creates a .packlist based on dist_name if the module_name
is not specified.

=cut

sub install_map {
  my ($self, $blib) = @_;
  $blib ||= $self->blib;

  my %map;
  foreach my $type ($self->install_types) {
    my $localdir = File::Spec->catdir( $blib, $type );
    next unless -e $localdir;

    if (my $dest = $self->install_destination($type)) {
      # thins alters the behavious of Module::Build, and
      # looks into the implementation
      if (   $self->install_path($type)
          && !File::Spec->file_name_is_absolute($dest)) {
        $dest = File::Spec->catdir( $self->_prefix, $dest );
      }
      $map{$localdir} = $dest;
    } else {
      # Platforms like Win32, MacOS, etc. may not build man pages
      die "Can't figure out where to install things of type '$type'"
        unless $type =~ /^(lib|bin)doc$/;
    }
  }

  my $extra_dirs_attrs = $self->_get_extra_dirs_attributes();
  foreach my $dir ( $self->_get_extra_dirs() ) {
    my $dest = $extra_dirs_attrs->{$dir}{dest_dir};



( run in 0.736 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )