0

Is there a way to easily package resource files with a Perl module? Right now, I'm using %INC to find the location of the module then loading my resource files, but I'm looking for a solution where Perl will automatically reference the correct path (similar to how Java's class resources work).

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
SArcher
  • 264
  • 1
  • 9
  • I don't have time for an answer, but you might want to look into `__DATA__` sections, the `FindBin` module, distribution creation tools like `Dist::Zilla`, and archive packers like `PAR` (which in Java-speak creates a JAR with a JVM inside). You can also search CPAN to see how existing modules tackle this problem. – amon Jan 01 '14 at 00:53

2 Answers2

2

%INC approach is actually pretty good.

If you want it generic, you can wrap it up in a little module and use caller(0) for getting the parent module (caller(0) will return an array whose second element will be the same as %INC value for your module)

Here's my sample code (I tested it but won't include full test code for brevity):

package ModulePath;
# This module can be used for getting resource files
# In the same directory as a Perl module
use File::Basename;
use File::Spec;

sub path {
    my @c=caller(0);
    return dirname($c[1]);
}   

sub default_resource {
    my $resource_suffix = shift || "txt";
    my @c=caller(0);
    my @suffixes = ("pm");
    my ($name,$path,$suffix) = fileparse($c[1], @suffixes);
    my $file = File::Spec->catfile(dirname($c[1]), "$name$resource_suffix");
    return $file;
}

1;

And here's the SYNOPSIS (from a librery called "p/a.pm" I just wrote and tested)

# Get directory, supply resource file name
my $path = ModulePath::path();
my $file = File::Spec->catfile($path,"b.txt"); 

# Get default resource (module name with ".txt" suffix)
my $file2 = ModulePath::default_resource();

# Get resource with default name (same as module) but non-default suffix
my $file3 = ModulePath::default_resource("dat");

Test results (abriged):

$VAR2 = 'C:\\_Code\\so\\20864526\\p\\b.txt';
$VAR1 = 'C:\\_Code\\so\\20864526\\p\\a.txt';
$VAR1 = 'C:\\_Code\\so\\20864526\\p\\a.dat';
DVK
  • 126,886
  • 32
  • 213
  • 327
  • Note - there may be a CPAN module to do this, but "more than one way..."... and it was fun to slap this together – DVK Jan 01 '14 at 02:09
  • Thanks. I like this, but I'd prefer to use a public module so I don't have maintain the code. – SArcher Jan 17 '14 at 23:47
  • @DByrne - so wrap this into a module and post on CPAN :) – DVK Jan 18 '14 at 01:06
0

File::ShareDir for loading resources at run-time.

File::ShareDir::Install orModule::Install::Share or Dist::Zilla::Plugin::ModuleShareDirs or Dist::Zilla::Plugin::ShareDir for handling the install-time copying of files.

(You may be wondering about why Dist::Zilla includes two plugins for doing this sort of thing. Reading the File::ShareDir documentation should make it clear - File::ShareDir allows you to install resource files in two different locations - one which is grouped by module name (e.g. Foo::Bar), and one which is grouped by distribution name (e.g. Foo-Bar). When you're creating distributions with more than one module, this is an important distinction.)

tobyink
  • 13,478
  • 1
  • 23
  • 35