Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Alien::Base::ModuleBuiUserFContributed Perl DoAlien::Base::ModuleBuild::FAQ(3)

NAME
       Alien::Base::ModuleBuild::FAQ - Frequently Asked	Questions about
       Alien::Base::ModuleBuild

VERSION
       version 1.15

SYNOPSIS
	perldoc	Alien::Base::FAQ

DESCRIPTION
       NOTE: Please consider for new development of Aliens that	you use
       Alien::Build and	alienfile instead.  Like Alien::Base::ModuleBUild they
       work with Alien::Base.  Unlike Alien::Base::Module::Build they are more
       easily customized and handle a number of	corner cases better.  For a
       good place to start, please see Alien::Build::Manual::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 Alien::Base authors.

   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 Alien.	 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.

   How do I specify a minimum or exact version requirement for packages	that
       use pkg-config?
       The "alien_version_check" attribute to Alien::Base::ModuleBuild will be
       executed	to determine if	the library is provided	by the operating
       system.	The default for	this is	"%{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 "--atleast-version",
       "--exact-version" options to require a specific range of	versions, but
       these flags do not work with the	"--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	"%{pkg_config}"	helper as it will use
       the system provided pkg-config if it is available and fallback on the
       pure perl PkgConfig if not.

       You can also use	"--exact-version" to specify an	exact version.

   How to create an Alien module for packages that do not support pkg-config?
       Although	Alien::Base and	Alien::Base::ModuleBuild assume	packages come
       with a "pkg-config" ".pc" file to determine compiler and	linker flags
       by default, you can implement an	Alien module for packages that do use
       "pkg-config" by following these tasks:

       subclass	Alien::Base::ModuleBuild and implement
       "alien_check_installed_version"
	   Create a subclass of	Alien::Base::ModuleBuild and put it in the
	   "inc" directory of your distribution	so that	it can be used during
	   install but won't 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 Devel::CheckLib,
	   ExtUtils::CBuilder, ExtUtls::CChecker, Config::AutoConf,
	   FFI::CheckLib among others.	It is also frequently possible to
	   determine if	a library is installed using a "-config" suffixed
	   program.  For example "libxml2" comes with xml2-config which
	   provides the	existence, compiler and	linker flags it	needs.	In my
	   experience, however,	most packages that provide a "-config"
	   suffixed program also provide a "pkg-config"	interface as well.

       implement "alien_check_built_version" in	your Alien::Base::ModuleBuild
       subclass
	   You should also implement "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;
	    }

       set "alien_provides_cflags" and "alien_provides_libs" in	"Build.PL".
	   Add something like this to your "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
	   "alien_provides_libs" and the appropriate "-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
	   "alien_check_installed_version" above.

       For a fully implemented example,	see Alien::Libbz2.

   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 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 Alien::gmake and Alien::patch).
       Here is a short example,	there are many others included with the
       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;

   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	Alien::patch and the
       "%{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
	  },
	  alien_build_commands => [
	    '%{patch} -p1 < ../../patch/mypackage.patch',
	    ...
	  ],
	  ...
	)->create_build_script;

       Create a	folder in your distribution root called	"patch"	and place the
       "mypackage.patch" file in there.	 Since the "patch" command will	be
       executed	in the package root instead of the distribution	root, you need
       to use a	relative path prefixed by "../..".  Here we use	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;

   How do I build a package that uses build system?
       autoconf

       By default Alien::Base::ModuleBuild assumes a package with an autoconf
       style "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 indicates the platform
       independent method for executing	the "configure"	script,	plus any
       normal autoconf flags that are appropriate for Perl Alien libraries.
       The %c also tells Alien::Base::ModuleBuild to use Alien::MSYS on
       Windows platforms and to	add that as a dependency.  The %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.

       autoconf-like

       If you see an error like	this:

	Unknown	option "--with-pic".

       It may be because your package provides a "configure" script that
       provides	an autoconf-style interface, but is not	actually autoconf.
       Alien::Base::ModuleBuild	is aggressive in using the "--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 "configure" scripts consider it an error when they see
       options that they do not	recognize.  You	can tell
       Alien::Base::ModuleBuild	to not use the "--with-pic" option via the
       "alien_autoconf_with_pic" property:

	# Build.PL
	use Alien::Base::ModuleBuild;
	Alien::Base::ModuleBuild->new(
	  ...
	  alien_autoconf_with_pic => 0,
	  ...
	)->create_build_script;

       CMAKE

       You probably cannot count on CMake being	available on most platforms.
       Fortunately, there is an	alien distribution 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 "Build.PL" with the
       "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;

       vanilla Makefiles?

       If you want to use the same "make" as Perl, you can use Config:

	# Build.PL
	use Alien::Base::ModuleBuild;
	use Config;
	Alien::Base::ModuleBuild->new(
	  ...
	  alien_build_commands => [
	    "$Config{make}",
	  ],
	  alien_install_commands => [
	    "$Config{make} install",
	  ],
	  ...
	)->create_build_script;

       GNU Makefiles?

       Some packages require GNU Make's	unique syntax.	Perl's Config provides
       an entry	for "gmake", but it is frequently wrong.  Do not depend	on it.
       Instead you can use Alien::gmake	to provide a real GNU Make (either
       from the	operating system, or built from	source):

	# Build.PL
	use Alien::Base::ModuleBuild;

	Alien::Base::ModuleBuild->new(
	  ...
	  alien_bin_requires =>	{
	    'Alien::gmake' => 0.11, # needed for %{gmake} helper
	  },
	  alien_build_commands => [
	    "%{gmake}",
	  ],
	  alien_install_commands => [
	    "%{gmake} install",
	  ],
	  ...
	)->create_build_script;

   When	debugging my package build, I get different results!
       If you get results from running the commands in your shell different to
       what happens when your "Alien::"	distribution attempts to build,	it may
       be because your environment is different	than the one that your
       distribution is using.  For example, if you use Alien::CMake or
       Alien::gmake to build with specific tools that are provided by your
       operating system, Alien::Build::ModuleBuild will	adjust the path	before
       executing build and install commands.

       In the alien build directory (usually "_alien") you will	find
       environment files that you can source into your shell ("env.csh"	for
       tcsh and	"env.sh" for bourne based shells), which should	provide	the
       identical environment used by the build process in order	to
       troubleshoot the	build manually.

	% source _alien/env.sh

   Can/Should I	write a	tool oriented Alien module using "Alien::Base" that
       provides	executables instead of a library?
       Certainly.  The original	intent was to provide libraries, but tools are
       also quite doable using the "Alien::Base" tool set.  A simple minded
       example of this which is	fairly easy to replicate is Alien::m4.

       In general, this	means specifying a subclass in your "Build.PL" and
       bundling	it in your distribution	"inc" directory.

       "Build.PL":

	...
	use lib	'inc';
	use My::ModuleBuild;

	My::ModuleBuild->new(
	  ...
	)->create_build_script;

       "inc/My/ModuleBuild.pm":

	package	My::ModuleBuild;

	use strict;
	use warnings;
	use parent 'Alien::Base::ModuleBuild';
	use Capture::Tiny qw( capture );

	sub alien_check_installed_version
	{
	  # see	Alien::Base::ModuleBuild#alien_check_installed_version for details

	  my($self) = @_;
	  my($stdout, $stderr) = capture { system 'mytool', '--version'	};

	  # return empty list if the tool is unavailable on the	system,
	  # or unacceptable.
	  return if $! || ...;

	  # parse from stdout or stderr
	  my $version =	...;
	  return $version;
	}

	sub alien_check_built_version
	{
	  # see	Alien::Base::ModuleBuild#alien_check_built_version for details

	  # return empty list if the tool version cannot be found, or if it
	  # is unacceptable.  Note that	this will cause	a failure, so "unknown"
	  # may	be reasonable if the tool version cannot be determined.
	  return if ...;

	  # determine from the tool itself, or the current directory.
	  my $version =	...;
	  return $version;
	}

	1;

       As usual	your "Alien::MyTool" class will	simply be a subclass of
       Alien::Base.  If	you tool is installed in a "bin" directory, you	are
       done, the default "bin_dir" implementation should work for you.
       Otherwise you may need to provide an alternate implementation:

	package	Alien::MyTool;

	use strict;
	use warnings;
	use parent 'Alien::Base';

	sub bin_dir
	{
	  # see	Alien::Base#bin_dir for	details
	  # You	only need to override the default implementation if your tool
	  # does not install into the standard "bin" directory.

	  my($class) = @_;

	  # normally for system	installs the tool should already be in your
	  # PATH, so return an empty list.
	  return if $class->install_type eq 'system';

	  # install_type = share
	  my $dist_dir = $class->dist_dir;
	  return ("$dist_dir/some/bin",	"$dist_dir/some/other/bin");
	}

	1;

       Now once	your tool based	Alien is installed you can use the "bin_dir"
       method to update	the "PATH" as necessary:

	use Alien::MyTool;
	use Env	qw( @PATH );

	unshift	@PATH, Alien::MyTool->bin_dir;
	system 'mytool';

   How do I use	"Alien::Base" from "Dist::Zilla"
       For creating Alien::Base	based dists from Dist::Zilla you can use the
       plugin Dist::Zilla::Plugin::Alien.

   How do I check the built version if my library doesn't provide a ".pc"
       file.
       The default implementation of "alien_check_built_version" uses several
       heuristics, but leans heavily on	"pkg-config" style ".pc" files,	so if
       your library or tool does not provide a ".pc", the version may not be
       detected	and your build may fail.

       A lot of	libraries are bundled as tarballs with the version in the
       directory name that they	are extracted into, and	the current directory
       when "alien_check_built_version"	is called is the build root, so	you
       can use "File::chdir" as	an easy	way to determine the version number:

	package	My::ModuleBuild;

	use strict;
	use warnings;
	use parent 'Alien::Base::ModuleBuild';
	use File::chdir; # provides @CWD

	sub alien_check_built_version
	{
	  my $dir_name = $CWD[-1];

	  if($dir_name =~ /^libfoo-([0-9\.]+)$/) {
	    return $1;
	  } else {
	    # Note that	this will trigger a build failure
	    return;
	  }
	}

	1;

       Using File::chdir and @CWD is a common idiom in Alien::Base, because
       File::chdir is already a	dependency of Alien::Base.  For	packages that
       do not provide a	version	number in the extracted	directory, you may
       require some creativity.

   I have question not listed here!
       There are a number of forums available to people	working	on Alien and
       Alien::Base modules:

       "#native" on irc.perl.org
	   This	is intended for	native interfaces in general and so is a good
	   place for questions about Alien generally or	Alien::Base
	   specifically.

       mailing list
	   The "perl5-alien" google group is intended for Alien	issues
	   generally, including	Alien::Base.

	   <https://groups.google.com/forum/#!forum/perl5-alien>

       Open a support ticket
	   If you have an issue	with Alien::Base itself, then please open a
	   support ticket on the project's GitHub issue	tracker.

	   <https://github.com/PerlAlien/Alien-Base-ModuleBuild/issues>

SEE ALSO
       o   Alien::Base

       o   Alien::Base::ModuleBuild

       o   Alien::Base::ModuleBuild::API

AUTHOR
       Original	author:	Joel A Berger <joel.a.berger@gmail.com>

       Current maintainer: 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)

       Salvador	Fandin~o (salva)

       Gianni Ceccarelli (dakkar)

       Pavel Shaydo (zwon, trinitum)

       Kang-min	Liu (XXX, gugod)

       Nicholas	Shipp (nshp)

       Petr Pisar (ppisar)

       Alberto Simo~es (ambs)

COPYRIGHT AND LICENSE
       This software is	copyright (c) 2012-2020	by Joel	A Berger.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.32.1			  2021-02-28  Alien::Base::ModuleBuild::FAQ(3)

NAME | VERSION | SYNOPSIS | DESCRIPTION | SEE ALSO | AUTHOR | COPYRIGHT AND LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Alien::Base::ModuleBuild::FAQ&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help