manpagez: man pages & more
man Alien::Build::Manual::PluginAuthor(3)
Home | html | info | man
Alien::Build::Manual::PluginAuthor(3)      User Contributed Perl Documentation



NAME

       Alien::Build::Manual::PluginAuthor - Alien::Build plugin author
       documentation


VERSION

       version 2.80


SYNOPSIS

       your plugin:

        package Alien::Build::Plugin::Build::MyPlugin;

        use strict;
        use warnings;
        use Alien::Build::Plugin;

        has arg1 => 'default_for arg1';
        has arg2 => sub { [ 'default', 'for', 'arg2' ] };

        sub init
        {
          my($self, $meta) = @_;
          ...
        }

        1;

       and then from alienfile:

        use alienfile;
        plugin 'Build::MyPlugin' => (
          arg1 => 'override for arg1',
          arg2 => [ 'something', 'else' ],
        );

       Perlish pseudo code for how plugins are called:

        my $probe;
        my $override = override();

        if($override eq 'system') {

          $probe = probe();

          if($probe ne 'system') {
            die 'system tool or library not found';
          }

        }

        elsif($override eq 'default') {
          $probe = probe();

        } else { # $override eq 'share'
          # note that in this instance the
          # probe hook is never called
          $probe = 'share';
        }

        if($probe eq 'system') {
          gather_system();

        } else { # $probe eq 'share'

          download();
          extract();
          patch();
          build();
          gather_share();

          # Check to see if there isa build_ffi hook
          if(defined &build_ffi) {
            patch_ffi();
            build_ffi();
            gather_ffi();
          }
        }

        # By default this just returns the value of $ENV{ALIEN_INSTALL_TYPE}
        sub override {
          return $ENV{ALIEN_INSTALL_TYPE};
        }

        # Default download implementation; can be
        # replaced by specifying a different download
        # hook.  See Alien::Build::Plugin::Core::Download
        # for detailed implementation.
        sub download {

          my $response = fetch();

          if($response->{type} eq 'html' || $response->{type} eq 'dir_listing') {
            # decode will transform an HTML listing (html) or a FTP directory
            # listing (dir_listing) into a regular list
            $response = decode($response);
          }

          if($response->{type} eq 'list') {

            # prefer will filter bad entries in the list
            # and sort them so that the first one is
            # the one that we want
            $response = prefer($response);

            my $first_preferred = $res->{list}->[0];

            # prefer can sometimes infer the version from the
            # filename.
            if(defined $first_preferred->{version}) {
              # not a hook
              runtime_prop->{version} = $first_preferred->{version};
            }

            $response = fetch($first_preferred);

          }

          if($response->{type} eq 'file') {
            # not a hook
            write_file_to_disk $response;
          }

        }


DESCRIPTION

       This document explains how to write Alien::Build plugins using the
       Alien::Build::Plugin base class.

   Writing plugins
       Plugins use Alien::Build::Plugin, which sets the appropriate base
       class, and provides you with the "has" property builder.  "has" takes
       two arguments, the name of the property and the default value.  (As
       with Moose and Moo, you should use a code reference to specify default
       values for non-string defaults).  No not set this as your plugin's base
       class directly:

        use parent qw( Alien::Build::Plugin );  # wrong
        use Alien::Build::Plugin;               # right

       The only method that you need to implement is "init".  From this method
       you can add hooks to change the behavior of the alienfile recipe.  This
       is a very simple example of a probe hook, with the actual probe logic
       removed:

        sub init
        {
          my($self, $meta) = @_;
          $meta->register_hook(
            probe => sub {
              my($build) = @_;
              if( ... )
              {
                return 'system';
              }
              else
              {
                return 'share';
              }
            },
          );
        }

       Hooks get the Alien::Build instance as their first argument, and
       depending on the hook may get additional arguments.

   Modifying hooks
       You can also modify hooks using "before_hook", "around_hook" and
       "after_hook", similar to Moose modifiers:

        sub init
        {
          my($self, $meta) = @_;

          $meta->before_hook(
            build => sub {
              my($build) = @_;
              $build->log('this runs before the build');
            },
          );

          $meta->after_hook(
            build => sub {
              my($build) = @_;
              $build->log('this runs after the build');
            },
          );

          $meta->around_hook(
            build => sub {
              my $orig = shift;

              # around hooks are useful for setting environment variables
              local $ENV{CPPFLAGS} = '-I/foo/include';

              $orig->(@_);
            },
          );
        }

   Testing plugins
       You can and should write tests for your plugin.  The best way to do
       this is using Test::Alien::Build, which allows you to write an inline
       alienfile in your test.  Here is an example:

        use Test::V0;
        use Test::Alien::Build;

        my $build = alienfile_ok q{
          use alienfile;
          plugin 'Build::MyPlugin' => (
            arg1 => 'override for arg1',
            arg2 => [ 'something', 'else' ],
          );
          ...
        };

        # you can interrogate $build, it is an instance of L<Alien::Build>.

        my $alien = alien_build_ok;

        # you can interrogate $alien, it is an instance of L<Alien::Base>.

   Negotiator plugins
       A Negotiator plugin doesn't itself typically implement anything on its
       own, but picks the best plugin to achieve a particular goal.

       The "best" plugin can in some cases vary depending on the platform or
       tools that are available.  For example The download negotiator might
       choose to use the fetch plugin that relies on the command line "curl",
       or it might choose the fetch plugin that relies on the Perl module
       HTTP::Tiny depending on the platform and what is already installed.
       (For either to be useful they have to support SSL).

       The Negotiator plugin is by convention named something like
       "Alien::Build::Plugin::*::Negotiate", but is typically invoked without
       the "::Negotiate" suffix.  For example:

        plugin 'Download'; # is short for Alien::Build::Plugin::Download::Negotiator

       Here is a simple example of a negotiator which picks "curl" if already
       installed and HTTP::Tiny otherwise.  (The actual download plugin is a
       lot smarter and complicated than this, but this is a good simplified
       example).

        package Alien::Build::Plugin::Download::Negotiate;

        use strict;
        use warnings;
        use Alien::Build::Plugin;
        use File::Which qw( which );

        sub init
        {
          my($self, $meta) = @_;

          if(which('curl')) {
            $meta->apply_plugin('Fetch::Curl');
          } else {
            $meta->apply_plugin('Fetch::HTTPTiny');
          }
        }

   Hooks
       The remainder of this document is a reference for the hooks that you
       can register.  Generally speaking you can register any hook that you
       like, but some care must be taken as some hooks have default behavior
       that will be overridden when you register a hook.  The hooks are
       presented in alphabetical order.  The execution order is shown in the
       flowchart above (if you are browsing the HTML version of this
       document), or the Perlish pseudo code in the synopsis section.


HOOKS

   build hook
        $meta->register_hook( build => sub {
          my($build) = @_;
          ...
        });

       This does the main build of the alienized project and installs it into
       the staging area.  The current directory is the build root.  You need
       to run whatever tools are necessary for the project, and install them
       into "$build-"install_prop->{prefix}> ("%{.install.prefix}").

   build_ffi hook
        $meta->register_hook( build_ffi => sub {
          my($build) = @_;
          ...
        });

       This is the same as build, except it fires only on a FFI build.

   decode hook
        $meta->register_hook( decode => sub {
          my($build, $res) = @_;
          ...
        }

       This hook takes a response hash reference from the "fetch" hook above
       with a type of "html" or "dir_listing" and converts it into a response
       hash reference of type "list".  In short it takes an HTML or FTP file
       listing response from a fetch hook and converts it into a list of
       filenames and links that can be used by the prefer hook to choose the
       correct file to download.  See the fetch hook for the specification of
       the input and response hash references.

   check_digest hook
        # implement the well known FOO-92 digest
        $meta->register_hook( check_digest => sub {
          my($build, $file, $algorithm, $digest) = @_;
          if($algorithm ne 'FOO92') {
            return 0;
          }
          my $actual = foo92_hex_digest($file);
          if($actual eq $digest) {
            return 1;
          } else {
            die "Digest FOO92 does not match: got $actual, expected $digest";
          }
        });

       This hook should check the given $file (the format is the same as used
       by the fetch hook) matches the given $digest using the given
       $algorithm.  If the plugin does not support the given algorithm, then
       it should return a false value.  If the digest does not match, it
       should throw an exception.  If the digest matches, it should return a
       true value.

   clean_install
        $meta->register_hook( clean_install => sub {
          my($build) = @_;
        });

       This hook allows you to remove files from the final install location
       before the files are installed by the installer layer (examples:
       Alien::Build::MM, Alien::Build::MB or App::af).  This hook is not
       called by default, and must be enabled via the interface to the
       installer layer (example: "clean_install" in Alien::Build::MM).

       This hook SHOULD NOT remove the "_alien" directory or its content from
       the install location.

       The default implementation removes all the files EXCEPT the "_alien"
       directory and its content.

   download hook
        $meta->register_hook( download => sub {
          my($build) = @_;
          ...
        });

       This hook is used to download from the internet the source.  Either as
       an archive (like tar, zip, etc), or as a directory of files ("git
       clone", etc).  When the hook is called, the current working directory
       will be a new empty directory, so you can save the download to the
       current directory.  If you store a single file in the directory,
       Alien::Build will assume that it is an archive, which will be processed
       by the extract hook.  If you store multiple files, Alien::Build will
       assume the current directory is the source root.  If no files are
       stored at all, an exception with an appropriate diagnostic will be
       thrown.

       Note: If you register this hook, then the fetch, decode and prefer
       hooks will NOT be called, unless you call them yourself from this hook.

   extract hook
        $meta->register_hook( extract => sub {
          my($build, $archive) = @_;
          ...
        });

       This hook is used to extract an archive that has already been
       downloaded.  Alien::Build already has plugins for the most common
       archive formats, so you will likely only need this to add support for
       new or novel archive formats.  When this hook is called, the current
       working directory will be a new empty directory, so you can save the
       content of the archive to the current directory.  If a single directory
       is written to the current directory, Alien::Build will assume that is
       the root directory of the package.  If multiple files and/or
       directories are present, that will indicate that the current working
       directory is the root of the package.  The logic typically handles
       correctly the default behavior for tar (where packages are typically
       extracted to a subdirectory) and for zip (where packages are typically
       extracted to the current directory).

   fetch hook
        package Alien::Build::Plugin::MyPlugin;

        use strict;
        use warnings;
        use Alien::Build::Plugin;
        use Carp ();

        has '+url' => sub { Carp::croak "url is required property" };

        sub init
        {
          my($self, $meta) = @_;

          $meta->register_hook( fetch => sub {
            my($build, $url, %options) = @_;
            ...
          }
        }

        1;

       Used to fetch a resource.  The first time it will be called without an
       argument (or with $url set to "undef", so the configuration used to
       find the resource should be specified by the plugin's properties.  On
       subsequent calls the first argument will be a URL.

       The %options hash may contain these options:

       http_headers
           HTTP request headers, if an appropriate protocol is being used.
           The headers are provided as an array reference of key/value pairs,
           which allows for duplicate header keys with multiple values.

           If a non-HTTP protocol is used, or if the plugin cannot otherwise
           send HTTP request headers, the plugin SHOULD issue a warning using
           the "$build->log" method, but because this option wasn't part of
           the original spec, the plugin MAY no issue that warning while
           ignoring it.

       Note that versions of Alien::Build prior to 2.39 did not pass the
       options hash into the fetch plugin.

       Normally the first fetch will be to either a file or a directory
       listing.  If it is a file then the content should be returned as a hash
       reference with the following keys:

        # content of file stored in Perl
        return {
          type     => 'file',
          filename => $filename,
          content  => $content,
          version  => $version,  # optional, if known
          protocol => $protocol, # AB 2.60 optional, but recommended
        };

        # content of file stored in the filesystem
        return {
          type     => 'file',
          filename => $filename,
          path     => $path,     # full file system path to file
          version  => $version,  # optional, if known
          tmp      => $tmp,      # optional
          protocol => $protocol, # AB 2.60 optional, but recommended
        };

       $tmp if set will indicate if the file is temporary or not, and can be
       used by Alien::Build to save a copy in some cases.  The default is
       true, so Alien::Build assumes the file or directory is temporary if you
       don't tell it otherwise.  Probably the most common situation when you
       would set "tmp" to false, is when the file is bundled inside the Alien
       distribution.  See Alien::Build::Plugin::Fetch::Local for example.

       If the URL points to a directory listing you should return it as either
       a hash reference containing a list of files:

        return {
          type => 'list',
          list => [
            # filename: each filename should be just the
            #   filename portion, no path or url.
            # url: each url should be the complete url
            #   needed to fetch the file.
            # version: OPTIONAL, may be provided by some fetch or prefer
            { filename => $filename1, url => $url1, version => $version1 },
            { filename => $filename2, url => $url2, version => $version2 },
          ],
          protocol => $protocol, # AB 2.60 optional, but recommended
        };

       or if the listing is in HTML format as a hash reference containing the
       HTML information:

        return {
          type => 'html',
          charset  => $charset, # optional
          base     => $base,    # the base URL: used for computing relative URLs
          content  => $content, # the HTML content
          protocol => $protocol, # optional, but recommended
        };

       or a directory listing (usually produced by an FTP servers) as a hash
       reference:

        return {
          type     => 'dir_listing',
          base     => $base,
          content  => $content,
          protocol => $protocol, # AB 2.60 optional, but recommended
        };

       [version 2.60]

       For all of these responses $protocol is optional, since it was not part
       of the original spec, however it is strongly recommended that you
       include this field, because future versions of Alien::Build will use
       this to determine if a file was downloaded securely (that is via a
       secure protocol such as SSL).

       Some plugins (like decode plugins ) trans late a file hash from one
       type to another, they should maintain the $protocol from the old to the
       new representation of the file.

   gather_ffi hook
        $meta->register_hook( gather_ffi => sub {
          my($build) = @_;
          $build->runtime_prop->{cflags}  = ...;
          $build->runtime_prop->{libs}    = ...;
          $build->runtime_prop->{version} = ...;
        });

       This hook is called for a FFI build to determine the properties
       necessary for using the library or tool.  These properties should be
       stored in the runtime_prop hash as shown above.  Typical properties
       that are needed for libraries are cflags and libs.  If at all possible
       you should also try to determine the version of the library or tool.

   gather_share hook
        $meta->register_hook( gather_share => sub {
          my($build) = @_;
          $build->runtime_prop->{cflags}  = ...;
          $build->runtime_prop->{libs}    = ...;
          $build->runtime_prop->{version} = ...;
        });

       This hook is called for a share install to determine the properties
       necessary for using the library or tool.  These properties should be
       stored in the runtime_prop hash as shown above.  Typical properties
       that are needed for libraries are cflags and libs.  If at all possible
       you should also try to determine the version of the library or tool.

   gather_system hook
        $meta->register_hook( gather_system => sub {
          my($build) = @_;
          $build->runtime_prop->{cflags}  = ...;
          $build->runtime_prop->{libs}    = ...;
          $build->runtime_prop->{version} = ...;
        });

       This hook is called for a system install to determine the properties
       necessary for using the library or tool.  These properties should be
       stored in the runtime_prop hash as shown above.  Typical properties
       that are needed for libraries are cflags and libs.  If at all possible
       you should also try to determine the version of the library or tool.

   override hook
        $meta->register_hook( override => sub {
          my($build) = @_;
          return $ENV{ALIEN_INSTALL_TYPE} || '';
        });

       This allows you to alter the override logic.  It should return one of
       "share", "system", "default" or ''.  The default implementation is
       shown above.  Alien::Build::Plugin::Probe::Override and
       Alien::Build::Plugin::Probe::OverrideCI are examples of how you can use
       this hook.

   patch hook
        $meta->register_hook( patch => sub {
          my($build) = @_;
          ...
        });

       This hook is completely optional.  If registered, it will be triggered
       after extraction and before build.  It allows you to apply any patches
       or make any modifications to the source if they are necessary.

   patch_ffi hook
        $meta->register_hook( patch_ffi => sub {
          my($build) = @_;
          ...
        });

       This hook is exactly like the patch hook, except it fires only on an
       FFI build.

   prefer hook
        $meta->register_hook( prefer => sub {
          my($build, $res) = @_;
          return {
            type => 'list',
            list => [sort @{ $res->{list} }],
          };
        }

       This hook sorts candidates from a listing generated from either the
       "fetch" or "decode" hooks.  It should return a new list hash reference
       with the candidates sorted from best to worst.  It may also remove
       candidates that are totally unacceptable.

   probe hook
        $meta->register_hook( probe => sub {
          my($build) = @_;
          return 'system' if ...; # system install
          return 'share';         # otherwise
        });

        $meta->register_hook( probe => [ $command ] );

       This hook should return the string "system" if the operating system
       provides the library or tool.  It should return "share" otherwise.

       You can also use a command that returns true when the tool or library
       is available.  For example for use with "pkg-config":

        $meta->register_hook( probe =>
          [ '%{pkgconf} --exists libfoo' ] );

       Or if you needed a minimum version:

        $meta->register_hook( probe =>
          [ '%{pkgconf} --atleast-version=1.00 libfoo' ] );

       Note that this hook SHOULD NOT gather system properties, such as
       cflags, libs, versions, etc, because the probe hook will be skipped in
       the event the environment variable "ALIEN_INSTALL_TYPE" is set.  The
       detection of these properties should instead be done by the
       gather_system hook.

       Multiple probe hooks can be given.  These will be used in sequence,
       stopping at the first that detects a system installation.


SEE ALSO

       Alien::Build::Manual(3)
           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 Fandino (salva)

       Gianni Ceccarelli (dakkar)

       Pavel Shaydo (zwon, trinitum)

       Kang-min Liu (<?><?><?>, gugod)

       Nicholas Shipp (nshp)

       Juan Julian Merelo Guervos (JJ)

       Joel Berger (JBERGER)

       Petr Pisar (ppisar)

       Lance Wicks (LANCEW)

       Ahmad Fatoum (a3f, ATHREEF)

       Jose Joaquin Atria (JJATRIA)

       Duke Leto (LETO)

       Shoichi Kaji (SKAJI)

       Shawn Laffan (SLAFFAN)

       Paul Evans (leonerd, PEVANS)

       Hakon Haegland (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.

perl v5.34.1                      2023-05-11
                                         Alien::Build::Manual::PluginAuthor(3)

alien-build 2.800.0 - Generated Mon Apr 8 18:39:05 CDT 2024
© manpagez.com 2000-2025
Individual documents may contain additional copyright information.