Provided by: libalien-build-perl_2.80-2_all bug

NAME

       Alien::Build::Manual::AlienAuthor - Alien author documentation

VERSION

       version 2.80

SYNOPSIS

        perldoc Alien::Build::Manual::AlienAuthor

DESCRIPTION

       Note: Please read the entire document before you get started in writing your own
       alienfile.  The section on dynamic vs. static libraries will likely save you a lot of
       grief if you read it now!

       This document is intended to teach Alien authors how to build their own Alien distribution
       using Alien::Build and Alien::Base.  Such an Alien distribution consists of three
       essential parts:

       An alienfile
           This is a recipe for how to 1) detect an already installed version of the library or
           tool you are alienizing 2) download and build the library or tool that you are
           alienizing and 3) gather the configuration settings necessary for the use of that
           library or tool.

       An installer "Makefile.PL" or "Build.PL" or a "dist.ini" if you are using Dist::Zilla
           This is a thin layer between your alienfile recipe, and the Perl installer (either
           ExtUtils::MakeMaker or Module::Build.

       A Perl class (.pm file) that inherits from Alien::Base
           For most Aliens this does not need to be customized at all, since Alien::Base usually
           does what you need.

       For example if you were alienizing a library called libfoo, you might have these files:

        Alien-Libfoo-1.00/Makefile.PL
        Alien-Libfoo-1.00/alienfile
        Alien-Libfoo-1.00/lib/Alien/Libfoo.pm

       This document will focus mainly on instructing you how to construct an alienfile, but we
       will also briefly cover making a simple "Makefile.PL" or "dist.ini" to go along with it.
       We will also touch on when you might want to extend your subclass to add non-standard
       functionality.

   Using commands
       Most software libraries and tools will come with instructions for how to install them in
       the form of commands that you are intended to type into a shell manually.  The easiest way
       to automate those instructions is to just put the commands in your alienfile.  For
       example, lets suppose that libfoo is built using autoconf and provides a "pkg-config"
       ".pc" file.

       We will also later discuss plugins.  For common build systems like autoconf or CMake, it
       is usually better to use the appropriate plugin because they will handle corner cases
       better than a simple set of commands.  We're going to take a look at commands first
       because it's easier to understand the different phases with commands.

       (Aside, autoconf is a series of tools and macros used to configure (usually) a C or C++
       library or tool by generating any number of Makefiles.  It is the C equivalent to
       ExtUtils::MakeMaker, if you will.  Basically, if your library or tool instructions start
       with './configure' it is most likely an autoconf based library or tool).

       (Aside2, "pkg-config" is a standard-ish way to provide the compiler and linker flags
       needed for compiling and linking against the library.  If your tool installs a ".pc" file,
       usually in "$PREFIX/lib/pkgconfig" then, your tool uses "pkg-config").

       Here is the alienfile that you might have:

        use alienfile;

        probe [ 'pkg-config --exists libfoo' ];

        share {

          start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';

          download [ 'wget %{.meta.start_url}' ];

          extract [ 'tar zxf %{.install.download}' ];

          build [
            [ './configure --prefix=%{.install.prefix} --disable-shared' ],
            [ '%{make}' ],
            [ '%{make} install' ],
          ];

        };

        gather [
          [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
          [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
          [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
        ];

       There is a lot going on here, so lets decode it a little bit.  An alienfile is just some
       Perl with some alien specific sugar.  The first line

        use alienfile;

       imports the sugar into the alienfile.  It also is a flag for the reader to see that this
       is an alienfile and not some other kind of Perl script.

       The second line is the probe directive:

        probe [ 'pkg-config --exists libfoo' ];

       is used to see if the library is already installed on the target system.  If "pkg-config"
       is in the path, and if libfoo is installed, this should exit with a success (0) and tell
       Alien::Build to use the system library.  If either "pkg-config" in the PATH, or if libfoo
       is not installed, then it will exist with non-success (!= 0) and tells Alien::Build to
       download and build from source.

       You can provide as many probe directives as you want.  This is useful if there are
       different ways to probe for the system.  Alien::Build will stop on the first successfully
       found system library found.  Say our library libfoo comes with a ".pc" file for use with
       "pkg-config" and also provides a "foo-config" program to find the same values.  You could
       then specify this in your alienfile

        probe [ 'pkg-config --exists libfoo' ];
        probe [ 'foo-config --version' ];

       Other directives can be specified multiple times if there are different methods that can
       be tried for the various steps.

       Sometimes it is easier to probe for a library from Perl rather than with a command.  For
       that you can use a code reference.  For example, another way to call "pkg-config" would be
       from Perl:

        probe sub {
          my($build) = @_;  # $build is the Alien::Build instance.
          system 'pkg-config --exists libfoo';
          $? == 0 ? 'system' : 'share';
        };

       The Perl code should return 'system' if the library is installed, and 'share' if not.
       (Other directives should return a true value on success, and a false value on failure).
       You can also throw an exception with "die" to indicate a failure.

       The next part of the alienfile is the "share" block, which is used to group the directives
       which are used to download and install the library or tool in the event that it is not
       already installed.

        share {
          start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';
          download [ 'wget %{.meta.start_url}' ];
          extract [ 'tar zxf %{.install.download}' ];
          build [
            [ './configure --prefix=%{.install.prefix} --disable-shared' ],
            [ '%{make}' ],
            [ '%{make} install' ],
          ];
        };

       The start_url specifies where to find the package that you are alienizing.  It should be
       either a tarball (or zip file, or what have you) or an HTML index.  The download directive
       as you might imagine specifies how to download  the library or tool.  The extract
       directive specifies how to extract the archive once it is downloaded.  In the extract
       step, you can use the variable "%{.install.download}" as a placeholder for the archive
       that was downloaded in the download step.  This is also accessible if you use a code
       reference from the Alien::Build instance:

        share {
          ...
          requires 'Archive::Extract';
          extract sub {
            my($build) = @_;
            my $tarball = $build->install_prop->{download};
            my $ae = Archive::Extract->new( archive => $tarball );
            $ae->extract;
            1;
          }
          ...
        };

       The build directive specifies how to build the library or tool once it has been downloaded
       and extracted.  Note the special variable "%{.install.prefix}" is the location where the
       library should be installed.  "%{make}" is a helper which will be replaced by the
       appropriate "make", which may be called something different on some platforms (on Windows
       for example, it frequently may be called "nmake" or "dmake").

       The final part of the alienfile has a gather directive which specifies how to get the
       details on how to compile and link against the library.  For this, once again we use the
       "pkg-config" command:

        gather [
          [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
          [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
          [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
        ];

       The scalar reference as the final item in the command list tells Alien::Build that the
       output from the command should be stored in the given variable.  The runtime variables are
       the ones that will be available to "Alien::Libfoo" once it is installed.  (Install
       properties, which are the ones that we have seen up till now are thrown away once the
       Alien distribution is installed.

       You can also provide a "sys" block for directives that should be used when a system
       install is detected.  Normally you only need to do this if the gather step is different
       between share and system installs.  For example, the above is equivalent to:

        build {
          ...
          gather [
            [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
            [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
            [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
          ];
        };

        sys {
          gather [
            [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
            [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
            [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
          ];
        };

       (Aside3, the reason it is called "sys" and not "system" is so that it does not conflict
       with the built in "system" function)!

   Using plugins
       The first example is a good way of showing the full manual path that you can choose, but
       there is a lot of repetition, if you are doing many Aliens that use autoconf and
       "pkg-config" (which are quite common.  alienfile allows you to use plugins.  See
       Alien::Build::Plugin for a list of some of the plugin categories.

       For now, I will just show you how to write the alienfile for libfoo above using
       Alien::Build::Plugin::Build::Autoconf, Alien::Build::Plugin::PkgConfig::Negotiate,
       Alien::Build::Plugin::Download::Negotiate, and Alien::Build::Plugin::Extract::Negotiate

        use alienfile;

        plugin 'PkgConfig' => (
          pkg_name => 'libfoo',
        );

        share {
          start_url 'http://www.libfoo.org/src';
          plugin 'Download' => (
            filter => qr/^libfoo-[0-9\.]+\.tar\.gz$/,
            version => qr/^libfoo-([0-9\.]+)\.tar\.gz$/,
          );
          plugin 'Extract' => 'tar.gz';
          plugin 'Build::Autoconf';
          build [
            '%{configure} --disable-shared',
            '%{make}',
            '%{make} install',
          ];
        };

       The first plugin that we use is the "pkg-config" negotiation plugin.  A negotiation plugin
       is one which doesn't do the actual work but selects the best one from a set of plugins
       depending on your platform and environment.  (In the case of
       Alien::Build::Plugin::PkgConfig::Negotiate, it may choose to use command line tools, a
       pure Perl implementation (PkgConfig), or libpkgconf, depending on what is available).
       When using negotiation plugins you may omit the "::Negotiate" suffix.  So as you can see
       using the plugin here is an advantage because it is more reliable than just specifying a
       command which may not be installed!

       Next we use the download negotiation plugin.  This is also better than the version above,
       because again, "wget" my not be installed on the target system.  Also you can specify a
       URL which will be scanned for links, and use the most recent version.

       We use the Extract negotiation plugin to use either command line tools, or Perl libraries
       to extract from the archive once it is downloaded.

       Finally we use the Autoconf plugin (Alien::Build::Plugin::Build::Autoconf).  This is a lot
       more sophisticated and reliable than in the previous example, for a number of reasons.
       This version will even work on Windows assuming the library or tool you are alienizing
       supports that platform!

       Strictly speaking the build directive is not necessary, because the autoconf plugin
       provides a default which is reasonable.  The only reason that you would want to include it
       is if you need to provide additional flags to the configure step.

        share {
          ...
          build [
            '%{configure} --enable-bar --enable-baz --disable-shared',
            '%{make}',
            '%{make} install',
          ];
        };

   Multiple .pc files
       Some packages come with multiple libraries paired with multiple ".pc" files.  In this case
       you want to provide the Alien::Build::Plugin::PkgConfig::Negotiate with an array reference
       of package names.

        plugin 'PkgConfig' => (
          pkg_name => [ 'foo', 'bar', 'baz' ],
        );

       All packages must be found in order for the "system" install to succeed.  Once installed
       the first "pkg_name" will be used by default (in this example "foo"), and you can retrieve
       any other "pkg_name" using the Alien::Base alt method.

   A note about dynamic vs. static libraries
       If you are using your Alien to build an XS module, it is important that you use static
       libraries if possible.  If you have a package that refuses to build a static library, then
       you can use Alien::Role::Dino.

       Actually let me back up a minute.  For a "share" install it is best to use static
       libraries to build your XS extension.  This is because if your Alien is ever upgraded to a
       new version it can break your existing XS modules.  For a "system" install shared
       libraries are usually best because you can often get security patches without having to
       re-build anything in perl land.

       If you looked closely at the "Using commands" and "Using plugins" sections above, you may
       notice that we went out of our way where possible to tell Autotools to build only static
       libraries using the "--disable-shared" command.  The Autoconf plugin also does this by
       default.

       Sometimes though you will have a package that builds both, or maybe you want both static
       and dynamic libraries to work with XS and FFI.  For that case, there is the
       Alien::Build::Plugin::Gather::IsolateDynamic plugin.

        use alienfile;
        ...
        plugin 'Gather::IsolateDynamic';

       What it does, is that it moves the dynamic libraries (usually .so on Unix and .DLL on
       Windows) to a place where they can be found by FFI, and where they won't be used by the
       compiler for building XS.  It usually doesn't do any harm to include this plugin, so if
       you are just starting out you might want to add it anyway.  Arguably it should have been
       the default behavior from the beginning.

       If you have already published an Alien that does not isolate its dynamic libraries, then
       you might get some fails from old upgraded aliens because the share directory isn't
       cleaned up by default (this is perhaps a design bug in the way that share directories
       work, but it is a long standing characteristic).  One work around for this is to use the
       "clean_install" property on Alien::Build::MM, which will clean out the share directory on
       upgrade, and possibly save you a lot of grief.

   Verifying and debugging your alienfile
       You could feed your alienfile directly into Alien::Build, or Alien::Build::MM, but it is
       sometimes useful to test your alienfile using the "af" command (it does not come with
       Alien::Build, you need to install App::af).  By default "af" will use the "alienfile" in
       the current directory (just as "make" uses the "Makefile" in the current directory; just
       like "make" you can use the "-f" option to specify a different alienfile).

       You can test your alienfile in dry run mode:

        % af install --dry-run
        Alien::Build::Plugin::Core::Legacy> adding legacy hash to config
        Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/I2YXRyxb0r/_alien
        ---
        cflags: ''
        cflags_static: ''
        install_type: system
        legacy:
          finished_installing: 1
          install_type: system
          name: libfoo
          original_prefix: /tmp/7RtAusykNN
          version: 1.2.3
        libs: '-lfoo '
        libs_static: '-lfoo '
        prefix: /tmp/7RtAusykNN
        version: 1.2.3

       You can use the "--type" option to force a share install (download and build from source):

        % af install --type=share --dry-run
        Alien::Build::Plugin::Core::Download> decoding html
        Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  ...
        Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
        Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
        Alien::Build::CommandSequence> + ./configure --prefix=/tmp/P22WEXj80r --with-pic --disable-shared
        ... snip ...
        Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/WsoLAQ889w/_alien
        ---
        cflags: ''
        cflags_static: ''
        install_type: share
        legacy:
          finished_installing: 1
          install_type: share
          original_prefix: /tmp/P22WEXj80r
          version: 1.2.4
        libs: '-L/tmp/P22WEXj80r/lib -lfoo '
        libs_static: '-L/tmp/P22WEXj80r/lib -lfoo '
        prefix: /tmp/P22WEXj80r
        version: 1.2.4

       You can also use the "--before" and "--after" options to take a peek at what the build
       environment looks like at different stages as well, which can sometimes be useful:

        % af install --dry-run --type=share --before build bash
        Alien::Build::Plugin::Core::Download> decoding html
        Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
        Alien::Build::Plugin::Core::Download> candidate  ...
        Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
        Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
        App::af::install>  [ before build ] + bash
        /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$ ls
        CHANGES Makefile autoconf.ac lib
        /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$

       There are a lot of other useful things that you can do with the "af" command.  See af for
       details.

   Integrating with MakeMaker
       Once you have a working alienfile you can write your "Makefile.PL".

        use ExtUtils::MakeMaker;
        use Alien::Build::MM;

        my $abmm = Alien::Build::MM->new;

        WriteMakefile($abmm->mm_args(
          ABSTRACT           => 'Discover or download and install libfoo',
          DISTNAME           => 'Alien-Libfoo',
          NAME               => 'Alien::Libfoo',
          VERSION_FROM       => 'lib/Alien/Libfoo.pm',
          CONFIGURE_REQUIRES => {
            'Alien::Build::MM' => 0,
          },
          BUILD_REQUIRES => {
            'Alien::Build::MM' => 0,
          },
          PREREQ_PM => {
            'Alien::Base' => 0,
          },
          # If you are going to write the recommended
          # tests you will will want these:
          TEST_REQUIRES => {
            'Test::Alien' => 0,
            'Test2::V0'   => 0,
          },
        ));

        sub MY::postamble {
          $abmm->mm_postamble;
        }

       The "lib/Alien/Libfoo.pm" that goes along with it is very simple:

        package Alien::Libfoo;

        use strict;
        use warnings;
        use parent qw( Alien::Base );

        1;

       You are done and can install it normally:

        % perl Makefile.PL
        % make
        % make test
        % make install

   Integrating with Module::Build
       Please don't!  Okay if you have to there is Alien::Build::MB.

   Non standard configuration
       Alien::Base support most of the things that your Alien will need, like compiler flags
       (cflags), linker flags (libs) and binary directory (bin_dir).  Your library or tool may
       have other configuration items which are not supported by default.  You can store the
       values in the alienfile into the runtime properties:

        gather [
          # standard:
          [ 'foo-config --version libfoo', \'%{.runtime.version}' ],
          [ 'foo-config --cflags  libfoo', \'%{.runtime.cflags}'  ],
          [ 'foo-config --libs    libfoo', \'%{.runtime.libs}'    ],
          # non-standard
          [ 'foo-config --bar-baz libfoo', \'%{.runtime.bar_baz}' ],
        ];

       then you can expose them in your Alien::Base subclass:

        package Alien::Libfoo;

        use strict;
        use warnings;
        use parent qw( Alien::Base );

        sub bar_baz {
          my($self) = @_;
          $self->runtime_prop->{bar_baz},
        };

        1;

   Testing
       (optional, but highly recommended)

       You should write a test using Test::Alien to make sure that your alien will work with any
       XS modules that are going to use it:

        use Test2::V0;
        use Test::Alien;
        use Alien::Libfoo;

        alien_ok 'Alien::Libfoo';

        xs_ok do { local $/; <DATA> }, with_subtest {
          is Foo::something(), 1, 'Foo::something() returns 1';
        };

        done_testing;

        __DATA__
        #include "EXTERN.h"
        #include "perl.h"
        #include "XSUB.h"
        #include <foo.h>

        MODULE = Foo PACKAGE = Foo

        int something()

       You can also use Test::Alien to test tools instead of libraries:

        use Test2::V0;
        use Test::Alien;
        use Alien::Libfoo;

        alien_ok 'Alien::Libfoo';
        run_ok(['foo', '--version'])
          ->exit_is(0);

        done_testing;

       You can also write tests specifically for FFI::Platypus, if your alien is going to be used
       to write FFI bindings.  (the test below is the FFI equivalent to the XS example above).

        use Test2::V0;
        use Test::Alien;
        use Alien::Libfoo;

        alien_ok 'Alien::Libfoo';
        ffi_ok { symbols => [ 'something' ] }, with_subtest {
          # $ffi is an instance of FFI::Platypus with the lib
          # set appropriately.
          my($ffi) = @_;
          my $something = $ffi->function( something => [] => 'int' );
          is $something->call(), 1, 'Foo::something() returns 1';
        };

       If you do use "ffi_ok" you want to make sure that your alien reliably produces dynamic
       libraries.  If it isn't consistent (if for example some platforms tend not to provide or
       build dynamic libraries), you can check that "dynamic_libs" doesn't return an empty list.

        ...
        alien_ok 'Alien::Libfoo';
        SKIP: {
          skip "This test requires a dynamic library"
            unless Alien::Libfoo->dynamic_libs;
          ffi_ok { symbols [ 'something' ] }, with_subtest {
            ...
          };
        }

       More details on testing Alien modules can be found in the Test::Alien documentation.

       You can also run the tests that come with the package that you are alienizing, by using a
       "test" block in your alienfile.  Keep in mind that some packages use testing tools or have
       other prerequisites that will not be available on your users machines when they attempt to
       install your alien.  So you do not want to blindly add a test block without checking what
       the prereqs are.  For Autoconf style packages you typically test a package using the "make
       check" command:

        use alienfile;

        plugin 'PkgConfig' => 'libfoo';

        share {
          ... # standard build steps.
          test [ '%{make} check' ];
        };

   Dist::Zilla
       (optional, mildly recommended)

       You can also use the Alien::Build Dist::Zilla plugin Dist::Zilla::Plugin::AlienBuild:

        name    = Alien-Libfoo
        author  = E. Xavier Ample <example@cpan.org>
        license = Perl_5
        copyright_holder = E. Xavier Ample <example@cpan.org>
        copyright_year   = 2017
        version = 0.01

        [@Basic]
        [AlienBuild]

       The plugin takes care of a lot of details like making sure that the correct minimum
       versions of Alien::Build and Alien::Base are used.  See the plugin documentation for
       additional details.

   Using your Alien
       Once you have installed you can use your Alien.  See Alien::Build::Manual::AlienUser for
       guidance on that.

SEE ALSO

       Alien::Build::Manual
           Other Alien::Build manuals.

AUTHOR

       Author: Graham Ollis <plicease@cpan.org>

       Contributors:

       Diab Jerius (DJERIUS)

       Roy Storey (KIWIROY)

       Ilya Pavlov

       David Mertens (run4flat)

       Mark Nunberg (mordy, mnunberg)

       Christian Walde (Mithaldu)

       Brian Wightman (MidLifeXis)

       Zaki Mughal (zmughal)

       mohawk (mohawk2, ETJ)

       Vikas N Kumar (vikasnkumar)

       Flavio Poletti (polettix)

       Salvador Fandiño (salva)

       Gianni Ceccarelli (dakkar)

       Pavel Shaydo (zwon, trinitum)

       Kang-min Liu (劉康民, gugod)

       Nicholas Shipp (nshp)

       Juan Julián Merelo Guervós (JJ)

       Joel Berger (JBERGER)

       Petr Písař (ppisar)

       Lance Wicks (LANCEW)

       Ahmad Fatoum (a3f, ATHREEF)

       José Joaquín Atria (JJATRIA)

       Duke Leto (LETO)

       Shoichi Kaji (SKAJI)

       Shawn Laffan (SLAFFAN)

       Paul Evans (leonerd, PEVANS)

       Håkon Hægland (hakonhagland, HAKONH)

       nick nauwelaerts (INPHOBIA)

       Florian Weimer

COPYRIGHT AND LICENSE

       This software is copyright (c) 2011-2022 by Graham Ollis.

       This is free software; you can redistribute it and/or modify it under the same terms as
       the Perl 5 programming language system itself.