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).
-
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 Answers
%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';

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

- 13,478
- 1
- 23
- 35