Starting to use File::ShareDir

File::ShareDir is a module to allow you to fetch files that were copied during install-time of your distribution/module. Things like templates, images, XMLs or any other data that you need falls under the category of things you might want to have installed.

The installation itself is done by the module distribution toolchain (initially implemented in Module::Install but now available on all, including Dist::Zilla). You can read on how to add a share files in a directory on the respected documentation of you toolchain selection (or Dist::Zilla).

To reach the files after they were installed you need to use File::ShareDir. It has a few functions that fetch files or directories by module or distribution. It's comfortable, it's easy, it's simple.

However, I was reluctant to use it since I've heard about it mainly since I don't know what to do if I want to use the data files without actually installing the module each time.

Today, I finally understood it (after digging in the docs, the bug list, AnnoCPAN and the raw code). Yes, I had to go through these steps to find out. Apparently it's not documented, nor was the ticket of its documentation request (which doesn't include enough information anyway) wasn't handled yet.

The trick is, File::ShareDir uses @INC as well, in order to find your data files. This means that if you run your toolchain (perl Makefile.PL && make; or perl Build.PL && ./Build;), then you will be able to use the blib/lib folder:

perl -Iblib/lib bin/your_app

(or however you run your stuff)

If you're using Dist::Zilla, you can run dzil build, and grab the Makefile.PL or Build.PL from there and run them.

5 Comments

I've also used File::ShareDir but always ran into the problem where it seems to only work after the module is installed, which makes it not very useful for development. I never thought of the build trick, I'll have to give that a go.

What I usually do is saying something like "get from File::ShareDir, or if in Author mode (which I figure out using various ugly methods involving looking for certain types of files on the filesystem) I'll get a root directory with Findlib. I've also seem people use Class::Inspector for this.

Another way (from some point of view better):

perl -Mblib bin/your_app

Hi Folks

Here's what I do (in a Moose-based class) to set the attribute config_file_path:

sub BUILD
{
my($self) = @_;
my($name) = '.htoffice.cms.conf';

my($path);

for (keys %INC)
{
next if ($_ !~ m|App/Office/CMS/Util/Config.pm|);
($path = $INC{$_}) =~ s|Util/Config.pm|$name|;
}

$self -> config_file_path($path);

# Check [global].

$self -> config(Config::Tiny -> read($path) );

etc
} # End of Build.

Then before installation you tell you app to look in the dev dir, and after installation you don't have to tell it anything.

If you're running Dist::Zilla, you can use "dzil run". So I'm doing this:


dzil run 'twiggy bin/myapp'


You don't even need to add the -Iblib/lib, that is already set up via environment vars. Including the things needed for File::ShareDir, specifically.

The right thing to do here is use Test::File::ShareDir from your tests, which does the right thing with your @INC so the local share directory can be found:

```
use Test::File::ShareDir -share => { -dist => { 'My-Dist-Name' => 'share' } };
```

Leave a comment

About Sawyer X

user-pic Gots to do the bloggingz