Spade
Mini Shell
# PODNAME: Alien::Build::Manual::FAQ
# ABSTRACT: Frequently Asked Questions about Alien::Build
# VERSION
__END__
=pod
=encoding UTF-8
=head1 NAME
Alien::Build::Manual::FAQ - Frequently Asked Questions about Alien::Build
=head1 VERSION
version 2.33
=head1 SYNOPSIS
perldoc Alien::Build::Manual::FAQ
=head1 DESCRIPTION
This document serves to answer the most frequently asked questions made by
developers
creating L<Alien> modules using L<Alien::Build>.
=head1 QUESTIONS
=head2 What is Alien, Alien::Base and Alien::Build?
Alien in 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 for the
L<Alien> runtime. L<Alien::Build> is
a tool for probing the operating system for existing libraries and tools,
and downloading, building
and installing packages. L<alienfile> is a recipe format for
describing how to probe,
download, build and install a package.
=head2 How do I build a package that uses I<build system>
=head3 autoconf
Use the autoconf plugin (L<Alien::Build::Plugin::Build::Autoconf>).
If your package
provides a pkg-config C<.pc> file, then you can also use the
PkgConfig plugin
(L<Alien::Build::Plugin::PkgConfig::Negotiate>).
use alienfile
plugin PkgConfig => 'libfoo';
share {
start_url => 'http://example.org/dist';
plugin Download => (
version => qr/libfoo-([0-9\.])\.tar\.gz$/,
);
plugin Extract => 'tar.gz';
plugin 'Build::Autoconf';
};
If you need to provide custom flags to configure, you can do that too:
share {
plugin 'Build::Autoconf';
build [
'%{configure} --disable-shared --enable-foo',
'%{make}',
'%{make} install',
];
};
If your package requires GNU Make, use C<%{gmake}> instead of
C<%{make}>.
=head3 autoconf-like
If you see an error like this:
Unknown option "--with-pic".
It is because the autoconf plugin uses the C<--with-pic> option by
default, since
it makes sense most of the time, and autoconf usually ignores options that
it does
not recognize. Some autoconf style build systems fail when they see an
option that
they do not recognize. You can turn this behavior off for these packages:
plugin 'Build::Autoconf' => (
with_pic => 0,
);
Another thing about the autoconf plugin is that it uses C<DESTDIR> to
do a double
staged install. If you see an error like "nothing was installed into
destdir", that
means that your package does not support C<DESTDIR>. You should
instead use the
MSYS plugin and use a command sequence to do the build like this:
share {
plugin 'Build::MSYS';
build [
# explicitly running configure with "sh" will make sure that
# it works on windows as well as UNIX.
'sh configure --prefix=%{.install.prefix} --disable-shared',
'%{make}',
'%{make} install',
];
};
=head3 CMake
There is an alien L<Alien::cmake3> that provides C<cmake> 3.x
or better (It is preferred to the
older L<Alien::CMake>). Though it is recommended that you use the
C<cmake>
(L<Alien::Build::Plugin::Build::CMake>) plugin instead of using
L<Alien::cmake3>.
use alienfile;
share {
plugin 'Build::CMake';
build [
# this is the default build step, if you do not specify one.
[ '%{cmake}',
@{ meta->prop->{plugin_build_cmake}->{args} },
# ... put extra cmake args here ...
'.'
],
'%{make}',
'%{make} install',
];
};
=head3 vanilla Makefiles
L<Alien::Build> provides a helper (C<%{make}>) for the
C<make> that is used by Perl and
L<ExtUtils::MakeMaker> (EUMM). Unfortunately the C<make>
supported by Perl and EUMM on
Windows (C<nmake> and C<dmake>) are not widely supported by
most open source projects.
(Thankfully recent perls and EUMM support GNU Make on windows now).
You can use the C<make> plugin
(L<Alien::Build::Plugin::Build::Make>) to tell the
L<Alien::Build> system know which make the project that you are
alienizing requires.
plugin 'Build::Make' => 'umake';
# umake makes %{make} either GNU Make or BSD Make on Unix and GNU Make on
Windows.
build {
build [
# You can use the Perl config compiler and cflags using the
%{perl.config...} helper
[ '%{make}', 'CC=%{perl.config.cc}',
'CFLAGS=%{perl.config.cccdlflags} %{perl.config.optimize}' ],
[ '%{make}', 'install',
'PREFIX=%{.install.prefix}' ],
],
};
Some open source projects require GNU Make, and you can specify that, and
L<Alien::gmake>
will be pulled in on platforms that do not already have it.
plugin 'Build::Make' => 'gmake';
...
=head2 How do I probe for a package that uses pkg-config
Use the C<pkg-config> plugin
(L<Alien::Build::Plugin::PkgConfig::Negotiate>):
use alienfile;
plugin 'PkgConfig' => (
pkg_name => 'libfoo',
);
It will probe for a system version of the library. It will also add the
appropriate C<version>
C<cflags> and C<libs> properties on either a C<system> or
C<share> install.
=head2 How do I specify a minimum or exact version requirement for packages
that use pkg-config?
The various pkg-config plugins all support atleast_version, exact_version
and maximum_version
fields, which have the same meaning as the C<pkg-config> command line
interface:
use alienfile;
plugin 'PkgConfig', pkg_name => foo, atleast_version =>
'1.2.3';
or
use alienfile;
plugin 'PkgConfig', pkg_name => foo, exact_version =>
'1.2.3';
=head2 How to create an Alien module for a packages that do not support
pkg-config?
=head3 Packages that provide a configuration script
Many packages provide a command that you can use to get the appropriate
version, compiler
and linker flags. For those packages you can just use the commands in your
L<alienfile>.
Something like this:
use alienfile;
probe [ 'foo-config --version' ];
share {
...
build [
'%{make} PREFIX=%{.runtime.prefix}',
'%{amek} install PREFIX=%{.runtime.prefix}',
];
};
gather [
[ 'foo-config', '--version',
\'%{.runtime.version}' ],
[ 'foo-config', '--cflags',
\'%{.runtime.cflags}' ],
[ 'foo-config', '--libs',
\'%{.runtime.libs}' ],
];
=head3 Packages that require a compile test
Some packages just expect you do know that C<-lfoo> will work. For
those you can use
the C<cbuilder> plugin
(L<Alien::Build::Plugin::Probe::CBuilder>.
use alienfile;
plugin 'Probe::CBuilder' => (
cflags => '-I/opt/libfoo/include',
libs => '-L/opt/libfoo/lib -lfoo',
);
share {
...
gather sub {
my($build) = @_;
my $prefix = $build->runtime_prop->{prefix};
$build->runtime_prop->{cflags} = "-I$prefix/include ";
$build->runtime_prop->{libs} = "-L$prefix/lib -lfoo
";
};
}
This plugin will build a small program with these flags and test that it
works. (There
are also options to provide a program that can make simple tests to ensure
the library
works). If the probe works, it will set the compiler and linker flags.
(There are also
options for extracting the version from the test program). If you do a
share install
you will need to set the compiler and linker flags yourself in the gather
step, if you
aren't using a build plugin that will do that for you.
=head2 Can/Should I write a tool oriented Alien module?
Certainly. The original intent was to provide libraries, but tools are
also quite doable using
the L<Alien::Build> toolset. A good example of how to do this is
L<Alien::nasm>. You will want
to use the 'Probe::CommandLine':
use alienfile;
plugin 'Probe::CommandLine' => (
command => 'gzip',
);
=head2 How do I test my package once it is built (before it is installed)?
Use L<Test::Alien>. It has extensive documentation, and integrates
nicely with L<Alien::Base>.
=head2 How do I patch packages that need alterations?
If you have a diff file you can use patch:
use alienfile;
probe sub { 'share' }; # replace with appropriate probe
share {
...
patch [ '%{patch} -p1 < %{.install.patch}/mypatch.diff' ];
build [ ... ] ;
}
...
You can also patch using Perl if that is easier:
use alienfile;
probe sub { 'share' };
share {
...
patch sub {
my($build) = @_;
# make changes to source prior to build
};
build [ ... ];
};
=head2 The flags that a plugin produces are wrong!
Sometimes, the compiler or linker flags that the PkgConfig plugin comes up
with are not quite
right. (Frequently this is actually because a package maintainer is
providing a broken
C<.pc> file). (Other plugins may also have problems). You could
replace the plugin's C<gather> step
but a better way is to provide a subroutine callback to be called after the
gather stage
is complete. You can do this with the L<alienfile> C<after>
directive:
use alienfile;
plugin 'PlgConfig' => 'libfoo';
share {
...
after 'gather' => sub {
my($build) = @_;
$build->runtime_prop->{libs} .= " -lbar";
# libfoo also requires libbar
$build->runtime_prop->{libs_static} .= " -lbar -lbaz";
# libfoo also requires libbaz under static linkage
};
};
Sometimes you only need to do this on certain platforms. You can adjust
the logic based on C<$^O>
appropriately.
use alienfile;
plugin 'PlgConfig' => 'libfoo';
share {
...
after 'gather' => sub {
my($build) = @_;
if($^O eq 'MSWin32') {
$build->runtime_prop->{libs} .= " -lpsapi";
}
};
};
=head2 "cannot open shared object file" trying to load XS
The error looks something like this:
t/acme_alien_dontpanic2.t ....... 1/?
# Failed test 'xs'
# at t/acme_alien_dontpanic2.t line 13.
# XSLoader failed
# Can't load
'/home/cip/.cpanm/work/1581635869.456/Acme-Alien-DontPanic2-2.0401/_alien/tmp/test-alien-lyiQNX/auto/Test/Alien/XS/
Mod0/Mod0.so' for module Test::Alien::XS::Mod0: libdontpanic.so.0:
cannot open shared object file: No such file or directory at /opt
/perl/5.30.1/lib/5.30.1/x86_64-linux/DynaLoader.pm line 193.
# at /home/cip/perl5/lib/perl5/Test/Alien.pm line 414.
# Compilation failed in require at /home/cip/perl5/lib/perl5/Test/Alien.pm
line 414.
# BEGIN failed--compilation aborted at
/home/cip/perl5/lib/perl5/Test/Alien.pm line 414.
t/acme_alien_dontpanic2.t ....... Dubious, test returned 1 (wstat 256,
0x100)
Failed 1/6 subtests
t/acme_alien_dontpanic2__ffi.t .. ok
This error happened at test time for the Alien, but depending on your
environment and Alien it might
happen later and the actual diagnostic wording might vary.
This is usually because your XS or Alien tries to use dynamic libraries
instead of dynamic libraries.
Please consult the section about dynamic vs. static libraries in
L<Alien::Build::Manual::AlienAuthor>.
The TL;DR is that L<Alien::Build::Plugin::Gather::IsolateDynamic>
might help.
If you are the Alien author and the package you are alienizing doesn't
have a static option you can
use L<Alien::Role::Dino>, but please note the extended set of
caveats!
=head2 599 Internal Exception errors downloading packages from the internet
Alien::Build::Plugin::Fetch::HTTPTiny> 599 Internal Exception fetching
http://dist.libuv.org/dist/v1.15.0
Alien::Build::Plugin::Fetch::HTTPTiny> exception: IO::Socket::SSL 1.42
must be installed for https support
Alien::Build::Plugin::Fetch::HTTPTiny> exception: Net::SSLeay 1.49 must
be installed for https support
Alien::Build::Plugin::Fetch::HTTPTiny> An attempt at a SSL URL https
was made, but your HTTP::Tiny does not appear to be able to use https.
Alien::Build::Plugin::Fetch::HTTPTiny> Please see:
https://metacpan.org/pod/Alien::Build::Manual::FAQ#599-Internal-Exception-errors-downloading-packages-from-the-internet
error fetching http://dist.libuv.org/dist/v1.15.0: 599 Internal Exception
at
/Users/ollisg/.perlbrew/libs/perl-5.26.0@test1/lib/perl5/Alien/Build/Plugin/Fetch/HTTPTiny.pm
line 68.
(Older versions of L<Alien::Build> produced a less verbose more
confusing version of this diagnostic).
TL;DR, instead of this:
share {
start_url => 'http://example.org/dist';
...
};
do this:
share {
start_url => 'https://example.org/dist';
};
If the website is going to redirect to a secure URL anyway.
The "599 Internal Exception" indicates an "internal"
exception from L<HTTP::Tiny> and is not a real
HTTP status code or error. This could mean a number of different problems,
but most frequently
indicates that a SSL request was made without the required modules
(L<Net::SSLeay> and
L<IO::Socket::SSL>). Normally the
L<Alien::Build::Plugin::Download::Negotiate>
and L<Alien::Build::Plugin::Fetch::HTTPTiny> will make sure that the
appropriate modules are added
to your prerequisites for you if you specify a C<https> URL. Some
websites allow an initial request
from C<http> but then redirect to C<https>. If you can it is
better to specify C<https>, if you
cannot, then you can instead use the C<ssl> property on either of
those two plugins.
=head2 Network fetch is turned off
If you get an error like this:
Alien::Build> install type share requested or detected, but network
fetch is turned off
Alien::Build> see see
https://metacpan.org/pod/Alien::Build::Manual::FAQ#Network-fetch-is-turned-off
This is because your environment is setup not to install aliens that
require the network. You
can turn network fetch back on by setting C<ALIEN_INSTALL_NETWORK> to
true, or by unsetting it.
This environment variable is designed for environments that don't ever
want to install aliens that
require downloading source packages over the internet.
=head2 I would really prefer you not download stuff off the internet
The idea of L<Alien> is to download missing packages and build them
automatically to make installing
easier. Some people may not like this, or may even have security
requirements that they not download
random package over the internet (caveat, downloading random stuff off of
CPAN may not be any safer,
so make sure you audit all of the open source software that you use
appropriately). Another reason
you may not want to download from the internet is if you are packaging up
an alien for an operating
system vendor, which will always want to use the system version of a
library. In that situation you
don't want L<Alien::Build> to go off and download something from
the internet because the probe failed
for some reason.
This is easy to take care of, simply set C<ALIEN_INSTALL_TYPE> to
C<system> and a build from source
code will never be attempted. On systems that do not provide system
versions of the library or tool
you will get an error, allowing you to install the library, and retry the
alien install. You can
also set the environment variable on just some aliens.
% export ALIEN_INSTALL_TYPE=system # for everyone
% env ALIEN_INSTALL_TYPE=system cpanm -v Alien::libfoo
=head2 For testing I would like to test both system and share installs!
You can use the C<ALIEN_INSTALL_TYPE> environment variable. It will
force either a C<share> or
C<system> install depending on how it is set. For travis you can do
something like this:
env:
matrix:
- ALIEN_INSTALL_TYPE=share
- ALIEN_INSTALL_TYPE=system
=head2 How do I use Alien::Build from Dist::Zilla?
For creating L<Alien::Base> and L<Alien::Build> based dist from
L<Dist::Zilla> you can use the
dzil plugin L<Dist::Zilla::Plugin::AlienBuild>.
=head2 Cannot find either a share directory or a ConfigData module
If you see an error like this:
Cannot find either a share directory or a ConfigData module for
Alien::libfoo.
(Alien::libfoo loaded from lib/Alien/libfoo.pm)
Please see
https://metacpan.org/pod/distribution/Alien-Build/lib/Alien/Build/Manual/FAQ.pod#Cannot-find-either-a-share-directory-or-a-ConfigData-module
Can't locate Alien/libfoo/ConfigData.pm in @INC (you may need to
install the Alien::libfoo::ConfigData module) (@INC contains: ...)
it means you are trying to use an Alien that hasn't been properly
installed. An L<Alien::Base>
based Alien needs to have either the share directory build during the
install process or for
older legacy L<Alien::Base::ModuleBuild> based Aliens, a ConfigData
module generated by
L<Module::Build>.
This usually happens if you try to use an Alien module from the lib
directory as part of the
Alien's distribution. You need to build the alien and use
C<blib/lib> instead of C<lib> or
install the alien and use the installed path.
It is also possible that your Alien installer is not set up correctly.
Make sure your
C<Makefile.PL> is using L<Alien::Build::MM> correctly.
=head2 I have a question not listed here!
There are a number of forums available to people working on L<Alien>,
L<Alien::Base> and
L<Alien::Build> modules:
=over 4
=item C<#native> on irc.perl.org
This is intended for native interfaces in general so is a good place for
questions about L<Alien>
generally or L<Alien::Base> and L<Alien::Build> specifically.
=item mailing list
The C<perl5-alien> google group is intended for L<Alien> issues
generally, including L<Alien::Base>
and L<Alien::Build>.
L<https://groups.google.com/forum/#!forum/perl5-alien>
=item Open a support ticket
If you have an issue with L<Alie::Build> itself, then please open a
support ticket on the project's GitHub issue
tracker.
L<https://github.com/plicease/Alien-Build/issues>
=back
=head1 SEE ALSO
L<Alien::Build>, L<Alien::Build::MM>,
L<Alien::Build::Plugin>, L<alienfile>
=head1 AUTHOR
Author: Graham Ollis E<lt>plicease@cpan.orgE<gt>
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 Fandiño (salva)
Gianni Ceccarelli (dakkar)
Pavel Shaydo (zwon, trinitum)
Kang-min Liu (劉康民, gugod)
Nicholas Shipp (nshp)
Juan Julián Merelo Guervós (JJ)
Joel Berger (JBERGER)
Petr Pisar (ppisar)
Lance Wicks (LANCEW)
Ahmad Fatoum (a3f, ATHREEF)
José Joaquín Atria (JJATRIA)
Duke Leto (LETO)
Shoichi Kaji (SKAJI)
Shawn Laffan (SLAFFAN)
Paul Evans (leonerd, PEVANS)
Håkon Hægland (hakonhagland, HAKONH)
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2011-2020 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.
=cut