Mini Shell

Direktori : /usr/local/share/man/man3/
Upload File :
Current File : //usr/local/share/man/man3/Alien::Build::Manual::AlienAuthor.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::AlienAuthor 3"
.TH Alien::Build::Manual::AlienAuthor 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::AlienAuthor \- Alien author documentation
.SH "VERSION"
.IX Header "VERSION"
version 2.84
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 1
\& perldoc Alien::Build::Manual::AlienAuthor
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBNote\fR: 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!
.PP
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:
.IP "An alienfile" 4
.IX Item "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.
.ie n .IP "An installer ""Makefile.PL"" or ""Build.PL"" or a ""dist.ini"" if you are using Dist::Zilla" 4
.el .IP "An installer \f(CWMakefile.PL\fR or \f(CWBuild.PL\fR or a \f(CWdist.ini\fR if you are using Dist::Zilla" 4
.IX Item "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.
.IP "A Perl class (.pm file) that inherits from Alien::Base" 4
.IX Item "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.
.PP
For example if you were alienizing a library called libfoo, you might
have these files:
.PP
.Vb 3
\& Alien\-Libfoo\-1.00/Makefile.PL
\& Alien\-Libfoo\-1.00/alienfile
\& Alien\-Libfoo\-1.00/lib/Alien/Libfoo.pm
.Ve
.PP
This document will focus mainly on instructing you how to construct an
alienfile, but we will also briefly cover making a simple
\&\f(CW\*(C`Makefile.PL\*(C'\fR or \f(CW\*(C`dist.ini\*(C'\fR to go along with it.  We will also touch
on when you might want to extend your subclass to add non-standard
functionality.
.SS "Using commands"
.IX Subsection "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 \f(CW\*(C`pkg\-config\*(C'\fR \f(CW\*(C`.pc\*(C'\fR
file.
.PP
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.
.PP
(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).
.PP
(Aside2, \f(CW\*(C`pkg\-config\*(C'\fR 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 \f(CW\*(C`.pc\*(C'\fR file, usually in \f(CW\*(C`$PREFIX/lib/pkgconfig\*(C'\fR
then, your tool uses \f(CW\*(C`pkg\-config\*(C'\fR).
.PP
Here is the alienfile that you might have:
.PP
.Vb 1
\& use alienfile;
\& 
\& probe [ \*(Aqpkg\-config \-\-exists libfoo\*(Aq ];
\& 
\& share {
\& 
\&   start_url \*(Aqhttp://www.libfoo.org/src/libfoo\-1.00.tar.gz\*(Aq;
\& 
\&   download [ \*(Aqwget %{.meta.start_url}\*(Aq ];
\& 
\&   extract [ \*(Aqtar zxf %{.install.download}\*(Aq ];
\& 
\&   build [
\&     [ \*(Aq./configure \-\-prefix=%{.install.prefix} \-\-disable\-shared\*(Aq ],
\&     [ \*(Aq%{make}\*(Aq ],
\&     [ \*(Aq%{make} install\*(Aq ],
\&   ];
\& 
\& };
\& 
\& gather [
\&   [ \*(Aqpkg\-config \-\-modversion libfoo\*(Aq, \e\*(Aq%{.runtime.version}\*(Aq ],
\&   [ \*(Aqpkg\-config \-\-cflags     libfoo\*(Aq, \e\*(Aq%{.runtime.cflags}\*(Aq  ],
\&   [ \*(Aqpkg\-config \-\-libs       libfoo\*(Aq, \e\*(Aq%{.runtime.libs}\*(Aq    ],
\& ];
.Ve
.PP
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
.PP
.Vb 1
\& use alienfile;
.Ve
.PP
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.
.PP
The second line is the probe directive:
.PP
.Vb 1
\& probe [ \*(Aqpkg\-config \-\-exists libfoo\*(Aq ];
.Ve
.PP
is used to see if the library is already installed on the target system.
If \f(CW\*(C`pkg\-config\*(C'\fR 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 \f(CW\*(C`pkg\-config\*(C'\fR in the \s-1PATH,\s0 or if libfoo is not
installed, then it will exist with non-success (!= 0) and tells
Alien::Build to download and build from source.
.PP
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 \f(CW\*(C`.pc\*(C'\fR file for use with \f(CW\*(C`pkg\-config\*(C'\fR and
also provides a \f(CW\*(C`foo\-config\*(C'\fR program to find the same values.  You
could then specify this in your alienfile
.PP
.Vb 2
\& probe [ \*(Aqpkg\-config \-\-exists libfoo\*(Aq ];
\& probe [ \*(Aqfoo\-config \-\-version\*(Aq ];
.Ve
.PP
Other directives can be specified multiple times if there are different
methods that can be tried for the various steps.
.PP
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 \f(CW\*(C`pkg\-config\*(C'\fR would be from Perl:
.PP
.Vb 5
\& probe sub {
\&   my($build) = @_;  # $build is the Alien::Build instance.
\&   system \*(Aqpkg\-config \-\-exists libfoo\*(Aq;
\&   $? == 0 ? \*(Aqsystem\*(Aq : \*(Aqshare\*(Aq;
\& };
.Ve
.PP
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
\&\f(CW\*(C`die\*(C'\fR to indicate a failure.
.PP
The next part of the alienfile is the \f(CW\*(C`share\*(C'\fR 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.
.PP
.Vb 10
\& share {
\&   start_url \*(Aqhttp://www.libfoo.org/src/libfoo\-1.00.tar.gz\*(Aq;
\&   download [ \*(Aqwget %{.meta.start_url}\*(Aq ];
\&   extract [ \*(Aqtar zxf %{.install.download}\*(Aq ];
\&   build [
\&     [ \*(Aq./configure \-\-prefix=%{.install.prefix} \-\-disable\-shared\*(Aq ],
\&     [ \*(Aq%{make}\*(Aq ],
\&     [ \*(Aq%{make} install\*(Aq ],
\&   ];
\& };
.Ve
.PP
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
\&\s-1HTML\s0 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 \f(CW\*(C`%{.install.download}\*(C'\fR 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:
.PP
.Vb 12
\& share {
\&   ...
\&   requires \*(AqArchive::Extract\*(Aq;
\&   extract sub {
\&     my($build) = @_;
\&     my $tarball = $build\->install_prop\->{download};
\&     my $ae = Archive::Extract\->new( archive => $tarball );
\&     $ae\->extract;
\&     1;
\&   }
\&   ...
\& };
.Ve
.PP
The build directive specifies how to build the library or tool once it
has been downloaded and extracted.  Note the special variable
\&\f(CW\*(C`%{.install.prefix}\*(C'\fR is the location where the library should be
installed.  \f(CW\*(C`%{make}\*(C'\fR is a helper which will be replaced by the
appropriate \f(CW\*(C`make\*(C'\fR, which may be called something different on some
platforms (on Windows for example, it frequently may be called \f(CW\*(C`nmake\*(C'\fR
or \f(CW\*(C`dmake\*(C'\fR).
.PP
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 \f(CW\*(C`pkg\-config\*(C'\fR command:
.PP
.Vb 5
\& gather [
\&   [ \*(Aqpkg\-config \-\-modversion libfoo\*(Aq, \e\*(Aq%{.runtime.version}\*(Aq ],
\&   [ \*(Aqpkg\-config \-\-cflags     libfoo\*(Aq, \e\*(Aq%{.runtime.cflags}\*(Aq  ],
\&   [ \*(Aqpkg\-config \-\-libs       libfoo\*(Aq, \e\*(Aq%{.runtime.libs}\*(Aq    ],
\& ];
.Ve
.PP
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 \f(CW\*(C`Alien::Libfoo\*(C'\fR 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.
.PP
You can also provide a \f(CW\*(C`sys\*(C'\fR 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:
.PP
.Vb 8
\& build {
\&   ...
\&   gather [
\&     [ \*(Aqpkg\-config \-\-modversion libfoo\*(Aq, \e\*(Aq%{.runtime.version}\*(Aq ],
\&     [ \*(Aqpkg\-config \-\-cflags     libfoo\*(Aq, \e\*(Aq%{.runtime.cflags}\*(Aq  ],
\&     [ \*(Aqpkg\-config \-\-libs       libfoo\*(Aq, \e\*(Aq%{.runtime.libs}\*(Aq    ],
\&   ];
\& };
\& 
\& sys {
\&   gather [
\&     [ \*(Aqpkg\-config \-\-modversion libfoo\*(Aq, \e\*(Aq%{.runtime.version}\*(Aq ],
\&     [ \*(Aqpkg\-config \-\-cflags     libfoo\*(Aq, \e\*(Aq%{.runtime.cflags}\*(Aq  ],
\&     [ \*(Aqpkg\-config \-\-libs       libfoo\*(Aq, \e\*(Aq%{.runtime.libs}\*(Aq    ],
\&   ];
\& };
.Ve
.PP
(Aside3, the reason it is called \f(CW\*(C`sys\*(C'\fR and not \f(CW\*(C`system\*(C'\fR is so that it
does not conflict with the built in \f(CW\*(C`system\*(C'\fR function)!
.SS "Using plugins"
.IX Subsection "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 \f(CW\*(C`pkg\-config\*(C'\fR (which are quite common.
alienfile allows you to use plugins.  See Alien::Build::Plugin for
a list of some of the plugin categories.
.PP
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
.PP
.Vb 1
\& use alienfile;
\& 
\& plugin \*(AqPkgConfig\*(Aq => (
\&   pkg_name => \*(Aqlibfoo\*(Aq,
\& );
\& 
\& share {
\&   start_url \*(Aqhttp://www.libfoo.org/src\*(Aq;
\&   plugin \*(AqDownload\*(Aq => (
\&     filter => qr/^libfoo\-[0\-9\e.]+\e.tar\e.gz$/,
\&     version => qr/^libfoo\-([0\-9\e.]+)\e.tar\e.gz$/,
\&   );
\&   plugin \*(AqExtract\*(Aq => \*(Aqtar.gz\*(Aq;
\&   plugin \*(AqBuild::Autoconf\*(Aq;
\&   build [
\&     \*(Aq%{configure} \-\-disable\-shared\*(Aq,
\&     \*(Aq%{make}\*(Aq,
\&     \*(Aq%{make} install\*(Aq,
\&   ];
\& };
.Ve
.PP
The first plugin that we use is the \f(CW\*(C`pkg\-config\*(C'\fR 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 \f(CW\*(C`::Negotiate\*(C'\fR 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!
.PP
Next we use the download negotiation plugin.  This is also better than
the version above, because again, \f(CW\*(C`wget\*(C'\fR my not be installed on the
target system.  Also you can specify a \s-1URL\s0 which will be scanned for
links, and use the most recent version.
.PP
We use the Extract negotiation plugin to use either command line tools,
or Perl libraries to extract from the archive once it is downloaded.
.PP
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!
.PP
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.
.PP
.Vb 8
\& share {
\&   ...
\&   build [
\&     \*(Aq%{configure} \-\-enable\-bar \-\-enable\-baz \-\-disable\-shared\*(Aq,
\&     \*(Aq%{make}\*(Aq,
\&     \*(Aq%{make} install\*(Aq,
\&   ];
\& };
.Ve
.SS "Multiple .pc files"
.IX Subsection "Multiple .pc files"
Some packages come with multiple libraries paired with multiple \f(CW\*(C`.pc\*(C'\fR
files.  In this case you want to provide the
Alien::Build::Plugin::PkgConfig::Negotiate with an array reference
of package names.
.PP
.Vb 3
\& plugin \*(AqPkgConfig\*(Aq => (
\&   pkg_name => [ \*(Aqfoo\*(Aq, \*(Aqbar\*(Aq, \*(Aqbaz\*(Aq ],
\& );
.Ve
.PP
All packages must be found in order for the \f(CW\*(C`system\*(C'\fR install to succeed.
Once installed the first \f(CW\*(C`pkg_name\*(C'\fR will be used by default (in this
example \f(CW\*(C`foo\*(C'\fR), and you can retrieve any other \f(CW\*(C`pkg_name\*(C'\fR using
the Alien::Base alt method.
.SS "A note about dynamic vs. static libraries"
.IX Subsection "A note about dynamic vs. static libraries"
If you are using your Alien to build an \s-1XS\s0 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.
.PP
Actually let me back up a minute.  For a \f(CW\*(C`share\*(C'\fR install it is best
to use static libraries to build your \s-1XS\s0 extension.  This is because
if your Alien is ever upgraded to a new version it can break your
existing \s-1XS\s0 modules.  For a \f(CW\*(C`system\*(C'\fR install shared libraries are
usually best because you can often get security patches without having
to re-build anything in perl land.
.PP
If you looked closely at the \*(L"Using commands\*(R" and \*(L"Using plugins\*(R"
sections above, you may notice that we went out of our way where
possible to tell Autotools to build only static libraries using the
\&\f(CW\*(C`\-\-disable\-shared\*(C'\fR command.  The Autoconf plugin also does this by
default.
.PP
Sometimes though you will have a package that builds both, or maybe
you \fIwant\fR both static and dynamic libraries to work with \s-1XS\s0 and \s-1FFI.\s0
For that case, there is the Alien::Build::Plugin::Gather::IsolateDynamic
plugin.
.PP
.Vb 3
\& use alienfile;
\& ...
\& plugin \*(AqGather::IsolateDynamic\*(Aq;
.Ve
.PP
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 \s-1FFI,\s0
and where they won't be used by the compiler for building \s-1XS.\s0  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.
.PP
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 \f(CW\*(C`clean_install\*(C'\fR property on Alien::Build::MM, which will
clean out the share directory on upgrade, and possibly save you a lot
of grief.
.SS "Verifying and debugging your alienfile"
.IX Subsection "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 \f(CW\*(C`af\*(C'\fR command (it does not come with Alien::Build, you need
to install App::af).  By default \f(CW\*(C`af\*(C'\fR will use the \f(CW\*(C`alienfile\*(C'\fR in
the current directory (just as \f(CW\*(C`make\*(C'\fR uses the \f(CW\*(C`Makefile\*(C'\fR in the
current directory; just like \f(CW\*(C`make\*(C'\fR you can use the \f(CW\*(C`\-f\*(C'\fR option to
specify a different alienfile).
.PP
You can test your alienfile in dry run mode:
.PP
.Vb 10
\& % 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: \*(Aq\*(Aq
\& cflags_static: \*(Aq\*(Aq
\& install_type: system
\& legacy:
\&   finished_installing: 1
\&   install_type: system
\&   name: libfoo
\&   original_prefix: /tmp/7RtAusykNN
\&   version: 1.2.3
\& libs: \*(Aq\-lfoo \*(Aq
\& libs_static: \*(Aq\-lfoo \*(Aq
\& prefix: /tmp/7RtAusykNN
\& version: 1.2.3
.Ve
.PP
You can use the \f(CW\*(C`\-\-type\*(C'\fR option to force a share install (download and
build from source):
.PP
.Vb 10
\& % 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: \*(Aq\*(Aq
\& cflags_static: \*(Aq\*(Aq
\& install_type: share
\& legacy:
\&   finished_installing: 1
\&   install_type: share
\&   original_prefix: /tmp/P22WEXj80r
\&   version: 1.2.4
\& libs: \*(Aq\-L/tmp/P22WEXj80r/lib \-lfoo \*(Aq
\& libs_static: \*(Aq\-L/tmp/P22WEXj80r/lib \-lfoo \*(Aq
\& prefix: /tmp/P22WEXj80r
\& version: 1.2.4
.Ve
.PP
You can also use the \f(CW\*(C`\-\-before\*(C'\fR and \f(CW\*(C`\-\-after\*(C'\fR options to take a peek
at what the build environment looks like at different stages as well,
which can sometimes be useful:
.PP
.Vb 10
\& % 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$
.Ve
.PP
There are a lot of other useful things that you can do with the \f(CW\*(C`af\*(C'\fR
command.  See af for details.
.SS "Integrating with MakeMaker"
.IX Subsection "Integrating with MakeMaker"
Once you have a working alienfile you can write your \f(CW\*(C`Makefile.PL\*(C'\fR.
.PP
.Vb 2
\& use ExtUtils::MakeMaker;
\& use Alien::Build::MM;
\& 
\& my $abmm = Alien::Build::MM\->new;
\& 
\& WriteMakefile($abmm\->mm_args(
\&   ABSTRACT           => \*(AqDiscover or download and install libfoo\*(Aq,
\&   DISTNAME           => \*(AqAlien\-Libfoo\*(Aq,
\&   NAME               => \*(AqAlien::Libfoo\*(Aq,
\&   VERSION_FROM       => \*(Aqlib/Alien/Libfoo.pm\*(Aq,
\&   CONFIGURE_REQUIRES => {
\&     \*(AqAlien::Build::MM\*(Aq => 0,
\&   },
\&   BUILD_REQUIRES => {
\&     \*(AqAlien::Build::MM\*(Aq => 0,
\&   },
\&   PREREQ_PM => {
\&     \*(AqAlien::Base\*(Aq => 0,
\&   },
\&   # If you are going to write the recommended
\&   # tests you will will want these:
\&   TEST_REQUIRES => {
\&     \*(AqTest::Alien\*(Aq => 0,
\&     \*(AqTest2::V0\*(Aq   => 0,
\&   },
\& ));
\& 
\& sub MY::postamble {
\&   $abmm\->mm_postamble;
\& }
.Ve
.PP
The \f(CW\*(C`lib/Alien/Libfoo.pm\*(C'\fR that goes along with it is very simple:
.PP
.Vb 1
\& package Alien::Libfoo;
\& 
\& use strict;
\& use warnings;
\& use parent qw( Alien::Base );
\& 
\& 1;
.Ve
.PP
You are done and can install it normally:
.PP
.Vb 4
\& % perl Makefile.PL
\& % make
\& % make test
\& % make install
.Ve
.SS "Integrating with Module::Build"
.IX Subsection "Integrating with Module::Build"
Please don't!  Okay if you have to there is Alien::Build::MB.
.SS "Non standard configuration"
.IX Subsection "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:
.PP
.Vb 8
\& gather [
\&   # standard:
\&   [ \*(Aqfoo\-config \-\-version libfoo\*(Aq, \e\*(Aq%{.runtime.version}\*(Aq ],
\&   [ \*(Aqfoo\-config \-\-cflags  libfoo\*(Aq, \e\*(Aq%{.runtime.cflags}\*(Aq  ],
\&   [ \*(Aqfoo\-config \-\-libs    libfoo\*(Aq, \e\*(Aq%{.runtime.libs}\*(Aq    ],
\&   # non\-standard
\&   [ \*(Aqfoo\-config \-\-bar\-baz libfoo\*(Aq, \e\*(Aq%{.runtime.bar_baz}\*(Aq ],
\& ];
.Ve
.PP
then you can expose them in your Alien::Base subclass:
.PP
.Vb 1
\& package Alien::Libfoo;
\& 
\& use strict;
\& use warnings;
\& use parent qw( Alien::Base );
\& 
\& sub bar_baz {
\&   my($self) = @_;
\&   $self\->runtime_prop\->{bar_baz},
\& };
\& 
\& 1;
.Ve
.SS "Testing"
.IX Subsection "Testing"
(optional, but highly recommended)
.PP
You should write a test using Test::Alien to make sure that your
alien will work with any \s-1XS\s0 modules that are going to use it:
.PP
.Vb 3
\& use Test2::V0;
\& use Test::Alien;
\& use Alien::Libfoo;
\& 
\& alien_ok \*(AqAlien::Libfoo\*(Aq;
\& 
\& xs_ok do { local $/; <DATA> }, with_subtest {
\&   is Foo::something(), 1, \*(AqFoo::something() returns 1\*(Aq;
\& };
\& 
\& done_testing;
\& 
\& _\|_DATA_\|_
\& #include "EXTERN.h"
\& #include "perl.h"
\& #include "XSUB.h"
\& #include <foo.h>
\& 
\& MODULE = Foo PACKAGE = Foo
\& 
\& int something()
.Ve
.PP
You can also use Test::Alien to test tools instead of libraries:
.PP
.Vb 3
\& use Test2::V0;
\& use Test::Alien;
\& use Alien::Libfoo;
\& 
\& alien_ok \*(AqAlien::Libfoo\*(Aq;
\& run_ok([\*(Aqfoo\*(Aq, \*(Aq\-\-version\*(Aq])
\&   \->exit_is(0);
\& 
\& done_testing;
.Ve
.PP
You can also write tests specifically for FFI::Platypus, if your
alien is going to be used to write \s-1FFI\s0 bindings.  (the test below
is the \s-1FFI\s0 equivalent to the \s-1XS\s0 example above).
.PP
.Vb 3
\& use Test2::V0;
\& use Test::Alien;
\& use Alien::Libfoo;
\& 
\& alien_ok \*(AqAlien::Libfoo\*(Aq;
\& ffi_ok { symbols => [ \*(Aqsomething\*(Aq ] }, with_subtest {
\&   # $ffi is an instance of FFI::Platypus with the lib
\&   # set appropriately.
\&   my($ffi) = @_;
\&   my $something = $ffi\->function( something => [] => \*(Aqint\*(Aq );
\&   is $something\->call(), 1, \*(AqFoo::something() returns 1\*(Aq;
\& };
.Ve
.PP
If you do use \f(CW\*(C`ffi_ok\*(C'\fR 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 \f(CW\*(C`dynamic_libs\*(C'\fR doesn't return an empty list.
.PP
.Vb 9
\& ...
\& alien_ok \*(AqAlien::Libfoo\*(Aq;
\& SKIP: {
\&   skip "This test requires a dynamic library"
\&     unless Alien::Libfoo\->dynamic_libs;
\&   ffi_ok { symbols [ \*(Aqsomething\*(Aq ] }, with_subtest {
\&     ...
\&   };
\& }
.Ve
.PP
More details on testing Alien modules can be found in the
Test::Alien documentation.
.PP
You can also run the tests that come with the package that you are alienizing,
by using a \f(CW\*(C`test\*(C'\fR 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 \f(CW\*(C`make check\*(C'\fR command:
.PP
.Vb 1
\& use alienfile;
\& 
\& plugin \*(AqPkgConfig\*(Aq => \*(Aqlibfoo\*(Aq;
\& 
\& share {
\&   ... # standard build steps.
\&   test [ \*(Aq%{make} check\*(Aq ];
\& };
.Ve
.SS "Dist::Zilla"
.IX Subsection "Dist::Zilla"
(optional, mildly recommended)
.PP
You can also use the Alien::Build Dist::Zilla plugin
Dist::Zilla::Plugin::AlienBuild:
.PP
.Vb 6
\& 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]
.Ve
.PP
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.
.SS "Using your Alien"
.IX Subsection "Using your Alien"
Once you have installed you can use your Alien.  See
Alien::Build::Manual::AlienUser for guidance on that.
.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