Alien-Base-ModuleBuild
view release on metacpan or search on metacpan
lib/Alien/Base/ModuleBuild/FAQ.pod view on Meta::CPAN
# ABSTRACT: Frequently Asked Questions about Alien::Base::ModuleBuild
# PODNAME: Alien::Base::ModuleBuild::FAQ
# VERSION
__END__
=pod
=encoding UTF-8
=head1 NAME
Alien::Base::ModuleBuild::FAQ - Frequently Asked Questions about Alien::Base::ModuleBuild
=head1 VERSION
version 1.17
=head1 SYNOPSIS
perldoc Alien::Base::FAQ
=head1 DESCRIPTION
B<NOTE>: Please consider for new development of L<Alien>s that you use
L<Alien::Build> and L<alienfile> instead. Like L<Alien::Base::ModuleBuild> they work
with L<Alien::Base>. Unlike L<Alien::Base::ModuleBuild> they are more easily customized
and handle a number of corner cases better. For a good place to start,
please see L<Alien::Base::ModuleBuild::API>. Although the
Alien-Base / Alien-Build team will continue to maintain this module,
(we will continue to fix bugs where appropriate), we aren't adding any
new features to this module.
This document serves to answer the most frequently asked questions made by L<Alien::Base> authors.
=head2 What is Alien and Alien::Base?
Alien is a Perl namespace for defining dependencies in CPAN for libraries and tools which are not "native"
to CPAN. For a manifesto style description of the Why, and How see L<Alien>. L<Alien::Base> is a base
class and framework for creating Alien distributions. The idea is to address as many of the common challenges
to developing Alien modules in the base class to simplify the process.
=head2 How do I specify a minimum or exact version requirement for packages that use pkg-config?
The C<alien_version_check> attribute to L<Alien::Base::ModuleBuild> will be executed to determine if
the library is provided by the operating system. The default for this is C<%{pkg_config} --modversion %n>
which simply checks to see if any version of that package is available, and prints the version
number. You can use the C<--atleast-version>, C<--exact-version> options to require a specific range of versions,
but these flags do not work with the C<--modversion> flag, so be sure to invoke separately.
use Alien::Base::ModuleBuild;
Alien::Base::ModuleBuild->new(
dist_name => 'Alien::Foo',
alien_name => 'foo',
configure_requires => { 'Alien::Base::ModuleBuild' => '0.022' }, # required for %{pkg_config}
alien_version_check => '%{pkg_config} --atleast-version 1.2.3 %n && %{pkg_config} --modversion %n',
...
)->create_build_script;
It is better to use the built in C<%{pkg_config}> helper as it will use the system provided pkg-config
if it is available and fallback on the pure perl L<PkgConfig> if not.
You can also use C<--exact-version> to specify an exact version.
=head2 How to create an Alien module for packages that do not support pkg-config?
Although L<Alien::Base> and L<Alien::Base::ModuleBuild> assume packages come with a C<pkg-config>
C<.pc> file to determine compiler and linker flags by default, you can implement an Alien module
for packages that do use C<pkg-config> by following these tasks:
=over 4
=item subclass L<Alien::Base::ModuleBuild> and implement C<alien_check_installed_version>
Create a subclass of L<Alien::Base::ModuleBuild> and put it in the C<inc> directory of your distribution so
that it can be used during install but won't I<be installed>.
# inc/My/ModuleBuild.pm
package My::ModuleBuild;
use parent 'Alien::Base::ModuleBuild';
sub alien_check_installed_version {
my($class) = @_;
# determine if your library is already provided by the system
my $version = ...;
# return false if the library is NOT provided by the system
return unless defined $version;
# otherwise return the version detected
# (if you cannot determine the version it
# is usually sufficient to return a true value)
return $version;
}
There are number of methods you can use to determine if the system provides your library. From Perl
methods include L<Devel::CheckLib>, L<ExtUtils::CBuilder>, L<ExtUtils::CChecker>, L<Config::AutoConf>,
L<FFI::CheckLib> among others. It is also frequently possible to determine if a library is installed
using a C<-config> suffixed program. For example C<libxml2> comes with xml2-config which provides the
existence, compiler and linker flags it needs. In my experience, however, most packages that provide a
C<-config> suffixed program also provide a C<pkg-config> interface as well.
=item implement C<alien_check_built_version> in your L<Alien::Base::ModuleBuild> subclass
You should also implement C<alien_check_build_version> which will be executed from the package build
root once the package is successfully built.
# inc/My/ModuleBuild.pm
package My::ModuleBuild;
...
sub alien_check_built_version {
my($self) = @_;
my $version = ...
# (Again, if you cannot determine the version,
# it is usually sufficent to return a true value)
return $version;
}
=item set C<alien_provides_cflags> and C<alien_provides_libs> in C<Build.PL>.
Add something like this to your C<Build.PL>:
# Build.PL
use lib 'inc';
use My::ModuleBuild;
My::ModuleBuild->new(
...
alien_provides_cflags => '-I/usr/include/foo',
alien_provides_libs => '-L/usr/lib/foo -lfoo',
...
);
Note that it is frequently sufficient to provide C<alien_provides_libs> and the appropriate C<-l> flag.
These flags will be used in the event that the system package can be found. It is a good idea to verify
that these flags do indeed work in C<alien_check_installed_version> above.
=back
For a fully implemented example, see L<Alien::Libbz2>.
=head2 How do I test my package once it is built (before it is installed)?
There are many ways to test Alien modules before (or after) they are installed, but instead
of rolling your own, consider using L<Test::Alien> which is light on dependencies and will
test your module very closely to the way that it will actually be used. That is to say by
building a mini XS or FFI extension and using it. It even has tests for tool oriented Alien
distributions (like L<Alien::gmake> and L<Alien::patch>). Here is a short example, there
are many others included with the L<Test::Alien> documentation:
use Test2::V0;
use Test::Alien 0.05;
use Alien::Editline;
alien_ok 'Alien::Editline';
my $xs = do { local $/; <DATA> };
xs_ok $xs, with_subtest {
my($module) = @_;
ok $module->version;
};
done_testing;
__DATA__
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <editline/readline.h>
/* having a string parameter that we ignore
allows us to call this as a class method */
const char *
version(const char *class)
{
return rl_library_version;
}
MODULE = TA_MODULE PACKAGE = TA_MODULE
const char *version(class);
const char *class;
=head2 How do I patch packages that need minor (or major) alterations?
One approach is to create a unified diff for patches that you want to apply and simply run patch on them. The
L<Alien::patch> and the C<%{patch}> helper can be used like this:
# Build.PL
use Alien::Base::ModuleBuild;
Alien::Base::ModuleBuild->new(
...
alien_bin_requires => {
'Alien::patch' => 0.06, # needed for %{patch} helper
},
lib/Alien/Base/ModuleBuild/FAQ.pod view on Meta::CPAN
Create a folder in your distribution root called C<patch> and place the C<mypackage.patch> file in there. Since
the C<patch> command will be executed in the package root instead of the distribution root, you need to use a
relative path prefixed by C<../..>. Here we use L<Alien::patch> to provide patch even in environments where it
is not provided.
A more powerful approach to patching is to write a perl subroutine to modify the source after it has been
extracted. One way to do this is to create a module in your distribution's inc directory that does the
patching (modules in inc can be used during build/test but won't be installed):
# inc/My/AlienPatch.pm
package My::AlienPatch;
# add this sub to the main namespace
# so we don't need to quote or escape
# anything below
sub main::alien_patch {
# is executed in the package root,
# make what ever changes you need to
# to the source here.
}
1;
# Build.PL
use Alien::Base::ModuleBuild;
Alien::Base::ModuleBuild->new(
...
alien_build_commands => [
# %x will be replaced by path for calling Perl
# from the command line
"%x -I../../inc -MMy::AlienPatch -e alien_patch",
...
],
...
)->create_build_script;
=head2 How do I build a package that uses I<build system>?
=head3 autoconf
By default L<Alien::Base::ModuleBuild> assumes a package with an autoconf style C<configure> script. The
default is
# Build.PL
use Alien::Base::ModuleBuild;
Alien::Base::ModuleBuild->new(
...
alien_build_commands => [
'%c --prefix=%s',
'make',
],
alien_install_commands => [
'make install',
],
...
)->create_build_script;
There are a couple of short cuts here, C<%c> indicates the platform independent method for executing the
C<configure> script, plus any normal autoconf flags that are appropriate for Perl Alien libraries. The C<%c>
also tells L<Alien::Base::ModuleBuild> to use L<Alien::MSYS> on Windows platforms and to add that as a
dependency. The C<%s> is a placeholder for the location to which the package will be installed. This is
normally in a share directory specific to your distribution.
=head3 autoconf-like
If you see an error like this:
Unknown option "--with-pic".
It may be because your package provides a C<configure> script that provides an autoconf-style interface, but is
not actually autoconf. L<Alien::Base::ModuleBuild> is aggressive in using the C<--with-pic> option because when
supported by autoconf it produces position independent code (important for reliably building XS extensions), and
when not supported autoconf simply ignores the option. Unfortunately some autoconf-style C<configure> scripts
consider it an error when they see options that they do not recognize. You can tell L<Alien::Base::ModuleBuild>
to not use the C<--with-pic> option via the C<alien_autoconf_with_pic> property:
# Build.PL
use Alien::Base::ModuleBuild;
Alien::Base::ModuleBuild->new(
...
alien_autoconf_with_pic => 0,
...
)->create_build_script;
=head3 CMAKE
You probably cannot count on CMake being available on most platforms. Fortunately, there is an alien
distribution L<Alien::CMake> which will either use the CMake provided by the operating system, or download and
install it for you. You can use this from your C<Build.PL> with the C<alien_bin_requires> property:
# Build.PL
use Alien::Base::ModuleBuild;
use Config;
Alien::Base::ModuleBuild->new(
...
alien_bin_requires => {
'Alien::CMake' => 0.07,
},
alien_build_commands => [
# acutal required arguments may vary
"cmake -G 'Unix Makefiles' -DCMAKE_MAKE_PROGRAM=$Config{make} -DCMAKE_INSTALL_PREFIX:PATH=%s",
"$Config{make}",
],
alien_install_commands => [
"$Config{make} install",
],
...
)->create_build_script;
=head3 vanilla Makefiles?
If you want to use the same C<make> as Perl, you can use L<Config>:
# Build.PL
use Alien::Base::ModuleBuild;
use Config;
Alien::Base::ModuleBuild->new(
...
alien_build_commands => [
( run in 1.175 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )