Base classes for Alien builder modules
Create a simple instance:
use Alien::Builder;
my $ab = Alien::Builder->new(
name => 'foo',
retreiver_start => 'http://example.com/dist',
retriever_spec => [
{ pattern => qr{^libfoo-(([0-9]\.)*[0-9]+)\.tar\.gz$} },
],
# these are the default command lists
build_commands => [ '%c --prefix=%s', 'make' ],
install_commands => [ 'make install' ],
);
Install standalone:
use Alien::Builder;
my $ab = Alien::Builder->new(
# same as above
);
$ab->action_download
->action_extract
->action_build
->action_test
->action_install;
Deploy with ExtUtils::MakeMaker (see Alien::Builder::MM for more details):
use ExtUtils::MakeMaker;
use Alien::Builder::MM;
my $ab = Alien::Builder::MM->new(
# same as above
);
WriteMakefile(
$ab->mm_args(
NAME => 'Alien::Foo',
VERSION_FROM => 'Alien::Foo'
),
);
sub MY::postamble {
$ab->mm_postamble;
}
Deploy with Dist::Zilla:
[AlienBuilder]
name = foo
retreiver_start = http://ftp.example.com/dist/
retriever_spec.0.pattern = ^foo-(([0-9]+\.)*[0-9]+)\.tar\.gz$
build_commands = %c --prefix=%s
build_commands = make
install_commands = make install
Deploy with Module::Build, see Alien::Base::ModuleBuild.
WARNING: this interface is EXPERIMENTAL. If you need something stable right now, use Alien::Base::ModuleBuild.
The purpose of this class is to provide a generic builder/installer that can be used by ExtUtils::MakeMaker and Module::Build derivatives for creating Alien distributions. Basically this class provides the generic machinery used during the configure and build stages, and Alien::Base can be used at runtime once the Alien module is already installed. It could also be used independently of an installer to install a library.
The design goals of this library are to make the "easy" things easy, and hard things possible. For this discussion, "easy" means build and install libraries that use the standard GNU style autotools, or generic Makefiles. Harder things may require writing Perl code, and you can accomplish this by subclassing Alien::Builder.
my $builder = Alien::Builder->new(%properties);
Create a new instance of Alien::Builder.
At the minimum you will want to define a "retriever" specification. Unless your tool or library uses GNU autotools style interface (that is it is installed with something like "./configure && make && make install") you will need to also provide build and install commands with the "build_commands" and "install_commands" properties. Depending on the complexity of your tool or library you may need to specify additional properties.
Properties are read-only and can only be specified when passing them into "new" as arguments. They can be accessed after the Alien::Builder object is created using accessor methods of the same name.
my $builder = Alien::Builder->new( arch => 1 );
$builder->arch; # is 1
Install module into an architecture specific directory. This is off by
default, unless $ENV{ALIEN_ARCH}
is true. Most Alien distributions
will be installing binary code. If you are an integrator where the
@INC
path is shared by multiple Perls in a non-homogeneous
environment you can set $ENV{ALIEN_ARCH}
to 1 and Alien modules will
be installed in architecture specific directories.
Add --with-pic
option to autoconf style configure script when called.
This is the default, and normally a good practice. Normally autoconf
will ignore this and any other options that it does not recognize, but
some non-autoconf configure
scripts may complain.
Hash reference of modules (keys) and versions (values) that specifies
Alien modules that provide binary tools that are required to build.
Any Alien::Base that includes binaries should work. Also supported
are Alien::MSYS, Alien::CMake, Alien::TinyCC and
Alien::Autotools. These become build time requirements for your
module if Alien::Builder determines that a source code build is
required.
An array reference of commands used to build the library in the
directory specified in "build_dir". Each command is first passed
through the command interpolation engine, so
any variable or helper provided may be used. The default is tailored to
the GNU toolchain (that is autoconf and make
); it is
[ '%c --prefix=%s', 'make' ]
. Each command may be either a string or
an array reference. If the array reference form is used then the
multiple argument form of system is used.
The name of the folder which will house the library where it is
downloaded and built. The default name is _alien
.
If set to true (the default is false), do a "double staged destdir" install.
TODO: needs FAQ
Environment overrides. Allows you to set environment variables as a
hash reference that will override environment variables. You can use
the same interpolated escape sequences and helpers that commands use.
Set to undef
to remove the environment variable.
Alien::Builder->new(
env => {
PERL => '%X', # sets the environment variable PERL to the location
# of the Perl interpreter.
PERCENT => '%%', # evaluates to '%'
REMOVE => undef, # remove the environment variable if it is defined
},
);
Please keep in mind that frequently users have a good reason to have set environment variables, and you should not override them without a good reason. An example of a good justification would be if a project has a Makefile that interacts badly with common environment variables. This can sometimes be a problem since Makefile variables can be overridden with environment variables.
A useful pattern is to use a helper to only override an environment variable if it is not already set.
Alien::Builder->new(
helper => {
foo => '$ENV{FOO}||"my preferred value if not already set"',
},
env => {
FOO => '%{foo}',
},
);
A common pitfall with environment variables is that setting one to the empty string ('') is not portable. On Unix it works fine as you would expect, but in Windows it actually unsets the environment variable, which may not be what you intend.
Alien::Builder->new(
env => {
FOO => '', # is allowed, but may not do what you intend on some platforms!
},
);
$ENV{FOO} = ''; # same issue.
The extractor class. This is Alien::Builder::Extractor::Plugin::ArchiveTar by default.
The name of the shared library for use with FFI. Provided for
situations where the shared library name cannot be determined from the
pkg-config
name specified as "name". For example, libxml2
has a
pkg-config
name of libxml-2.0
, but a shared library name of
xml2
. By default "name" is used with any lib
prefix removed.
For example if you specify a "name" of libarchive
, "ffi_name"
will be archive
.
Provide helpers to generate commands or arguments at build or install time. This property is a hash reference. The keys are the helper names and the values are strings containing Perl code that will be evaluated and interpolated into the command before execution. Because helpers are only needed when building a package from the source code, any dependency may be specified as an "bin_requires". For example:
Alien::Builder->new(
bin_requires => {
'Alien::foo' => 0,
},
helper => {
'foocommand' => 'Alien::foo->some_command',
'fooargument' => 'Alien::foo->some_argument',
},
build_commands => [
'%{foocommand} %{fooargument}',
],
);
One helper that you get for free is %{pkg_config}
, which will be the
pkg-config
implementation chosen by Alien::Builder. This will
either be the "real" pkg-config
provided by the operating system
(preferred), or PkgConfig, the pure perl implementation found on
CPAN.
Array reference containing the list of header files to be used automatically by Inline::C and Inline::CPP.
An array reference of commands used to install the library in the
directory specified in "build_dir". Each command is first passed
through the command interpolation engine, so
any variable or helper provided may be used. The default is tailored to
the GNU toolchain (that is autoconf and make
); it is
[ 'make install' ]
. Each command may be either a string or an array
reference. If the array reference form is used then the multiple
argument form of system is used.
The interpolator class. This is Alien::Builder::Interpolator::Default by default.
If set to true (the default), then dynamic libraries will be moved from
the lib directory to a separate dynamic directory. This makes them
available for FFI modules (such as FFI::Platypus, or FFI::Raw),
while preferring static libraries when creating XS
extensions.
On windows wrap build and install commands in an MSYS
environment using
Alien::MSYS. This option will automatically add Alien::MSYS as a build
requirement when building on Windows.
The name of the primary library which will be provided. This should be
in the form to be passed to pkg-config
.
The install prefix to use. If you are using one of the MakeMaker or Module::Build interfaces, then this will likely be specified for you.
These parameters, if specified, augment the information found by
pkg-config
. If no package config data is found, these are used to
generate the necessary information. In that case, if these are not
specified, they are attempted to be created from found shared-object
files and header files. They both are empty by default.
The class used to do the actual retrieval. This allows you to write your own custom retriever if the build in version does not provide enough functionality.
An array reference that specifies the retrieval of your libraries archive. This is a sequence of one or more selection specifications. For example for a simple directory that contains multiple tarballs:
# finds the newest version of http://example.com/dist/libfoo-$VERSION.tar.gz
my $builder = Alien::Builder->new(
retriever_start => 'http://example.com',
retriever_spec => [
{ pattern => qr{^libfoo-[0-9]+\.[0-9]+\.tar\.gz$} },
],
);
If you have multiple directory hierarchy, you can handle this by extra selection specifications:
# finds the newest version of http://example.com/dist/$VERSION/libfoo-$VERSION.tar.gz
my $builder = Alien::Builder->new(
retriever_start => 'http://example.com',
retriever_spec => [
{ pattern => qr{^v[0-9]+$} },
{ pattern => qr{^libfoo-[0-9]+\.[0-9]+\.tar\.gz$} },
],
);
URL or hash reference to indicate the start of the retrieval process.
An array reference of commands used to test the library in the directory
specified in "build_dir". Each command is first passed through the
command interpolation engine, so any variable
or helper provided may be used. The default is not to run any tests; it
is []
. Each command may be either a string or an array reference. If
the array reference form is used then the multiple argument form of
system is used.
A command to run to check the version of the library installed on the
system. The default is pkg-config --modversion %n
.
$builder->action_download;
Action that downloads the archive.
$builder->action_extract;
Action that extracts the archive.
$builder->action_build;
Action that builds the library. Executes commands as specified by "build_commands".
$builder->action_test;
Action that tests the library. Executes commands as specified by "test_commands".
$builder->action_install;
Action that installs the library. Executes commands as specified by "install_commands".
$builder->action_fake;
Action that prints the commands that would be executed during the build, test and install stages.
my $hash = $builder->alien_build_requires
Returns hash of build requirements.
my $version = $builder->alien_check_installed_version;
This function determines if the library is already installed as part of the operating system, and returns the version as a string. If it can't be detected then it should return empty list.
The default implementation relies on pkg-config
, but you will
probably want to override this with your own implementation if the
package you are building does not use pkg-config
.
my $version = $builder->alien_check_built_version;
This function determines the version of the library after it has been built from source. This function only gets called if the operating system version can not be found and the package is successfully built.
The default implementation relies on pkg-config
, and other heuristics,
but you will probably want to override this with your own implementation
if the package you are building does not use pkg-config
.
When this method is called, the current working directory will be the build root.
If you see an error message like this:
Library looks like it installed, but no version was determined
After the package is built from source code then you probably need to provide an implementation for this method.
my %result = $builder->alien_do_system($cmd);
my %result = $builder->alien_do_system(@cmd);
Executes the given command using either the single argument or multiple argument form. Before executing the command, it will be interpolated using the command interpolation engine.
Returns a set of key value pairs including stdout
, stderr
,
success
and command
.
$builder->save;
Saves the state information of that Alien::Builder instance.
my $builder = Alien::Builder->restore;
Restores an Alien::Builder instance from the state information saved by "save".
Setting this changes the default for "arch" above. If the module
specifies its own "arch" then it will override this setting. Typically
installing into an architecture specific directory is what you want to
do, since most Alien::Base based distributions provide architecture
specific binary code, so you should consider carefully before installing
modules with this environment variable set to 0
. This may be useful
for integrators creating a single non-architecture specific RPM
,
.dep
or similar package. In this case the integrator should ensure
that the Alien package be installed with a system install_type and use
the system package.
Setting to share
will ignore a system-wide installation and build a
local version of the library. Setting to system
will only use a
system-wide installation and die if it cannot be found.
Before Alien::Builder executes system commands, or applies environment overrides, it replaces a few special escape sequences with useful data. This is needed especially for referencing the full path to the appropriate install location before the path is known. The available sequences are:
-
%{helper}
Evaluate the given helper, as provided by either the "helper" or "bin_requires" property. See Alien::Base#alien_helper.
-
%c
Platform independent incantation for running autoconf
configure
script. On Unix systems this is./configure
, on Windows this issh configure
. On windows Alien::MSYS is injected as a dependency and all commands are executed in aMSYS
environment. -
%n
Shortcut for the name stored in "name". The default is:
pkg-config --modversion %n
-
%s
The full path to the final installed location of the share directory. This is where the library should install itself; for autoconf style installs, this will look like
--prefix=%s
. -
%v
Captured version of the original archive.
-
%x
The current Perl interpreter (similar to
$^X
). -
%X
The current Perl interpreter using the Unix style path separator
/
instead of native Windows\
. -
%%
A literal
%
.
-
Runtime access to configuration determined by Alien::Builder and build time.
-
The original Alien manifesto.
Author: Graham Ollis <plicease@cpan.org>
Contributors:
David Mertens (run4flat)
Mark Nunberg (mordy, mnunberg)
Christian Walde (Mithaldu)
Brian Wightman (MidLifeXis)
Graham Ollis (plicease)
Zaki Mughal (zmughal)
mohawk2
Vikas N Kumar (vikasnkumar)
Flavio Poletti (polettix)
This software is copyright (c) 2016 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.