1Alien::Build::Manual::AUlsieernACuotnhtorri(b3u)ted PerlAlDioecnu:m:eBnutialtdi:o:nManual::AlienAuthor(3)
2
3
4
6 Alien::Build::Manual::AlienAuthor - Alien author documentation
7
9 version 2.45
10
12 perldoc Alien::Build::Manual::AlienAuthor
13
15 Note: Please read the entire document before you get started in writing
16 your own alienfile. The section on dynamic vs. static libraries will
17 likely save you a lot of grief if you read it now!
18
19 This document is intended to teach Alien authors how to build their own
20 Alien distribution using Alien::Build and Alien::Base. Such an Alien
21 distribution consists of three essential parts:
22
23 An alienfile
24 This is a recipe for how to 1) detect an already installed version
25 of the library or tool you are alienizing 2) download and build the
26 library or tool that you are alienizing and 3) gather the
27 configuration settings necessary for the use of that library or
28 tool.
29
30 An installer "Makefile.PL" or "Build.PL" or a "dist.ini" if you are
31 using Dist::Zilla
32 This is a thin layer between your alienfile recipe, and the Perl
33 installer (either ExtUtils::MakeMaker or Module::Build.
34
35 A Perl class (.pm file) that inherits from Alien::Base
36 For most Aliens this does not need to be customized at all, since
37 Alien::Base usually does what you need.
38
39 For example if you were alienizing a library called libfoo, you might
40 have these files:
41
42 Alien-Libfoo-1.00/Makefile.PL
43 Alien-Libfoo-1.00/alienfile
44 Alien-Libfoo-1.00/lib/Alien/Libfoo.pm
45
46 This document will focus mainly on instructing you how to construct an
47 alienfile, but we will also briefly cover making a simple "Makefile.PL"
48 or "dist.ini" to go along with it. We will also touch on when you
49 might want to extend your subclass to add non-standard functionality.
50
51 Using commands
52 Most software libraries and tools will come with instructions for how
53 to install them in the form of commands that you are intended to type
54 into a shell manually. The easiest way to automate those instructions
55 is to just put the commands in your alienfile. For example, lets
56 suppose that libfoo is built using autoconf and provides a "pkg-config"
57 ".pc" file.
58
59 We will also later discuss plugins. For common build systems like
60 autoconf or CMake, it is usually better to use the appropriate plugin
61 because they will handle corner cases better than a simple set of
62 commands. We're going to take a look at commands first because it's
63 easier to understand the different phases with commands.
64
65 (Aside, autoconf is a series of tools and macros used to configure
66 (usually) a C or C++ library or tool by generating any number of
67 Makefiles. It is the C equivalent to ExtUtils::MakeMaker, if you will.
68 Basically, if your library or tool instructions start with
69 './configure' it is most likely an autoconf based library or tool).
70
71 (Aside2, "pkg-config" is a standard-ish way to provide the compiler and
72 linker flags needed for compiling and linking against the library. If
73 your tool installs a ".pc" file, usually in "$PREFIX/lib/pkgconfig"
74 then, your tool uses "pkg-config").
75
76 Here is the alienfile that you might have:
77
78 use alienfile;
79
80 probe [ 'pkg-config --exists libfoo' ];
81
82 share {
83
84 start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';
85
86 download [ 'wget %{.meta.start_url}' ];
87
88 extract [ 'tar zxf %{.install.download}' ];
89
90 build [
91 [ './configure --prefix=%{.install.prefix} --disable-shared' ],
92 [ '%{make}' ],
93 [ '%{make} install' ],
94 ];
95
96 };
97
98 gather [
99 [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
100 [ 'pkg-config --cflags libfoo', \'%{.runtime.cflags}' ],
101 [ 'pkg-config --libs libfoo', \'%{.runtime.libs}' ],
102 ];
103
104 There is a lot going on here, so lets decode it a little bit. An
105 alienfile is just some Perl with some alien specific sugar. The first
106 line
107
108 use alienfile;
109
110 imports the sugar into the alienfile. It also is a flag for the reader
111 to see that this is an alienfile and not some other kind of Perl
112 script.
113
114 The second line is the probe directive:
115
116 probe [ 'pkg-config --exists libfoo' ];
117
118 is used to see if the library is already installed on the target
119 system. If "pkg-config" is in the path, and if libfoo is installed,
120 this should exit with a success (0) and tell Alien::Build to use the
121 system library. If either "pkg-config" in the PATH, or if libfoo is
122 not installed, then it will exist with non-success (!= 0) and tells
123 Alien::Build to download and build from source.
124
125 You can provide as many probe directives as you want. This is useful
126 if there are different ways to probe for the system. Alien::Build will
127 stop on the first successfully found system library found. Say our
128 library libfoo comes with a ".pc" file for use with "pkg-config" and
129 also provides a "foo-config" program to find the same values. You
130 could then specify this in your alienfile
131
132 probe [ 'pkg-config --exists libfoo' ];
133 probe [ 'foo-config --version' ];
134
135 Other directives can be specified multiple times if there are different
136 methods that can be tried for the various steps.
137
138 Sometimes it is easier to probe for a library from Perl rather than
139 with a command. For that you can use a code reference. For example,
140 another way to call "pkg-config" would be from Perl:
141
142 probe sub {
143 my($build) = @_; # $build is the Alien::Build instance.
144 system 'pkg-config --exists libfoo';
145 $? == 0 ? 'system' : 'share';
146 };
147
148 The Perl code should return 'system' if the library is installed, and
149 'share' if not. (Other directives should return a true value on
150 success, and a false value). You can also throw an exception with
151 "die" to indicate a failure.
152
153 The next part of the alienfile is the "share" block, which is used to
154 group the directives which are used to download and install the library
155 or tool in the event that it is not already installed.
156
157 share {
158 start_url 'http://www.libfoo.org/src/libfoo-1.00.tar.gz';
159 download [ 'wget %{.meta.start_url}' ];
160 extract [ 'tar zxf %{.install.download}' ];
161 build [
162 [ './configure --prefix=%{.install.prefix} --disable-shared' ],
163 [ '%{make}' ],
164 [ '%{make} install' ],
165 ];
166 };
167
168 The start_url specifies where to find the package that you are
169 alienizing. It should be either a tarball (or zip file, or what have
170 you) or an HTML index. The download directive as you might imagine
171 specifies how to download the library or tool. The extract directive
172 specifies how to extract the archive once it is downloaded. In the
173 extract step, you can use the variable "%{.install.download}" as a
174 placeholder for the archive that was downloaded in the download step.
175 This is also accessible if you use a code reference from the
176 Alien::Build instance:
177
178 share {
179 ...
180 requires 'Archive::Extract';
181 extract sub {
182 my($build) = @_;
183 my $tarball = $build->install_prop->{download};
184 my $ae = Archive::Extract->new( archive => $tarball );
185 $ae->extract;
186 1;
187 }
188 ...
189 };
190
191 The build directive specifies how to build the library or tool once it
192 has been downloaded and extracted. Note the special variable
193 "%{.install.prefix}" is the location where the library should be
194 installed. "%{make}" is a helper which will be replaced by the
195 appropriate "make", which may be called something different on some
196 platforms (on Windows for example, it frequently may be called "nmake"
197 or "dmake").
198
199 The final part of the alienfile has a gather directive which specifies
200 how to get the details on how to compile and link against the library.
201 For this, once again we use the "pkg-config" command:
202
203 gather [
204 [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
205 [ 'pkg-config --cflags libfoo', \'%{.runtime.cflags}' ],
206 [ 'pkg-config --libs libfoo', \'%{.runtime.libs}' ],
207 ];
208
209 The scalar reference as the final item in the command list tells
210 Alien::Build that the output from the command should be stored in the
211 given variable. The runtime variables are the ones that will be
212 available to "Alien::Libfoo" once it is installed. (Install
213 properties, which are the ones that we have seen up till now are thrown
214 away once the Alien distribution is installed.
215
216 You can also provide a "sys" block for directives that should be used
217 when a system install is detected. Normally you only need to do this
218 if the gather step is different between share and system installs. For
219 example, the above is equivalent to:
220
221 build {
222 ...
223 gather [
224 [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
225 [ 'pkg-config --cflags libfoo', \'%{.runtime.cflags}' ],
226 [ 'pkg-config --libs libfoo', \'%{.runtime.libs}' ],
227 ];
228 };
229
230 sys {
231 gather [
232 [ 'pkg-config --modversion libfoo', \'%{.runtime.version}' ],
233 [ 'pkg-config --cflags libfoo', \'%{.runtime.cflags}' ],
234 [ 'pkg-config --libs libfoo', \'%{.runtime.libs}' ],
235 ];
236 };
237
238 (Aside3, the reason it is called "sys" and not "system" is so that it
239 does not conflict with the built in "system" function)!
240
241 Using plugins
242 The first example is a good way of showing the full manual path that
243 you can choose, but there is a lot of repetition, if you are doing many
244 Aliens that use autoconf and "pkg-config" (which are quite common.
245 alienfile allows you to use plugins. See Alien::Build::Plugin for a
246 list of some of the plugin categories.
247
248 For now, I will just show you how to write the alienfile for libfoo
249 above using Alien::Build::Plugin::Build::Autoconf,
250 Alien::Build::Plugin::PkgConfig::Negotiate,
251 Alien::Build::Plugin::Download::Negotiate, and
252 Alien::Build::Plugin::Extract::Negotiate
253
254 use alienfile;
255
256 plugin 'PkgConfig' => (
257 pkg_name => 'libfoo',
258 );
259
260 share {
261 start_url 'http://www.libfoo.org/src';
262 plugin 'Download' => (
263 filter => qr/^libfoo-[0-9\.]+\.tar\.gz$/,
264 version => qr/^libfoo-([0-9\.]+)\.tar\.gz$/,
265 );
266 plugin 'Extract' => 'tar.gz';
267 plugin 'Build::Autoconf';
268 build [
269 '%{configure} --disable-shared',
270 '%{make}',
271 '%{make} install',
272 ];
273 };
274
275 The first plugin that we use is the "pkg-config" negotiation plugin. A
276 negotiation plugin is one which doesn't do the actual work but selects
277 the best one from a set of plugins depending on your platform and
278 environment. (In the case of
279 Alien::Build::Plugin::PkgConfig::Negotiate, it may choose to use
280 command line tools, a pure Perl implementation (PkgConfig), or
281 libpkgconf, depending on what is available). When using negotiation
282 plugins you may omit the "::Negotiate" suffix. So as you can see using
283 the plugin here is an advantage because it is more reliable than just
284 specifying a command which may not be installed!
285
286 Next we use the download negotiation plugin. This is also better than
287 the version above, because again, "wget" my not be installed on the
288 target system. Also you can specify a URL which will be scanned for
289 links, and use the most recent version.
290
291 We use the Extract negotiation plugin to use either command line tools,
292 or Perl libraries to extract from the archive once it is downloaded.
293
294 Finally we use the Autoconf plugin
295 (Alien::Build::Plugin::Build::Autoconf). This is a lot more
296 sophisticated and reliable than in the previous example, for a number
297 of reasons. This version will even work on Windows assuming the
298 library or tool you are alienizing supports that platform!
299
300 Strictly speaking the build directive is not necessary, because the
301 autoconf plugin provides a default which is reasonable. The only
302 reason that you would want to include it is if you need to provide
303 additional flags to the configure step.
304
305 share {
306 ...
307 build [
308 '%{configure} --enable-bar --enable-baz --disable-shared',
309 '%{make}',
310 '%{make} install',
311 ];
312 };
313
314 Multiple .pc files
315 Some packages come with multiple libraries paired with multiple ".pc"
316 files. In this case you want to provide the
317 Alien::Build::Plugin::PkgConfig::Negotiate with an array reference of
318 package names.
319
320 plugin 'PkgConfig' => (
321 pkg_name => [ 'foo', 'bar', 'baz' ],
322 );
323
324 All packages must be found in order for the "system" install to
325 succeed. Once installed the first "pkg_name" will be used by default
326 (in this example "foo"), and you can retrieve any other "pkg_name"
327 using the Alien::Base alt method.
328
329 A note about dynamic vs. static libraries
330 If you are using your Alien to build an XS module, it is important that
331 you use static libraries if possible. If you have a package that
332 refuses to build a static library, then you can use Alien::Role::Dino.
333
334 Actually let me back up a minute. For a "share" install it is best to
335 use static libraries to build your XS extension. This is because if
336 your Alien is ever upgraded to a new version it can break your existing
337 XS modules. For a "system" install shared libraries are usually best
338 because you can often get security patches without having to re-build
339 anything in perl land.
340
341 If you looked closely at the "Using commands" and "Using plugins"
342 sections above, you may notice that we went out of our way where
343 possible to tell Autotools to build only static libraries using the
344 "--disable-shared" command. The Autoconf plugin also does this by
345 default.
346
347 Sometimes though you will have a package that builds both, or maybe you
348 want both static and dynamic libraries to work with XS and FFI. For
349 that case, there is the Alien::Build::Plugin::Gather::IsolateDynamic
350 plugin.
351
352 use alienfile;
353 ...
354 plugin 'Gather::IsolateDynamic';
355
356 What it does, is that it moves the dynamic libraries (usually .so on
357 Unix and .DLL on Windows) to a place where they can be found by FFI,
358 and where they won't be used by the compiler for building XS. It
359 usually doesn't do any harm to include this plugin, so if you are just
360 starting out you might want to add it anyway. Arguably it should have
361 been the default behavior from the beginning.
362
363 If you have already published an Alien that does not isolate its
364 dynamic libraries, then you might get some fails from old upgraded
365 aliens because the share directory isn't cleaned up by default (this is
366 perhaps a design bug in the way that share directories work, but it is
367 a long standing characteristic). One work around for this is to use
368 the "clean_install" property on Alien::Build::MM, which will clean out
369 the share directory on upgrade, and possibly save you a lot of grief.
370
371 Verifying and debugging your alienfile
372 You could feed your alienfile directly into Alien::Build, or
373 Alien::Build::MM, but it is sometimes useful to test your alienfile
374 using the "af" command (it does not come with Alien::Build, you need to
375 install App::af). By default "af" will use the "alienfile" in the
376 current directory (just as "make" uses the "Makefile" in the current
377 directory; just like "make" you can use the "-f" option to specify a
378 different alienfile).
379
380 You can test your alienfile in dry run mode:
381
382 % af install --dry-run
383 Alien::Build::Plugin::Core::Legacy> adding legacy hash to config
384 Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/I2YXRyxb0r/_alien
385 ---
386 cflags: ''
387 cflags_static: ''
388 install_type: system
389 legacy:
390 finished_installing: 1
391 install_type: system
392 name: libfoo
393 original_prefix: /tmp/7RtAusykNN
394 version: 1.2.3
395 libs: '-lfoo '
396 libs_static: '-lfoo '
397 prefix: /tmp/7RtAusykNN
398 version: 1.2.3
399
400 You can use the "--type" option to force a share install (download and
401 build from source):
402
403 % af install --type=share --dry-run
404 Alien::Build::Plugin::Core::Download> decoding html
405 Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
406 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
407 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
408 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
409 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
410 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
411 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
412 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
413 Alien::Build::Plugin::Core::Download> candidate ...
414 Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
415 Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
416 Alien::Build::CommandSequence> + ./configure --prefix=/tmp/P22WEXj80r --with-pic --disable-shared
417 ... snip ...
418 Alien::Build::Plugin::Core::Gather> mkdir -p /tmp/WsoLAQ889w/_alien
419 ---
420 cflags: ''
421 cflags_static: ''
422 install_type: share
423 legacy:
424 finished_installing: 1
425 install_type: share
426 original_prefix: /tmp/P22WEXj80r
427 version: 1.2.4
428 libs: '-L/tmp/P22WEXj80r/lib -lfoo '
429 libs_static: '-L/tmp/P22WEXj80r/lib -lfoo '
430 prefix: /tmp/P22WEXj80r
431 version: 1.2.4
432
433 You can also use the "--before" and "--after" options to take a peek at
434 what the build environment looks like at different stages as well,
435 which can sometimes be useful:
436
437 % af install --dry-run --type=share --before build bash
438 Alien::Build::Plugin::Core::Download> decoding html
439 Alien::Build::Plugin::Core::Download> candidate *https://www.libfoo.org/download/libfoo-1.2.4.tar.gz
440 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.3.tar.gz
441 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.2.tar.gz
442 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.1.tar.gz
443 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.2.0.tar.gz
444 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.9.tar.gz
445 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.8.tar.gz
446 Alien::Build::Plugin::Core::Download> candidate https://www.libfoo.org/download/libfoo-1.1.7.tar.gz
447 Alien::Build::Plugin::Core::Download> candidate ...
448 Alien::Build::Plugin::Core::Download> setting version based on archive to 1.2.4
449 Alien::Build::Plugin::Core::Download> downloaded libfoo-1.2.4.tar.gz
450 App::af::install> [ before build ] + bash
451 /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$ ls
452 CHANGES Makefile autoconf.ac lib
453 /tmp/fbVPu4LRTs/build_5AVn/libfoo-1.2.4$
454
455 There are a lot of other useful things that you can do with the "af"
456 command. See af for details.
457
458 Integrating with MakeMaker
459 Once you have a working alienfile you can write your "Makefile.PL".
460
461 use ExtUtils::MakeMaker;
462 use Alien::Build::MM;
463
464 my $abmm = Alien::Build::MM->new;
465
466 WriteMakefile($abmm->mm_args(
467 ABSTRACT => 'Discover or download and install libfoo',
468 DISTNAME => 'Alien-Libfoo',
469 NAME => 'Alien::Libfoo',
470 VERSION_FROM => 'lib/Alien/Libfoo.pm',
471 CONFIGURE_REQUIRES => {
472 'Alien::Build::MM' => 0,
473 },
474 BUILD_REQUIRES => {
475 'Alien::Build::MM' => 0,
476 },
477 PREREQ_PM => {
478 'Alien::Base' => 0,
479 },
480 # If you are going to write the recommended
481 # tests you will will want these:
482 TEST_REQUIRES => {
483 'Test::Alien' => 0,
484 'Test2::V0' => 0,
485 },
486 ));
487
488 sub MY::postamble {
489 $abmm->mm_postamble;
490 }
491
492 The "lib/Alien/Libfoo.pm" that goes along with it is very simple:
493
494 package Alien::Libfoo;
495
496 use strict;
497 use warnings;
498 use parent qw( Alien::Base );
499
500 1;
501
502 You are done and can install it normally:
503
504 % perl Makefile.PL
505 % make
506 % make test
507 % make install
508
509 Integrating with Module::Build
510 Please don't! Okay if you have to there is Alien::Build::MB.
511
512 Non standard configuration
513 Alien::Base support most of the things that your Alien will need, like
514 compiler flags (cflags), linker flags (libs) and binary directory
515 (bin_dir). Your library or tool may have other configuration items
516 which are not supported by default. You can store the values in the
517 alienfile into the runtime properties:
518
519 gather [
520 # standard:
521 [ 'foo-config --version libfoo', \'%{.runtime.version}' ],
522 [ 'foo-config --cflags libfoo', \'%{.runtime.cflags}' ],
523 [ 'foo-config --libs libfoo', \'%{.runtime.libs}' ],
524 # non-standard
525 [ 'foo-config --bar-baz libfoo', \'%{.runtime.bar_baz}' ],
526 ];
527
528 then you can expose them in your Alien::Base subclass:
529
530 package Alien::Libfoo;
531
532 use strict;
533 use warnings;
534 use parent qw( Alien::Base );
535
536 sub bar_baz {
537 my($self) = @_;
538 $self->runtime_prop->{bar_baz},
539 };
540
541 1;
542
543 Testing
544 (optional, but highly recommended)
545
546 You should write a test using Test::Alien to make sure that your alien
547 will work with any XS modules that are going to use it:
548
549 use Test2::V0;
550 use Test::Alien;
551 use Alien::Libfoo;
552
553 alien_ok 'Alien::Libfoo';
554
555 xs_ok do { local $/; <DATA> }, with_subtest {
556 is Foo::something(), 1, 'Foo::something() returns 1';
557 };
558
559 done_testing;
560
561 __DATA__
562 #include "EXTERN.h"
563 #include "perl.h"
564 #include "XSUB.h"
565 #include <foo.h>
566
567 MODULE = Foo PACKAGE = Foo
568
569 int something()
570
571 You can also use Test::Alien to test tools instead of libraries:
572
573 use Test2::V0;
574 use Test::Alien;
575 use Alien::Libfoo;
576
577 alien_ok 'Alien::Libfoo';
578 run_ok(['foo', '--version'])
579 ->exit_is(0);
580
581 done_testing;
582
583 You can also write tests specifically for FFI::Platypus, if your alien
584 is going to be used to write FFI bindings. (the test below is the FFI
585 equivalent to the XS example above).
586
587 use Test2::V0;
588 use Test::Alien;
589 use Alien::Libfoo;
590
591 alien_ok 'Alien::Libfoo';
592 ffi_ok { symbols => [ 'something' ] }, with_subtest {
593 # $ffi is an instance of FFI::Platypus with the lib
594 # set appropriately.
595 my($ffi) = @_;
596 my $something = $ffi->function( something => [] => 'int' );
597 is $something->call(), 1, 'Foo::something() returns 1';
598 };
599
600 If you do use "ffi_ok" you want to make sure that your alien reliably
601 produces dynamic libraries. If it isn't consistent (if for example
602 some platforms tend not to provide or build dynamic libraries), you can
603 check that "dynamic_libs" doesn't return an empty list.
604
605 ...
606 alien_ok 'Alien::Libfoo';
607 SKIP: {
608 skip "This test requires a dynamic library"
609 unless Alien::Libfoo->dynamic_libs;
610 ffi_ok { symbols [ 'something' ] }, with_subtest {
611 ...
612 };
613 }
614
615 More details on testing Alien modules can be found in the Test::Alien
616 documentation.
617
618 You can also run the tests that come with the package that you are
619 alienizing, by using a "test" block in your alienfile. Keep in mind
620 that some packages use testing tools or have other prerequisites that
621 will not be available on your users machines when they attempt to
622 install your alien. So you do not want to blindly add a test block
623 without checking what the prereqs are. For Autoconf style packages you
624 typically test a package using the "make check" command:
625
626 use alienfile;
627
628 plugin 'PkgConfig' => 'libfoo';
629
630 share {
631 ... # standard build steps.
632 test [ '%{make} check' ];
633 };
634
635 Dist::Zilla
636 (optional, mildly recommended)
637
638 You can also use the Alien::Build Dist::Zilla plugin
639 Dist::Zilla::Plugin::AlienBuild:
640
641 name = Alien-Libfoo
642 author = E. Xavier Ample <example@cpan.org>
643 license = Perl_5
644 copyright_holder = E. Xavier Ample <example@cpan.org>
645 copyright_year = 2017
646 version = 0.01
647
648 [@Basic]
649 [AlienBuild]
650
651 The plugin takes care of a lot of details like making sure that the
652 correct minimum versions of Alien::Build and Alien::Base are used. See
653 the plugin documentation for additional details.
654
655 Using your Alien
656 Once you have installed you can use your Alien. See
657 Alien::Build::Manual::AlienUser for guidance on that.
658
660 Author: Graham Ollis <plicease@cpan.org>
661
662 Contributors:
663
664 Diab Jerius (DJERIUS)
665
666 Roy Storey (KIWIROY)
667
668 Ilya Pavlov
669
670 David Mertens (run4flat)
671
672 Mark Nunberg (mordy, mnunberg)
673
674 Christian Walde (Mithaldu)
675
676 Brian Wightman (MidLifeXis)
677
678 Zaki Mughal (zmughal)
679
680 mohawk (mohawk2, ETJ)
681
682 Vikas N Kumar (vikasnkumar)
683
684 Flavio Poletti (polettix)
685
686 Salvador Fandiño (salva)
687
688 Gianni Ceccarelli (dakkar)
689
690 Pavel Shaydo (zwon, trinitum)
691
692 Kang-min Liu (劉康民, gugod)
693
694 Nicholas Shipp (nshp)
695
696 Juan Julián Merelo Guervós (JJ)
697
698 Joel Berger (JBERGER)
699
700 Petr Písař (ppisar)
701
702 Lance Wicks (LANCEW)
703
704 Ahmad Fatoum (a3f, ATHREEF)
705
706 José Joaquín Atria (JJATRIA)
707
708 Duke Leto (LETO)
709
710 Shoichi Kaji (SKAJI)
711
712 Shawn Laffan (SLAFFAN)
713
714 Paul Evans (leonerd, PEVANS)
715
716 Håkon Hægland (hakonhagland, HAKONH)
717
718 nick nauwelaerts (INPHOBIA)
719
721 This software is copyright (c) 2011-2020 by Graham Ollis.
722
723 This is free software; you can redistribute it and/or modify it under
724 the same terms as the Perl 5 programming language system itself.
725
726
727
728perl v5.34.0 2021-10-2A9lien::Build::Manual::AlienAuthor(3)