Fetching contributors…
Cannot retrieve contributors at this time
717 lines (476 sloc) 23.3 KB


Synopsis 22: Distributions, Recommendations, Delivery and Installation


Created: 15 March 2014

Last Modified: 27 September 2015
Version: 6


Because many of the concepts used in this document may be overloaded by other concepts in the mind of the reader, it seems like a good idea to define some terminology first. Please note that these definitions only apply within the context of Perl 6.

compilation unit

A piece of code that can be compiled as a unit. It can either exist in a file (and be compiled using use or require), or be presented as a stream of characters for compilation with EVAL. An example of a compilation unit in a file:



A distribution is an archive of some form that can be used to install zero or more compilation units (each stored in a separate file), with any possibly associated files needed for execution. For example:


It has a name for identification, which may or may not coincide with the compilation units in the distribution. An example of a distribution name:


It also has a version, to distinguish it from other distributions with the same name. For instance:


Which, together, are used to create the filename of the distribution, for instance:


Please note that by changing the :: from the module specification to a - for the filename of the archive, we are effectively disallowing an owner to upload a distribution for "JSON-Fast" and "JSON::Fast" at the same time. This seems unlikely to become a problem.

A Perl 6 distribution must contain a configuration file named META6.json, containing JSON-encoded information about the contents of the distribution.


The owner of a distribution is responsible for the development of a distribution. This can either be a single person, or a (semi-)official organisation. The owner of a distribution has a (mnemonic) name, e.g.:


Please note that the owner is not necessarily the developer of a distribution, although if the owner is a single individual, this is pretty likely.

content storage

A service to which an owner can upload a distribution to and other people can download specific distributions from. This is most likely some online web-service, but it does not need to be. It has a logical name that is essentially a URL. An example would be:


The (mnemonic) name of the owner usually coincides with the userid or login name used to upload distributions, but does not need to be.


The auth of a distribution, is the combination of the content storage name with the name of the owner, separated by a colon. For example:


Please note that this is not an authority, merely an indication of the location where the distribution for that owner was obtained. Typically the auth of a distribution is used to try to load compilation units of already installed distributions, such as in:

use JSON::Fast:auth<cpan:JRANDOM>;


The identity of a distribution, is the combination of name of the content storage, the name of the owner, name and version of a distribution, separated by colons. For example:


There should really be only one unique distribution for a given identity in the world.

The content storage should accept an identity and either directly return the archive for that distribution, or return a URL from which that distribution can be downloaded.

recommendation manager

A service that will translate a request for a compilation unit (with optional owner and/or version and/or content storage specification, like a use statement) into a list of zero or more identities of distributions that match the request.

The recommendation manager is only used during the installation process of the distribution for a wanted compilation unit.

A recommendation manager can be run by a community (like the current Perl 6 ecosystem or the packages list for Perl 5 on CPAN), or by company (for use inside the company itself), or by any reviewing / grading service (for use by anybody wanting to use that service), or by any other person willing to put in the effort.

A request for:


would yield the identity:


because the compilation unit JSON::PurePerl is part of the JSON::Fast distribution.

However, a request for:


would not find anything, because it has the wrong content storage specification ("github" instead of "cpan").

Please note that a recommendation manager does not need to be bound to a single content storage. In fact, a recommendation manager would be best if being able to supply identities from the best of all worlds. And potentially be able to recommend identities responding to more natural language queries, but that is probably outside the scope of this specification.

A bundle of distributions is basically just a collection of identities that listen to a name (such as Rakudo *). A recommendation manager may provide bundles as part of its service. And packagers may use this information as the source for bundling distributions in their specific packaging system.


A Perl 6 distribution consists of an archive of some form (presumably a .tar.gz, .tar.bz2 or .zip file) which is expected to at least contain a file called "META6.json". The existence of this file indicates that this distribution is a Perl 6 distribution. This is important for those archive networks that also serve as a content-distribution system for other types of distributions (such as PAUSE / CPAN), so that they can adapt the processing of the contents, or decide to ignore any processing at all (such as CPAN-testers not being able to test Perl 6 distributions (yet)).


The META6.json file is a JSON-file that must at least contain a perl, name, version and description section.


Mandatory. The minimal perl version for which this distribution can be installed. Specified as a version string. So:

"perl" : "v6.0.1"

would not allow installation on Perl version 6.0.0.


Mandatory. The name identifying this distribution. This is usually the name of the main module that this distribution provides. An example of this would be:

"name" : "JSON::Fast"


Mandatory. The version literal for this distribution. An example of this would be:

"version" : "v1.23"


Mandatory. A one line description of this distribution. So, for instance:

"description" : "Providing fast JSON encoding/decoding"


Optional. A list of (mnemonic) names of people who work / have worked on this distribution. For informational purposes only. An example:

"authors" : [
  "Janet Random",
  "Sam Helpedwithit"

Please note that for identification purposes, only the owner (who uploaded the distribution to the content storage) should be used.


Optional. A list of module - local filename pairs that this distribution makes available to be used. For example:

"provides" : {
  "JSON::Fast"     : "lib/JSON/Fast.pm6",
  "JSON::PurePerl" : "lib/JSON/PurePerl.pm6"

Please note that the filenames specified only indicate the names of the files in the distribution. The installer may need to mangle filenames to be able support file systems that do not support the file names given (e.g. when they contain unicode characters where the file system does not support them). This also implies that any installer needs to keep a local database that is able to convert from the module names given, to the actual associated file).


Optional. A list of run-time dependencies, specified as use strings. To indicate alternatives, it is possible to specify a list of use strings, instead of just a single use string. So:

"depends" : [
  [ "Archive::Compress", "Archive::Zlib" ]

would indicate a dependency on Sereal, and either Archive::Compress or Archive::Zlib.

An installer has the option to automatically install any dependencies, if the user has so indicated. Dependencies and alternatives should be tried in the order they are specified. In the case of alternatives, the first one for which the recommendation manager returns an identity should be installed. Failure of installation of an alternative may allow automatic attempts on other alternatives.

Please note that the use strings of compilation units are specified. It is the responsibility of the recommendation manager to turn these into identities of distributions that can be downloaded.


Optional. A hash in which the key is the compunit (provided by the distribution) to be aliased, and the value is the use string that should match to get that compilation unit. An example of this would be:

"emulates" : {
  "JSON::Fast" : "JSON::XS:auth<cpan:MLEHMANN>"

If then later, a program would say:

use JSON::XS;

it would in fact load the JSON::Fast compunit, but make it appear as a JSON::XS compunit, but only if there was no "real" JSON::XS compunit installed that would match the use specification. In other words: if the real thing is available, then it will be used. If it is not, it will fall back to the indicated compilation unit. And it will look like you are using the thing you asked for.

Conversely, if one would do a:

use JSON::Fast;

then later doing a:

use JSON::XS:auth<cpan:MLEHMANN>;

in the same scope would become a no-op, just as if the compunit had already been loaded.

Please note that it is responsibility of the emulating compunit to actually provide a compatible interface with emulated compunit.


Optional. Has the same meaning as "emulates" for the "CompUnitRepo". But has additional meaning for external packagers: it indicates a potential superseding of the indicated compilation unit from the packagers point of view. See "superseded_by".


Optional. Has the reverse meaning of "emulates" for the "CompUnitRepo". It is a hash in which the key is compunit provided by the distribution, and the value is the use string of the compunit it should be aliased to if that compunit is available. So in this case:

"superseded_by" : {
  "JSON::Fast" : "SuperJSON:ver(v1.0 .. *)"

it would mean that if a program attempts to load the JSON::Fast compunit of this distribution, it should instead use any SuperJSON compunit that is installed that has a version of 1.0 or higher. In other words: please don't use my compunit, unless you really have to.

This tag has additional meaning for packagers: if a packager detects a valid supersedes and superseded_by pair in its collection of distributions to be packaged, the packager may decide to only supply the distribution providing the superseded_by compilation unit.

Please note that superseded_by has no meaning as a depends, so an installer should probably not automatically install any superseded_by compunits.


Optional. A hash in which the key is a compilation unit provided by this distribution, and the value is a use string of all compilation units that will be disallowed when attempted to be loaded in the same lexical scope. An example of this would be:

"excludes" : {
  "JSON::PurePerl" : "JSON::Slow:auth<cpan:*>:ver(1..*)"

So, if a lexical scope loads JSON::PurePerl from this distribution, then attempting to load JSON::Slow will cause a Failure. Please note that this has no meaning for packagers: it is simply a way to provide a better error message if a collision of some sort will occur when both modules are loaded in the same lexical scope.


Optional. A list of build-time dependencies, specified as use strings. An example of this would be:

"build-depends" : [


Optional. A list of test-time dependencies, specified as use strings. An example of this would be:

"test-depends" : [


Optional. A hash of resource groups, each of them corresponding to a directory in the "resource" directory in the distribution. Each resource group has a name and a list of files that are provided. At build time any not-yet existing files should be created. The installer will install all files into a location at its discretion (taking care of file-system case-insensitivity and unicode-support issues), and make the files available through the "%?RESOURCE" hash.


Optional. A hash of key-value pairs regarding support for this distribution. Possible names are: email, mailinglist, bugtracker, source, irc, phone.


The email address of the owner of this distribution, if any.


The mailinglist of users of this distribution, if any.


The bugtracker of this distribution, if any.


The URL of the source of this distribution, if any.


The URL of the IRC channel where this distribution can be discussed, if any.


A fully qualified phone number (with potential cost indication) that can be used with queries about this distribution.


Optional. A Boolean to indicate whether or not this is a distribution intended to be used in production. For instance:

"production" : 1

By default, a distribution is not ready for production. If a distribution is not ready for production, then it will never be recommended.

Please note that this section is only to be used by installers, giving them the opportunity to decide whether or not to install that distribution. Once a distribution is installed, it can be loaded just like any other distribution.


Optional. The URL with the text of the license under which this distribution is available for installation. Or some other way to indicate the license, e.g. inspired by the Perl 5 module Software::License.

"license" : ""


Optional. A list of general purpose tags. For instance:

"tags" : [

It has no meaning other than the meaning you assign to it.

Special directories

A distribution may contain several directories that will be handled specially.


Any file inside this directory, will be installed as a callable shell application.


All .t files in this directory, will be tested in alphabetical order, possibly in parallel.


All files in this directory should contain executable Perl 6 code, to be executed at various stages of the install process of this distribution.


Distributions can be installed with an installer. This may be a command-line script, or be some kind of GUI. The installer needs the user to (implicitly) select the CompUnitRepo in which the distribution should be installed, and the recommendation manager that should be used to convert requests for a compilation unit into an identity of a distribution to be downloaded.



Base class (interface, really) for the object living in the "@?INC" array. Used both for installing compunits, as well as finding a certain compunit by way of its from, longname, auth and ver information.

Specifying a CompUnitRepo

The specification of a CompUnitRepo can happen at various places: in a configuration file, on the command-line when starting (with -I), and in code when trying to create a CompUnitRepo object programmatically.

Each specification consists of a CompUnitRepo class specification (either explicitly, implicitly, or the short-hand form using the "short-id" identifier), optional named parameters and a location indicator (usually a path or a URL).

Some examples (where CURL is short for CompUnitRepo::Local):

/foo/bar                    simple CURL::File in /foo/bar
file#/foo/bar               (same)
inst#/installed             simple CURL::Installation in /installed
inst#name<work>#/installed  (same) but also set %?CUSTOM_LIwork
inst#name[work]#/installed  (same) but more CLI-friendly
inst#name{work}#/installed  (same) alternate CLI-friendly way
CompUnitRepo::Local::Installation#/installed  (same) but with full class name
CompUnitRepo::GitHub#masak/html-template      get it from GitHub

Multiple specifications may be concatenated with ,. If no class is specified on subsequent specifications, then the previous class specification will be assumed. So:

/foo/bar,/foo/baz           both use CURL::File
inst#/installed,/also       both use CURL::Installation
/foo/bar,inst#/installed    first CURL::File, second CURL::Installation


my $repo = $specification );

Create a new CompUnitRepo-like object with the given specification, either for inclusion in "@?INC", or to install a distribution. Returns the instantiated object.

Please note that for a given specification, there should always only be one CompUnitRepo object in a process.


say CompUnitRepo::Local::File.short-id;   # "file"

Returns a short \w+ identifier string (a tag if you will) to identify the use of this repo, e.g. in strings provided with the -I command line parameter. It should be unique for all of the CompUnitRepo subclasses loaded. The following short-id's are pre-defined:

file   CompUnitRepo::Local::File
inst   CompUnitRepo::Local::Installation


my $installed = $repo.install( $dist );

Install the compilation units of a "Distribution" in the appropriate way for this CompUnitRepo-like object. May cause a fatal exception if this repository does not support installing. The parameter contains the "Distribution" object to be installed. Returns True if the distribution was installed, or a Failure if it didn't.

Of course, any implementation of CompUnitRepo's install interface, may decide to accept additional meta-information and store this and make available for later introspection.


my $removed = $repo.uninstall( $dist );

The opposite of "install".


my @candidates = $repo.candidates( $longname, $auth?, $ver?, $from? );

Return CompUnit candidates given the matching credentials.


The simplest, default case for locating compilation units on a file system. The module name specified should directly map to a file, similar to how Perl 5 this does. Mainly intended to be used in development situations to allow developers to have modules to be available without them having to be installed.


Will fail unconditionally: installing compilation units is done by putting files in the right location.


The default case for installed compilation units. Similar to the way Perl 5 installs modules, but with meta-information per object, rather than globally in a packlist. This should be used by installers such as panda.


my $installed = $repo.install( $dist );

Install the given "Distribution" object in this repo.


The class for installing distributions using "CompUnitRepo::Local::Installation". Basically provides the API to access the META6.json file of a distribution. It should at least contain the following methods:


my $meta = $dist.meta;

Return a Hash with the representation of the meta-data, constructed the same way as in the META6.json specification. Please note that an actual META6.json file does not need to exist, just a representation in that format.


my $content = $dist.content( <provides JSON::Fast lib/JSON/Fast.pm6> );

my $content = $dist.content( <resource images fido.png> );

Return the octet-stream as specified by the given keys, navigating through the META6.json hash.


An implementation of the Distribution API for locally stored .tar files.


The object that describes a compilation unit. Contains as much meta-data as possible, e.g. from the Distribution object it came from.


my $compunit = $path );

Create a new CompUnit object with the given specification. Returns the instantiated object, or Failure if it could not find the path.

Please note that for a given path, there should always only be one CompUnit object in a process. This to prevent reloading the same compilation unit more than once.


my $loaded = @candidates[0].load(...);

Returns True if loading of the CompUnit was successful, or a Failure if something went wrong.


my $loaded = $compunit.loaded;

Return whether the compunit has been loaded.


my $precompiled = $compunit.precomp;

Create a pre-compiled version of the CompUnit. Optionally takes an output file argument (default: the same path as the source, with an extension identifying it is a precompiled version), an optional named argument :INC (with default @?INC) and a optional named argument :force to force creation even if the output file already exists.


Several dynamic variables are available.


This hash provides compile and runtime access to files associated with the "Distribution" of the current compilation unit.

So, if the META6.json file contains this resource section:

"resource" : {
  "images" : [
    "fido.png", "zowie.png"
  "libraries" : {
    "inline_helper" : "build-time",

then the Distribution is supposed to contain the files resource/images/fido.png and resource/images/zowie.png. After installation, IO objects of such a file would be available through


The absolute path could be obtained with:


and a handle could be obtained with:


without there being any guarantee that this path has anything to do with the path as specified in the distribution. Please also note that the installer will probably mangle filenames of actually installed files.

This means you can have files with unicode characters in upper/lower case, and still be able to access them when installed on a file system that does not support unicode.

If a leaf of the "resource" hash is a hash, it indicates files with special properties (such as being provided by the builder, so not part of the distribution). This will allow a good MANIFEST to be created from the META6.json information.


This hash provides key/value pairs of CompUnitRepo specifications, to be used by packagers and/or installers.


This array contains the CompUnitRepo objects that will be queried in turn whenever an attempt should be made to load a compilation unit (be that at compile time with use, or at runtime with require.

The first CompUnitRepo object to return one candidate, will then be loaded and no further CompUnitRepo objects in @?INC will be queried. If the first CompUnitRepo object to return any candidates, returns more than one candidate, then all other CompUnitRepo objects in @?INC will also be queried, to allow any error message to present a full list of CompUnit candidate objects.


Elizabeth Mattijsen <>


Hey! The above document had some coding errors, which are explained below:

Around line 671:

Unknown E content in E<images>

Around line 675:

Unknown E content in E<images>

Around line 679:

Unknown E content in E<images>