Mini Shell

Direktori : /usr/local/share/man/man3/
Upload File :
Current File : //usr/local/share/man/man3/Alien::Build::Manual::PluginAuthor.3pm

.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "Alien::Build::Manual::PluginAuthor 3"
.TH Alien::Build::Manual::PluginAuthor 3 "2024-10-29" "perl v5.32.1" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Alien::Build::Manual::PluginAuthor \- Alien::Build plugin author documentation
.SH "VERSION"
.IX Header "VERSION"
version 2.84
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
your plugin:
.PP
.Vb 1
\& package Alien::Build::Plugin::Build::MyPlugin;
\& 
\& use strict;
\& use warnings;
\& use Alien::Build::Plugin;
\& 
\& has arg1 => \*(Aqdefault_for arg1\*(Aq;
\& has arg2 => sub { [ \*(Aqdefault\*(Aq, \*(Aqfor\*(Aq, \*(Aqarg2\*(Aq ] };
\& 
\& sub init
\& {
\&   my($self, $meta) = @_;
\&   ...
\& }
\& 
\& 1;
.Ve
.PP
and then from alienfile:
.PP
.Vb 5
\& use alienfile;
\& plugin \*(AqBuild::MyPlugin\*(Aq => (
\&   arg1 => \*(Aqoverride for arg1\*(Aq,
\&   arg2 => [ \*(Aqsomething\*(Aq, \*(Aqelse\*(Aq ],
\& );
.Ve
.PP
Perlish pseudo code for how plugins are called:
.PP
.Vb 2
\& my $probe;
\& my $override = override();
\& 
\& if($override eq \*(Aqsystem\*(Aq) {
\& 
\&   $probe = probe();
\& 
\&   if($probe ne \*(Aqsystem\*(Aq) {
\&     die \*(Aqsystem tool or library not found\*(Aq;
\&   }
\& 
\& }
\& 
\& elsif($override eq \*(Aqdefault\*(Aq) {
\&   $probe = probe();
\& 
\& } else { # $override eq \*(Aqshare\*(Aq
\&   # note that in this instance the
\&   # probe hook is never called
\&   $probe = \*(Aqshare\*(Aq;
\& }
\& 
\& if($probe eq \*(Aqsystem\*(Aq) {
\&   gather_system();
\& 
\& } else { # $probe eq \*(Aqshare\*(Aq
\& 
\&   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 \*(Aqhtml\*(Aq || $response\->{type} eq \*(Aqdir_listing\*(Aq) {
\&     # 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 \*(Aqlist\*(Aq) {
\& 
\&     # 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 \*(Aqfile\*(Aq) {
\&     # not a hook
\&     write_file_to_disk $response;
\&   }
\& 
\& }
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This document explains how to write Alien::Build plugins using the
Alien::Build::Plugin base class.
.SS "Writing plugins"
.IX Subsection "Writing plugins"
Plugins use Alien::Build::Plugin, which sets the appropriate base
class, and provides you with the \f(CW\*(C`has\*(C'\fR property builder.  \f(CW\*(C`has\*(C'\fR 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 \fBnot\fR set this as your
plugin's base class directly:
.PP
.Vb 2
\& use parent qw( Alien::Build::Plugin );  # wrong
\& use Alien::Build::Plugin;               # right
.Ve
.PP
The only method that you need to implement is \f(CW\*(C`init\*(C'\fR.  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:
.PP
.Vb 10
\& sub init
\& {
\&   my($self, $meta) = @_;
\&   $meta\->register_hook(
\&     probe => sub {
\&       my($build) = @_;
\&       if( ... )
\&       {
\&         return \*(Aqsystem\*(Aq;
\&       }
\&       else
\&       {
\&         return \*(Aqshare\*(Aq;
\&       }
\&     },
\&   );
\& }
.Ve
.PP
Hooks get the Alien::Build instance as their first argument, and depending
on the hook may get additional arguments.
.SS "Modifying hooks"
.IX Subsection "Modifying hooks"
You can also modify hooks using \f(CW\*(C`before_hook\*(C'\fR, \f(CW\*(C`around_hook\*(C'\fR and \f(CW\*(C`after_hook\*(C'\fR,
similar to Moose modifiers:
.PP
.Vb 3
\& sub init
\& {
\&   my($self, $meta) = @_;
\& 
\&   $meta\->before_hook(
\&     build => sub {
\&       my($build) = @_;
\&       $build\->log(\*(Aqthis runs before the build\*(Aq);
\&     },
\&   );
\& 
\&   $meta\->after_hook(
\&     build => sub {
\&       my($build) = @_;
\&       $build\->log(\*(Aqthis runs after the build\*(Aq);
\&     },
\&   );
\& 
\&   $meta\->around_hook(
\&     build => sub {
\&       my $orig = shift;
\& 
\&       # around hooks are useful for setting environment variables
\&       local $ENV{CPPFLAGS} = \*(Aq\-I/foo/include\*(Aq;
\& 
\&       $orig\->(@_);
\&     },
\&   );
\& }
.Ve
.SS "Testing plugins"
.IX Subsection "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:
.PP
.Vb 2
\& use Test::V0;
\& use Test::Alien::Build;
\& 
\& my $build = alienfile_ok q{
\&   use alienfile;
\&   plugin \*(AqBuild::MyPlugin\*(Aq => (
\&     arg1 => \*(Aqoverride for arg1\*(Aq,
\&     arg2 => [ \*(Aqsomething\*(Aq, \*(Aqelse\*(Aq ],
\&   );
\&   ...
\& };
\& 
\& # 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>.
.Ve
.SS "Negotiator plugins"
.IX Subsection "Negotiator plugins"
A Negotiator plugin doesn't itself typically implement anything on
its own, but picks the best plugin to achieve a particular goal.
.PP
The \*(L"best\*(R" 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
\&\f(CW\*(C`curl\*(C'\fR, 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 \s-1SSL\s0).
.PP
The Negotiator plugin is by convention named something like
\&\f(CW\*(C`Alien::Build::Plugin::*::Negotiate\*(C'\fR, but is typically invoked
without the \f(CW\*(C`::Negotiate\*(C'\fR suffix.  For example:
.PP
.Vb 1
\& plugin \*(AqDownload\*(Aq; # is short for Alien::Build::Plugin::Download::Negotiator
.Ve
.PP
Here is a simple example of a negotiator which picks \f(CW\*(C`curl\*(C'\fR 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).
.PP
.Vb 1
\& 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(\*(Aqcurl\*(Aq)) {
\&     $meta\->apply_plugin(\*(AqFetch::Curl\*(Aq);
\&   } else {
\&     $meta\->apply_plugin(\*(AqFetch::HTTPTiny\*(Aq);
\&   }
\& }
.Ve
.SS "Hooks"
.IX Subsection "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 \s-1HTML\s0 version of this
document), or the Perlish pseudo code in the synopsis section.
.SH "HOOKS"
.IX Header "HOOKS"
.SS "build hook"
.IX Subsection "build hook"
.Vb 4
\& $meta\->register_hook( build => sub {
\&   my($build) = @_;
\&   ...
\& });
.Ve
.PP
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 \f(CW\*(C`$build\-\*(C'\fRinstall_prop\->{prefix}> (\f(CW\*(C`%{.install.prefix}\*(C'\fR).
.SS "build_ffi hook"
.IX Subsection "build_ffi hook"
.Vb 4
\& $meta\->register_hook( build_ffi => sub {
\&   my($build) = @_;
\&   ...
\& });
.Ve
.PP
This is the same as build, except it fires only on a \s-1FFI\s0 build.
.SS "decode hook"
.IX Subsection "decode hook"
.Vb 4
\& $meta\->register_hook( decode => sub {
\&   my($build, $res) = @_;
\&   ...
\& }
.Ve
.PP
This hook takes a response hash reference from the \f(CW\*(C`fetch\*(C'\fR hook above
with a type of \f(CW\*(C`html\*(C'\fR or \f(CW\*(C`dir_listing\*(C'\fR and converts it into a response
hash reference of type \f(CW\*(C`list\*(C'\fR.  In short it takes an \s-1HTML\s0 or \s-1FTP\s0 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.
.SS "check_digest hook"
.IX Subsection "check_digest hook"
.Vb 10
\& # implement the well known FOO\-92 digest
\& $meta\->register_hook( check_digest => sub {
\&   my($build, $file, $algorithm, $digest) = @_;
\&   if($algorithm ne \*(AqFOO92\*(Aq) {
\&     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";
\&   }
\& });
.Ve
.PP
This hook should check the given \f(CW$file\fR (the format is the same as used by
the fetch hook) matches the given \f(CW$digest\fR using the
given \f(CW$algorithm\fR.  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.
.SS "clean_install"
.IX Subsection "clean_install"
.Vb 3
\& $meta\->register_hook( clean_install => sub {
\&   my($build) = @_;
\& });
.Ve
.PP
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: \*(L"clean_install\*(R" in Alien::Build::MM).
.PP
This hook \s-1SHOULD NOT\s0 remove the \f(CW\*(C`_alien\*(C'\fR directory or its content from the
install location.
.PP
The default implementation removes all the files \s-1EXCEPT\s0 the \f(CW\*(C`_alien\*(C'\fR directory
and its content.
.SS "download hook"
.IX Subsection "download hook"
.Vb 4
\& $meta\->register_hook( download => sub {
\&   my($build) = @_;
\&   ...
\& });
.Ve
.PP
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 (\f(CW\*(C`git clone\*(C'\fR,
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.
.PP
\&\fBNote\fR: If you register this hook, then the fetch, decode and prefer
hooks will \s-1NOT\s0 be called, unless you call them yourself from this hook.
.SS "extract hook"
.IX Subsection "extract hook"
.Vb 4
\& $meta\->register_hook( extract => sub {
\&   my($build, $archive) = @_;
\&   ...
\& });
.Ve
.PP
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).
.SS "fetch hook"
.IX Subsection "fetch hook"
.Vb 1
\& package Alien::Build::Plugin::MyPlugin;
\& 
\& use strict;
\& use warnings;
\& use Alien::Build::Plugin;
\& use Carp ();
\& 
\& has \*(Aq+url\*(Aq => sub { Carp::croak "url is required property" };
\& 
\& sub init
\& {
\&   my($self, $meta) = @_;
\& 
\&   $meta\->register_hook( fetch => sub {
\&     my($build, $url, %options) = @_;
\&     ...
\&   }
\& }
\& 
\& 1;
.Ve
.PP
Used to fetch a resource.  The first time it will be called without an
argument (or with \f(CW$url\fR set to \f(CW\*(C`undef\*(C'\fR, 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 \s-1URL.\s0
.PP
The \f(CW%options\fR hash may contain these options:
.IP "http_headers" 4
.IX Item "http_headers"
\&\s-1HTTP\s0 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.
.Sp
If a non-HTTP protocol is used, or if the plugin cannot otherwise
send \s-1HTTP\s0 request headers, the plugin \s-1SHOULD\s0 issue a warning using
the \f(CW\*(C`$build\->log\*(C'\fR method, but because this option wasn't part
of the original spec, the plugin \s-1MAY\s0 no issue that warning while
ignoring it.
.PP
Note that versions of Alien::Build prior to 2.39 did not pass the
options hash into the fetch plugin.
.PP
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:
.PP
.Vb 8
\& # content of file stored in Perl
\& return {
\&   type     => \*(Aqfile\*(Aq,
\&   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     => \*(Aqfile\*(Aq,
\&   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
\& };
.Ve
.PP
\&\f(CW$tmp\fR 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 \f(CW\*(C`tmp\*(C'\fR to false, is when the file is bundled inside
the Alien distribution.  See Alien::Build::Plugin::Fetch::Local
for example.
.PP
If the \s-1URL\s0 points to a directory listing you should return it as either
a hash reference containing a list of files:
.PP
.Vb 10
\& return {
\&   type => \*(Aqlist\*(Aq,
\&   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
\& };
.Ve
.PP
or if the listing is in \s-1HTML\s0 format as a hash reference containing the
\&\s-1HTML\s0 information:
.PP
.Vb 7
\& return {
\&   type => \*(Aqhtml\*(Aq,
\&   charset  => $charset, # optional
\&   base     => $base,    # the base URL: used for computing relative URLs
\&   content  => $content, # the HTML content
\&   protocol => $protocol, # optional, but recommended
\& };
.Ve
.PP
or a directory listing (usually produced by an \s-1FTP\s0 servers) as a hash
reference:
.PP
.Vb 6
\& return {
\&   type     => \*(Aqdir_listing\*(Aq,
\&   base     => $base,
\&   content  => $content,
\&   protocol => $protocol, # AB 2.60 optional, but recommended
\& };
.Ve
.PP
[version 2.60]
.PP
For all of these responses \f(CW$protocol\fR 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 \s-1SSL\s0).
.PP
Some plugins (like decode plugins ) trans
late a file hash from one type to another, they should maintain the
\&\f(CW$protocol\fR from the old to the new representation of the file.
.SS "gather_ffi hook"
.IX Subsection "gather_ffi hook"
.Vb 6
\& $meta\->register_hook( gather_ffi => sub {
\&   my($build) = @_;
\&   $build\->runtime_prop\->{cflags}  = ...;
\&   $build\->runtime_prop\->{libs}    = ...;
\&   $build\->runtime_prop\->{version} = ...;
\& });
.Ve
.PP
This hook is called for a \s-1FFI\s0 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.
.SS "gather_share hook"
.IX Subsection "gather_share hook"
.Vb 6
\& $meta\->register_hook( gather_share => sub {
\&   my($build) = @_;
\&   $build\->runtime_prop\->{cflags}  = ...;
\&   $build\->runtime_prop\->{libs}    = ...;
\&   $build\->runtime_prop\->{version} = ...;
\& });
.Ve
.PP
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.
.SS "gather_system hook"
.IX Subsection "gather_system hook"
.Vb 6
\& $meta\->register_hook( gather_system => sub {
\&   my($build) = @_;
\&   $build\->runtime_prop\->{cflags}  = ...;
\&   $build\->runtime_prop\->{libs}    = ...;
\&   $build\->runtime_prop\->{version} = ...;
\& });
.Ve
.PP
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.
.SS "override hook"
.IX Subsection "override hook"
.Vb 4
\& $meta\->register_hook( override => sub {
\&   my($build) = @_;
\&   return $ENV{ALIEN_INSTALL_TYPE} || \*(Aq\*(Aq;
\& });
.Ve
.PP
This allows you to alter the override logic.  It should return one of
\&\f(CW\*(C`share\*(C'\fR, \f(CW\*(C`system\*(C'\fR, \f(CW\*(C`default\*(C'\fR or \f(CW\*(Aq\*(Aq\fR.  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.
.SS "patch hook"
.IX Subsection "patch hook"
.Vb 4
\& $meta\->register_hook( patch => sub {
\&   my($build) = @_;
\&   ...
\& });
.Ve
.PP
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.
.SS "patch_ffi hook"
.IX Subsection "patch_ffi hook"
.Vb 4
\& $meta\->register_hook( patch_ffi => sub {
\&   my($build) = @_;
\&   ...
\& });
.Ve
.PP
This hook is exactly like the patch hook, except it fires only on an
\&\s-1FFI\s0 build.
.SS "prefer hook"
.IX Subsection "prefer hook"
.Vb 7
\& $meta\->register_hook( prefer => sub {
\&   my($build, $res) = @_;
\&   return {
\&     type => \*(Aqlist\*(Aq,
\&     list => [sort @{ $res\->{list} }],
\&   };
\& }
.Ve
.PP
This hook sorts candidates from a listing generated from either the \f(CW\*(C`fetch\*(C'\fR
or \f(CW\*(C`decode\*(C'\fR 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.
.SS "probe hook"
.IX Subsection "probe hook"
.Vb 5
\& $meta\->register_hook( probe => sub {
\&   my($build) = @_;
\&   return \*(Aqsystem\*(Aq if ...; # system install
\&   return \*(Aqshare\*(Aq;         # otherwise
\& });
\& 
\& $meta\->register_hook( probe => [ $command ] );
.Ve
.PP
This hook should return the string \f(CW\*(C`system\*(C'\fR if the operating
system provides the library or tool.  It should return \f(CW\*(C`share\*(C'\fR
otherwise.
.PP
You can also use a command that returns true when the tool
or library is available.  For example for use with \f(CW\*(C`pkg\-config\*(C'\fR:
.PP
.Vb 2
\& $meta\->register_hook( probe =>
\&   [ \*(Aq%{pkgconf} \-\-exists libfoo\*(Aq ] );
.Ve
.PP
Or if you needed a minimum version:
.PP
.Vb 2
\& $meta\->register_hook( probe =>
\&   [ \*(Aq%{pkgconf} \-\-atleast\-version=1.00 libfoo\*(Aq ] );
.Ve
.PP
Note that this hook \s-1SHOULD NOT\s0 gather system properties, such as
cflags, libs, versions, etc, because the probe hook will be skipped
in the event the environment variable \f(CW\*(C`ALIEN_INSTALL_TYPE\*(C'\fR is set.
The detection of these properties should instead be done by the
gather_system hook.
.PP
Multiple probe hooks can be given.  These will be used in sequence,
stopping at the first that detects a system installation.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
.IP "Alien::Build::Manual" 4
.IX Item "Alien::Build::Manual"
Other Alien::Build manuals.
.SH "AUTHOR"
.IX Header "AUTHOR"
Author: Graham Ollis <plicease@cpan.org>
.PP
Contributors:
.PP
Diab Jerius (\s-1DJERIUS\s0)
.PP
Roy Storey (\s-1KIWIROY\s0)
.PP
Ilya Pavlov
.PP
David Mertens (run4flat)
.PP
Mark Nunberg (mordy, mnunberg)
.PP
Christian Walde (Mithaldu)
.PP
Brian Wightman (MidLifeXis)
.PP
Zaki Mughal (zmughal)
.PP
mohawk (mohawk2, \s-1ETJ\s0)
.PP
Vikas N Kumar (vikasnkumar)
.PP
Flavio Poletti (polettix)
.PP
Salvador Fandiño (salva)
.PP
Gianni Ceccarelli (dakkar)
.PP
Pavel Shaydo (zwon, trinitum)
.PP
Kang-min Liu (劉康民, gugod)
.PP
Nicholas Shipp (nshp)
.PP
Juan Julián Merelo Guervós (\s-1JJ\s0)
.PP
Joel Berger (\s-1JBERGER\s0)
.PP
Petr Písař (ppisar)
.PP
Lance Wicks (\s-1LANCEW\s0)
.PP
Ahmad Fatoum (a3f, \s-1ATHREEF\s0)
.PP
José Joaquín Atria (\s-1JJATRIA\s0)
.PP
Duke Leto (\s-1LETO\s0)
.PP
Shoichi Kaji (\s-1SKAJI\s0)
.PP
Shawn Laffan (\s-1SLAFFAN\s0)
.PP
Paul Evans (leonerd, \s-1PEVANS\s0)
.PP
Håkon Hægland (hakonhagland, \s-1HAKONH\s0)
.PP
nick nauwelaerts (\s-1INPHOBIA\s0)
.PP
Florian Weimer
.SH "COPYRIGHT AND LICENSE"
.IX Header "COPYRIGHT AND LICENSE"
This software is copyright (c) 2011\-2022 by Graham Ollis.
.PP
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

Zerion Mini Shell 1.0