In Making modules: the configuration and structureยง

See primary documentation in context for The %?RESOURCES variable.

Note the example here is returning a Distribution::Resource object. It should not be considered as a path to an object in the filesystem.

my $template-text = %?RESOURCES<templates/default-template.mustache>.slurp;

Note: Accessing these files via %?RESOURCES is not getting their installed locations or an IO class: You are accessing a Distribution::Resource. object indexed on the name provided. It's important to be careful in how you use these to avoid embedding the filename at compile-time which might be different than the location the file is in at runtime.

The L<$?RESOURCES|syntax/$?RESOURCES> variable is only populated within files listed in the provides section (usually those in the lib directory). If you want to use it outside that (i.e. in your tests), you'll need to provide a Routine that returns it.

An example of how to use this might be:

sub     MyModule-resources(*@resources) is export(:tests) {
        for @resources -> $resource-filename {
                my $resource = %?RESOURCES{$resource-filename};
                # Just some error-checking code
                if $resource !~~ Distribution::Resource {
                        note "Could not find resource '$resource-filename' in distribution";
                        say qx{ls -laF ; ls -laF resources ; cat META6.json};
                        say "Resource is: " ~ $resource.raku;
                        say "Resource keys are: " ~ %?RESOURCES.keys.raku;
                }
        }

        return %?RESOURCES;
}

...and then to use it in your code:

use     TOP :tests :DEFAULT;    # Note that the :tests here matches the "is export" above

my $resource-name = 'templates/default-template.mustache';
my $resources = MyModule-resources($resource-name);
my $resource = $resources{$resource-name};
my $file_handle = $resource.open();

The above will produce quite a bit of debugging output if the resource isn't found (but will continue regardless). This can be handy when running in a remote location, such as a GitHub action.

In Variablesยง

See primary documentation in context for %?RESOURCES.

%?RESOURCES is a compile-time variable available to the code of a Distribution.

It contains a hash that provides compile and runtime access to files associated with the Distribution of the current compilation unit. This hash is used to access a special storage for Distribution-wide static files (such as examples of configuration files, templates or data files).

Files available via this variable need to be placed under the Distribution's resources directory:

Module-Foo/
โ”œโ”€โ”€ lib
โ”‚   โ””โ”€โ”€ Module
โ”‚       โ””โ”€โ”€ Foo.rakumod
โ”œโ”€โ”€ META6.json
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ resources
    โ””โ”€โ”€ images
        โ””โ”€โ”€ foo.jpg

Additionally, a relative path (starting from the root resources directory of a distribution) to a file may be specified under the "resources" field in the META6.json file:

"resources": [
    "images/foo.jpg"
]

Every resource file is added to an installed Distribution and is accessible using a Hash-like access to %?RESOURCES, returning a Distribution::Resource object:

my $foo-IO = %?RESOURCES<images/foo.jpg>;          # gets an object you can slurp
my $foo-IO = %?RESOURCES<images/foo.jpg>.open;     # gets an opened IO::Handle to work with

Note that paths and names of resource files can be mangled in an installed distribution, so do not rely on their values in any other case besides using them as keys for the %?RESOURCES variable.

The %?RESOURCES variable is not implemented as a plain Hash, but as an instance of the Distribution::Resource type, so do not expect to see all available resource files in a distribution by printing or by using other ways to inspect its value. Instead, use the API described above to access particular files.

The %?RESOURCES variable is only accessible inside of modules. If you want to access %?RESOURCES outside of a module, you'll need to expose that API yourself. One way to do that is to create a routine in the lib directory to return its value:

unit module MyLib;
sub my-resources is export {
    %?RESOURCES
}

Then create a test file, say, t/resources.t, with contents:

use Test;
use MyLib;

my $resources = my-resources;
isa-ok $resources, Distribution::Resource;

The contents of the compile-time hash are thus exposed to the runtime code.