You probably want to use
Module::Build. With it you can easily collect path names during initial unpacking, then install to them during install. See
Gantry or
Bigtop for examples. Here is a minimal example of a Build.PL:
use strict;
use Module::Build;
use File::Find;
my $subclass = Module::Build->subclass(
class => 'My::Builder',
code => &_custom_code(),
);
# collect web files
my( %web_dirs, @web_dirs );
find( \&wanted, 'webstuff' );
sub wanted {
my $dir = $File::Find::dir;
$dir =~ s![^/]*/!!;
next if $dir =~ /\.svn/;
++$web_dirs{ $dir };
}
my @web_dirs = keys %web_dirs;
my $build = $subclass->new(
web_files => \@web_dirs,
build_web_dir => 'webstuff',
# Put your web content in subdirectories of webstuff.
#...Normal Module::Build constructor params here.
);
print "\n\nApp comes with a set of web stuff...\n"
. "A typical location for this\n"
. "stuff is your web server document root.\n\n";
my $web_path = $build->prompt(
'Path for web stuff',
'/var/www',
);
$build->notes( install_web_dir => $web_path );
# check to see if dir exists, use and other prompt
# to offer to make it if it doesn't
$build->create_build_script;
sub _custom_code {
return( q{
sub ACTION_code {
my $self = shift;
$self->SUPER::ACTION_code();
$self->add_build_element( 'web' );
$self->process_web_files( 'web' );
}
sub ACTION_install {
my $self = shift;
my $p = $self->{properties};
$self->SUPER::ACTION_install();
my $dir = $self->notes( 'install_web_dire' );
my $blib_dir = File::Spec->catdir(
$self->blib, 'web', $p->{build_web_directory}
);
my $num;
eval {
require File::Copy::Recursive;
import File::Copy::Recursive 'dircopy';
$num = dircopy($blib_dir, $dir);
};
if ( $@ ) {
print "\nError coping templates:\n";
print $@ . "\n";
}
else {
print "\n$num things copied to $dir\n";
}
}
sub process_web_files {
my $self = shift;
my $files = $self->find_web_files;
return unless @$files;
my $dir = File::Spec->catdir($self->blib, 'web');
File::Path::mkpath( $dir );
foreach my $file (@$files) {
my $result = $self->copy_if_modified(
$file, $dir
) or next;
}
}
sub find_web_files {
my $self = shift;
my $p = $self->{properties};
my $b_tmpl_dir = $p->{build_web_directory};
$b_tmpl_dir =~ s/\/$//g;
if (my $files = $p->{web_files}) {
if ( UNIVERSAL::isa($files, 'HASH') ) {
my @files = [keys %$files];
return( \@files );
}
my @files;
foreach my $glob ( @$files ) {
$glob = "$b_tmpl_dir/$glob";
push( @files, glob( $glob ) );
}
return( \@files );
return( [
map $self->localize_file_path($_),
@files
] );
return( \@localized );
}
}
sub web_files {
my $self = shift;
for ($self->{properties}{web_files}) {
$_ = shift if @_;
return unless $_;
# Always coerce into a hash
return $_ if UNIVERSAL::isa($_, 'HASH');
return $_ = {$_ => 1} unless ref();
return { map {$_,1} @$_ };
}
}
} ); # end return
} # end _custom_code
Disclaimer: I excerpted the above from Gantry's Build.PL to give you a feel for how things look. But, I didn't test the above so it probably doesn't complile. See Gantry for the example. Bigtop actually generates Build.PL's based on Gantry::Build which facilitates doing this, if you only need to install subdirectories to one top level path. You probably want to invest in an actual module for the Module::Build subclass.
Phil