Perl Module Resource Files

473 Views Asked by At

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).

2

There are 2 best solutions below

0
On BEST ANSWER

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.)

3
On

%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';