1Alien::Build::Manual::AUlsieernACuotnhtorri(b3u)ted PerlAlDioecnu:m:eBnutialtdi:o:nManual::AlienAuthor(3)
2
3
4

NAME

6       Alien::Build::Manual::AlienAuthor - Alien author documentation
7

VERSION

9       version 1.55
10

SYNOPSIS

12        perldoc Alien::Build::Manual::AlienAuthor
13

DESCRIPTION

15       This document is intended to teach Alien authors how to build their own
16       Alien distribution using Alien::Build and Alien::Base.  Such an Alien
17       distribution consists of three essential parts:
18
19       An alienfile
20           This is a recipe for how to 1) detect an already installed version
21           of the library or tool you are alienizing 2) download and build the
22           library or tool that you are alienizing and 3) gather the
23           configuration settings necessary for the use of that library or
24           tool.
25
26       An installer "Makefile.PL" or "Build.PL" or a "dist.ini" if you are
27       using Dist::Zilla
28           This is a thin layer between your alienfile recipe, and the Perl
29           installer (either ExtUtils::MakeMaker or Module::Build.
30
31       A Perl class (.pm file) that inherits from Alien::Base
32           For most Aliens this does not need to be customized at all, since
33           Alien::Base usually does what you need.
34
35       For example if you were alienizing a library called libfoo, you might
36       have these files:
37
38        Alien-Libfoo-1.00/Makefile.PL
39        Alien-Libfoo-1.00/alienfile
40        Alien-Libfoo-1.00/lib/Alien/Libfoo.pm
41
42       This document will focus mainly on instructing you how to construct an
43       alienfile, but we will also briefly cover making a simple "Makefile.PL"
44       or "dist.ini" to go along with it.  We will also touch on when you
45       might want to extend your subclass to add non-standard functionality.
46
47   Using commands
48       Most software libraries and tools will come with instructions for how
49       to install them in the form of commands that you are intended to type
50       into a shell manually.  The easiest way to automate those instructions
51       is to just put the commands in your alienfile.  For example, lets
52       suppose that libfoo is built using autoconf and provides a "pkg-config"
53       ".pc" file.
54
55       (Aside, autoconf is a series of tools and macros used to configure
56       (usually) a C or C++ library or tool by generating any number of
57       Makefiles.  It is the C equivalent to ExtUtils::MakeMaker, if you will.
58       Basically, if your library or tool instructions start with
59       './configure' it is most likely an autoconf based library or tool).
60
61       (Aside2, "pkg-config" is a standard-ish way to provide the compiler and
62       linker flags needed for compiling and linking against the library.  If
63       your tool installs a ".pc" file, usually in "$PREFIX/lib/pkgconfig"
64       then, your tool uses "pkg-config").
65
66       Here is the alienfile that you might have:
67
68        use alienfile;
69
70        probe [ 'pkg-config --exists libfoo' ];
71
72        share {
73
74          start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';
75
76          download [ 'wget %{.meta.start_url}' ];
77
78          extract [ 'tar zxf %{.install.download}' ];
79
80          build [
81            [ './configure --prefix=%{.install.prefix} --disable-shared' ],
82            [ '%{make}' ],
83            [ '%{make} install' ],
84          ];
85
86        };
87
88        gather [
89          [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
90          [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
91          [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
92        ];
93
94       There is a lot going on here, so lets decode it a little bit.  An
95       alienfile is just some Perl with some alien specific sugar.  The first
96       line
97
98        use alienfile;
99
100       imports the sugar into the alienfile.  It also is a flag for the reader
101       to see that this is an alienfile and not some other kind of Perl
102       script.
103
104       The second line is the probe directive:
105
106        probe [ 'pkg-config --exists libfoo' ];
107
108       is used to see if the library is already installed on the target
109       system.  If "pkg-config" is in the path, and if libfoo is installed,
110       this should exit with a success (0) and tell Alien::Build to use the
111       system library.  If either "pkg-config" in the PATH, or if libfoo is
112       not installed, then it will exist with non-success (!= 0) and tells
113       Alien::Build to download and build from source.
114
115       You can provide as many probe directives as you want.  This is useful
116       if there are different ways to probe for the system.  Alien::Build will
117       stop on the first successfully found system library found.  Say our
118       library libfoo comes with a ".pc" file for use with "pkg-config" and
119       also provides a "foo-config" program to find the same values.  You
120       could then specify this in your alienfile
121
122        probe [ 'pkg-config --exists libfoo' ];
123        probe [ 'foo-config --version' ];
124
125       Other directives can be specified multiple times if there are different
126       methods that can be tried for the various steps.
127
128       Sometimes it is easier to probe for a library from Perl rather than
129       with a command.  For that you can use a code reference.  For example,
130       another way to call "pkg-config" would be from Perl:
131
132        probe sub {
133          my($build) = @_;  # $build is the Alien::Build instance.
134          system 'pkg-config --exists libfoo';
135          $? == 0 ? 'system' : 'share';
136        };
137
138       The Perl code should return 'system' if the library is installed, and
139       'share' if not.  (Other directives should return a true value on
140       success, and a false value).  You can also throw an exception with
141       "die" to indicate a failure.
142
143       The next part of the alienfile is the "share" block, which is used to
144       group the directives which are used to download and install the library
145       or tool in the event that it is not already installed.
146
147        share {
148          start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';
149          download [ 'wget %{.meta.start_url}' ];
150          extract [ 'tar zxf %{.install.download}' ];
151          build [
152            [ './configure --prefix=%{.install.prefix} --disable-shared' ],
153            [ '%{make}' ],
154            [ '%{make} install' ],
155          ];
156        };
157
158       The start_url specifies where to find the package that you are
159       alienizing.  It should be either a tarball (or zip file, or what have
160       you) or an HTML index.  The download directive as you might imagine
161       specifies how to download  the library or tool.  The extract directive
162       specifies how to extract the archive once it is downloaded.  In the
163       extract step, you can use the variable "%{.install.download}" as a
164       placeholder for the archive that was downloaded in the download step.
165       This is also accessible if you use a code reference from the
166       Alien::Build instance:
167
168        share {
169          ...
170          requires 'Archive::Extract';
171          extract sub {
172            my($build) = @_;
173            my $tarball = $build->install_prop->{download};
174            my $ae = Archive::Extract->new( archive => $tarball );
175            $ae->extract;
176            1;
177          }
178          ...
179        };
180
181       The build directive specifies how to build the library or tool once it
182       has been downloaded and extracted.  Note the special variable
183       "%{.install.prefix}" is the location where the library should be
184       installed.  "%{make}" is a helper which will be replaced by the
185       appropriate "make", which may be called something different on some
186       platforms (on Windows for example, it frequently may be called "nmake"
187       or "dmake").
188
189       The final part of the alienfile has a gather directive which specifies
190       how to get the details on how to compile and link against the library.
191       For this, once again we use the "pkg-config" command:
192
193        gather [
194          [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
195          [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
196          [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
197        ];
198
199       The scalar reference as the final item in the command list tells
200       Alien::Build that the output from the command should be stored in the
201       given variable.  The runtime variables are the ones that will be
202       available to "Alien::Libfoo" once it is installed.  (Install
203       properties, which are the ones that we have seen up till now are thrown
204       away once the Alien distribution is installed.
205
206       You can also provide a "sys" block for directives that should be used
207       when a system install is detected.  Normally you only need to do this
208       if the gather step is different between share and system installs.  For
209       example, the above is equivalent to:
210
211        build {
212          ...
213          gather [
214            [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
215            [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
216            [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
217          ];
218        };
219
220        sys {
221          gather [
222            [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
223            [ 'pkg-config --cflags     libfoo', \'%{.runtime.cflags}'  ],
224            [ 'pkg-config --libs       libfoo', \'%{.runtime.libs}'    ],
225          ];
226        };
227
228       (Aside3, the reason it is called "sys" and not "system" is so that it
229       does not conflict with the built in "system" function)!
230
231   Using plugins
232       The first example is a good way of showing the full manual path that
233       you can choose, but there is a lot of repetition, if you are doing many
234       Aliens that use autoconf and "pkg-config" (which are quite common.
235       alienfile allows you to use plugins.  See Alien::Build::Plugin for a
236       list of some of the plugin categories.
237
238       For now, I will just show you how to write the alienfile for libfoo
239       above using Alien::Build::Plugin::Build::Autoconf,
240       Alien::Build::Plugin::PkgConfig::Negotiate,
241       Alien::Build::Plugin::Download::Negotiate, and
242       Alien::Build::Plugin::Extract::Negotiate
243
244        use alienfile;
245
246        plugin 'PkgConfig' => (
247          pkg_name => 'libfoo',
248        );
249
250        share {
251          start_url 'http://www.libfoo.org/src';
252          plugin 'Download' => (
253            filter => qr/^libfoo-[0-9\.]+\.tar\.gz$/,
254            version => qr/^libfoo-([0-9\.]+)\.tar\.gz$/,
255          );
256          plugin 'Extract' => 'tar.gz';
257          plugin 'Build::Autoconf';
258          build [
259            '%{configure} --disable-shared',
260            '%{make}',
261            '%{make} install',
262          ];
263        };
264
265       The first plugin that we use is the "pkg-config" negotiation plugin.  A
266       negotiation plugin is one which doesn't do the actual work but selects
267       the best one from a set of plugins depending on your platform and
268       environment.  (In the case of
269       Alien::Build::Plugin::PkgConfig::Negotiate, it may choose to use
270       command line tools, a pure Perl implementation (PkgConfig), or
271       libpkgconf, depending on what is available).  When using negotiation
272       plugins you may omit the "::Negotiate" suffix.  So as you can see using
273       the plugin here is an advantage because it is more reliable that just
274       specifying a command which may not be installed!
275
276       Next we use the download negotiation plugin.  This is also better than
277       the version above, because again, "wget" my not be installed on the
278       target system.  Also you can specify a URL which will be scanned for
279       links, and use the most recent version.
280
281       We use the Extract negotiation plugin to use either command line tools,
282       or Perl libraries to extract from the archive once it is downloaded.
283
284       Finally we use the Autoconf plugin
285       (Alien::Build::Plugin::Build::Autoconf).  This is a lot more
286       sophisticated and reliable than in the previous example, for a number
287       of reasons.  This version will even work on Windows assuming the
288       library or tool you are alienizing supports that platform!
289
290       Strictly speaking the build directive is not necessary, because the
291       autoconf plugin provides a default which is reasonable.  The only
292       reason that you would want to include it is if you need to provide
293       additional flags to the configure step.
294
295        share {
296          ...
297          build [
298            '%{configure} --enable-bar --enable-baz --disable-shared',
299            '%{make}',
300            '%{make} install',
301          ];
302        };
303
304   Verifying and debugging your alienfile
305       You could feed your alienfile directly into Alien::Build, or
306       Alien::Build::MM, but it is sometimes useful to test your alienfile
307       using the "af" command (it does not come with Alien::Build, you need to
308       install App::af).  By default "af" will use the "alienfile" in the
309       current directory (just as "make" uses the "Makefile" in the current
310       directory; just like "make" you can use the "-f" option to specify a
311       different alienfile).
312
313       You can test your alienfile in dry run mode:
314
315        % af install --dry-run
316        Alien::Build::Plugin::Core::Legacy> adding legacy hash to config
317        Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/I2YXRyxb0r/_alien
318        ---
319        cflags: ''
320        cflags_static: ''
321        install_type: system
322        legacy:
323          finished_installing: 1
324          install_type: system
325          name: libfoo
326          original_prefix: /tmp/7RtAusykNN
327          version: 1.2.3
328        libs: '-lfoo '
329        libs_static: '-lfoo '
330        prefix: /tmp/7RtAusykNN
331        version: 1.2.3
332
333       You can use the "--type" option to force a share install (download and
334       build from source):
335
336        % af install --type=share --dry-run
337        Alien::Build::Plugin::Core::Download> decoding html
338        Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
339        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
340        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
341        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
342        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
343        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
344        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
345        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
346        Alien::Build::Plugin::Core::Download> candidate  ...
347        Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
348        Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
349        Alien::Build::CommandSequence> + ./configure --prefix=/tmp/P22WEXj80r --with-pic --disable-shared
350        ... snip ...
351        Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/WsoLAQ889w/_alien
352        ---
353        cflags: ''
354        cflags_static: ''
355        install_type: share
356        legacy:
357          finished_installing: 1
358          install_type: share
359          original_prefix: /tmp/P22WEXj80r
360          version: 1.2.4
361        libs: '-L/tmp/P22WEXj80r/lib -lfoo '
362        libs_static: '-L/tmp/P22WEXj80r/lib -lfoo '
363        prefix: /tmp/P22WEXj80r
364        version: 1.2.4
365
366       You can also use the "--before" and "--after" options to take a peek at
367       what the build environment looks like at different stages as well,
368       which can sometimes be useful:
369
370        % af install --dry-run --type=share --before build bash
371        Alien::Build::Plugin::Core::Download> decoding html
372        Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
373        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
374        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
375        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
376        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
377        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
378        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
379        Alien::Build::Plugin::Core::Download> candidate  https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
380        Alien::Build::Plugin::Core::Download> candidate  ...
381        Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
382        Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
383        App::af::install>  [ before build ] + bash
384        /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$ ls
385        CHANGES Makefile autoconf.ac lib
386        /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$
387
388       There are a lot of other useful things that you can do with the "af"
389       command.  See af for details.
390
391   Integrating with MakeMaker
392       Once you have a working alienfile you can write your "Makefile.PL".
393
394        use ExtUtils::MakeMaker;
395        use Alien::Build::MM;
396
397        my $abmm = Alien::Build::MM->new;
398
399        WriteMakefile($abmm->mm_args(
400          ABSTRACT => 'Discover or download and install libfoo',
401          DISTNAME => 'Alien-Libfoo',
402          NAME     => 'Alien::Libfoo',
403          VERSION_FROM => 'lib/Alien/Libfoo.pm',
404        ));
405
406        sub MY::postamble {
407          $abmm->mm_postamble;
408        }
409
410       The "lib/Alien/Libfoo.pm" that goes along with it is very simple:
411
412        package Alien::Libfoo;
413
414        use strict;
415        use warnings;
416        use base qw( Alien::Base );
417
418        1;
419
420       You are done and can install it normally:
421
422        % perl Makefile.PL
423        % make
424        % make test
425        % make install
426
427   Integrating with Module::Build
428       Please don't!  Okay if you have to there is Alien::Build::MB.
429
430   Non standard configuration
431       Alien::Base support most of the things that your Alien will need, like
432       compiler flags (cflags), linker flags (libs) and binary directory
433       (bin_dir).  Your library or tool may have other configuration items
434       which are not supported by default.  You can store the values in the
435       alienfile into the runtime properties:
436
437        gather [
438          # standard:
439          [ 'foo-config --version libfoo', \'%{.runtime.version}' ],
440          [ 'foo-config --cflags  libfoo', \'%{.runtime.cflags}'  ],
441          [ 'foo-config --libs    libfoo', \'%{.runtime.libs}'    ],
442          # non-standard
443          [ 'foo-config --bar-baz libfoo', \'%{.runtime.bar_baz}' ],
444        ];
445
446       then you can expose them in your Alien::Base subclass:
447
448        package Alien::Libfoo;
449
450        use strict;
451        use warnings;
452        use base qw( Alien::Base );
453
454        sub bar_baz {
455          my($self) = @_;
456          $self->runtime_prop->{bar_baz},
457        };
458
459        1;
460
461   Testing
462       (optional, but highly recommended)
463
464       You should write a test using Test::Alien to make sure that your alien
465       will work with any XS modules that are going to use it:
466
467        use Test2::V0;
468        use Test::Alien;
469        use Alien::Libfoo;
470
471        alien_ok 'Alien::Libfoo';
472
473        xs_ok { local $/; <DATA> }, with_subtest {
474          is Foo::something(), 1, 'Foo::something() returns 1';
475        };
476
477        done_testing;
478
479        __DATA__
480        #include "EXTERN.h"
481        #include "perl.h"
482        #include "XSUB.h"
483        #include <foo.h>
484
485        MODULE = Foo PACKAGE = Foo
486
487        int something(class)
488
489       You can also use Test::Alien to test tools instead of libraries:
490
491        use Test2::V0;
492        use Test::Alien;
493        use Alien::Libfoo;
494
495        alien_ok 'Alien::Libfoo';
496        run_ok('foo', '--version')
497          ->exit_is(0);
498
499        done_testing;
500
501       More details on testing Alien modules can be found in the Test::Alien
502       documentation.
503
504       You can also run the tests that come with the package that you are
505       alienizing, by using a "test" block in your alienfile.  Keep in mind
506       that some packages use testing tools or have other prerequisites that
507       will not be available on your users machines when they attempt to
508       install your alien.  So you do not want to blindly add a test block
509       without checking what the prereqs are.  For Autoconf style packages you
510       typically test a package using the "make check" command:
511
512        use alienfile;
513
514        plugin 'PkgConfig' => 'libfoo';
515
516        share {
517          ... # standard build steps.
518          test [ '%{make} check' ];
519        };
520
521   Dist::Zilla
522       (optional, mildly recommended)
523
524       You can also use the Alien::Build Dist::Zilla plugin
525       Dist::Zilla::Plugin::AlienBuild:
526
527        name    = Alien-Libfoo
528        author  = E. Xavier Ample <example@cpan.org>
529        license = Perl_5
530        copyright_holder = E. Xavier Ample <example@cpan.org>
531        copyright_year   = 2017
532        version = 0.01
533
534        [@Basic]
535        [AlienBuild]
536
537       The plugin takes care of a lot of details like making sure that the
538       correct minimum versions of Alien::Build and Alien::Base are used.  See
539       the plugin documentation for additional details.
540
541   Using your Alien
542       Once you have installed you can use your Alien.  See
543       Alien::Build::Manual::AlienUser for guidance on that.
544

AUTHOR

546       Author: Graham Ollis <plicease@cpan.org>
547
548       Contributors:
549
550       Diab Jerius (DJERIUS)
551
552       Roy Storey
553
554       Ilya Pavlov
555
556       David Mertens (run4flat)
557
558       Mark Nunberg (mordy, mnunberg)
559
560       Christian Walde (Mithaldu)
561
562       Brian Wightman (MidLifeXis)
563
564       Zaki Mughal (zmughal)
565
566       mohawk (mohawk2, ETJ)
567
568       Vikas N Kumar (vikasnkumar)
569
570       Flavio Poletti (polettix)
571
572       Salvador Fandiño (salva)
573
574       Gianni Ceccarelli (dakkar)
575
576       Pavel Shaydo (zwon, trinitum)
577
578       Kang-min Liu (劉康民, gugod)
579
580       Nicholas Shipp (nshp)
581
582       Juan Julián Merelo Guervós (JJ)
583
584       Joel Berger (JBERGER)
585
586       Petr Pisar (ppisar)
587
588       Lance Wicks (LANCEW)
589
590       Ahmad Fatoum (a3f, ATHREEF)
591
592       José Joaquín Atria (JJATRIA)
593
594       Duke Leto (LETO)
595
596       Shoichi Kaji (SKAJI)
597
598       Shawn Laffan (SLAFFAN)
599
600       Paul Evans (leonerd, PEVANS)
601
603       This software is copyright (c) 2011-2018 by Graham Ollis.
604
605       This is free software; you can redistribute it and/or modify it under
606       the same terms as the Perl 5 programming language system itself.
607
608
609
610perl v5.28.1                      2019-02-2A4lien::Build::Manual::AlienAuthor(3)
Impressum