1Alien::Base::ModuleBuilUds:e:rFACQo(n3tprmi)buted Perl DAolciuemne:n:tBaatsieo:n:ModuleBuild::FAQ(3pm)
2
3
4
6 Alien::Base::ModuleBuild::FAQ - Frequently Asked Questions about
7 Alien::Base::ModuleBuild
8
10 version 1.17
11
13 perldoc Alien::Base::FAQ
14
16 NOTE: Please consider for new development of Aliens that you use
17 Alien::Build and alienfile instead. Like Alien::Base::ModuleBuild they
18 work with Alien::Base. Unlike Alien::Base::ModuleBuild they are more
19 easily customized and handle a number of corner cases better. For a
20 good place to start, please see Alien::Base::ModuleBuild::API.
21 Although the Alien-Base / Alien-Build team will continue to maintain
22 this module, (we will continue to fix bugs where appropriate), we
23 aren't adding any new features to this module.
24
25 This document serves to answer the most frequently asked questions made
26 by Alien::Base authors.
27
28 What is Alien and Alien::Base?
29 Alien is a Perl namespace for defining dependencies in CPAN for
30 libraries and tools which are not "native" to CPAN. For a manifesto
31 style description of the Why, and How see Alien. Alien::Base is a base
32 class and framework for creating Alien distributions. The idea is to
33 address as many of the common challenges to developing Alien modules in
34 the base class to simplify the process.
35
36 How do I specify a minimum or exact version requirement for packages that
37 use pkg-config?
38 The "alien_version_check" attribute to Alien::Base::ModuleBuild will be
39 executed to determine if the library is provided by the operating
40 system. The default for this is "%{pkg_config} --modversion %n" which
41 simply checks to see if any version of that package is available, and
42 prints the version number. You can use the "--atleast-version",
43 "--exact-version" options to require a specific range of versions, but
44 these flags do not work with the "--modversion" flag, so be sure to
45 invoke separately.
46
47 use Alien::Base::ModuleBuild;
48 Alien::Base::ModuleBuild->new(
49 dist_name => 'Alien::Foo',
50 alien_name => 'foo',
51 configure_requires => { 'Alien::Base::ModuleBuild' => '0.022' }, # required for %{pkg_config}
52 alien_version_check => '%{pkg_config} --atleast-version 1.2.3 %n && %{pkg_config} --modversion %n',
53 ...
54 )->create_build_script;
55
56 It is better to use the built in "%{pkg_config}" helper as it will use
57 the system provided pkg-config if it is available and fallback on the
58 pure perl PkgConfig if not.
59
60 You can also use "--exact-version" to specify an exact version.
61
62 How to create an Alien module for packages that do not support pkg-config?
63 Although Alien::Base and Alien::Base::ModuleBuild assume packages come
64 with a "pkg-config" ".pc" file to determine compiler and linker flags
65 by default, you can implement an Alien module for packages that do use
66 "pkg-config" by following these tasks:
67
68 subclass Alien::Base::ModuleBuild and implement
69 "alien_check_installed_version"
70 Create a subclass of Alien::Base::ModuleBuild and put it in the
71 "inc" directory of your distribution so that it can be used during
72 install but won't be installed.
73
74 # inc/My/ModuleBuild.pm
75 package My::ModuleBuild;
76
77 use parent 'Alien::Base::ModuleBuild';
78
79 sub alien_check_installed_version {
80 my($class) = @_;
81
82 # determine if your library is already provided by the system
83 my $version = ...;
84
85 # return false if the library is NOT provided by the system
86 return unless defined $version;
87
88 # otherwise return the version detected
89 # (if you cannot determine the version it
90 # is usually sufficient to return a true value)
91 return $version;
92 }
93
94 There are number of methods you can use to determine if the system
95 provides your library. From Perl methods include Devel::CheckLib,
96 ExtUtils::CBuilder, ExtUtils::CChecker, Config::AutoConf,
97 FFI::CheckLib among others. It is also frequently possible to
98 determine if a library is installed using a "-config" suffixed
99 program. For example "libxml2" comes with xml2-config which
100 provides the existence, compiler and linker flags it needs. In my
101 experience, however, most packages that provide a "-config"
102 suffixed program also provide a "pkg-config" interface as well.
103
104 implement "alien_check_built_version" in your Alien::Base::ModuleBuild
105 subclass
106 You should also implement "alien_check_build_version" which will be
107 executed from the package build root once the package is
108 successfully built.
109
110 # inc/My/ModuleBuild.pm
111 package My::ModuleBuild;
112
113 ...
114
115 sub alien_check_built_version {
116 my($self) = @_;
117
118 my $version = ...
119
120 # (Again, if you cannot determine the version,
121 # it is usually sufficent to return a true value)
122 return $version;
123 }
124
125 set "alien_provides_cflags" and "alien_provides_libs" in "Build.PL".
126 Add something like this to your "Build.PL":
127
128 # Build.PL
129 use lib 'inc';
130 use My::ModuleBuild;
131
132 My::ModuleBuild->new(
133 ...
134 alien_provides_cflags => '-I/usr/include/foo',
135 alien_provides_libs => '-L/usr/lib/foo -lfoo',
136 ...
137 );
138
139 Note that it is frequently sufficient to provide
140 "alien_provides_libs" and the appropriate "-l" flag. These flags
141 will be used in the event that the system package can be found. It
142 is a good idea to verify that these flags do indeed work in
143 "alien_check_installed_version" above.
144
145 For a fully implemented example, see Alien::Libbz2.
146
147 How do I test my package once it is built (before it is installed)?
148 There are many ways to test Alien modules before (or after) they are
149 installed, but instead of rolling your own, consider using Test::Alien
150 which is light on dependencies and will test your module very closely
151 to the way that it will actually be used. That is to say by building a
152 mini XS or FFI extension and using it. It even has tests for tool
153 oriented Alien distributions (like Alien::gmake and Alien::patch).
154 Here is a short example, there are many others included with the
155 Test::Alien documentation:
156
157 use Test2::V0;
158 use Test::Alien 0.05;
159 use Alien::Editline;
160
161 alien_ok 'Alien::Editline';
162 my $xs = do { local $/; <DATA> };
163 xs_ok $xs, with_subtest {
164 my($module) = @_;
165 ok $module->version;
166 };
167
168 done_testing;
169
170 __DATA__
171
172 #include "EXTERN.h"
173 #include "perl.h"
174 #include "XSUB.h"
175 #include <editline/readline.h>
176
177 /* having a string parameter that we ignore
178 allows us to call this as a class method */
179 const char *
180 version(const char *class)
181 {
182 return rl_library_version;
183 }
184
185 MODULE = TA_MODULE PACKAGE = TA_MODULE
186
187 const char *version(class);
188 const char *class;
189
190 How do I patch packages that need minor (or major) alterations?
191 One approach is to create a unified diff for patches that you want to
192 apply and simply run patch on them. The Alien::patch and the
193 "%{patch}" helper can be used like this:
194
195 # Build.PL
196 use Alien::Base::ModuleBuild;
197
198 Alien::Base::ModuleBuild->new(
199 ...
200 alien_bin_requires => {
201 'Alien::patch' => 0.06, # needed for %{patch} helper
202 },
203 alien_build_commands => [
204 '%{patch} -p1 < ../../patch/mypackage.patch',
205 ...
206 ],
207 ...
208 )->create_build_script;
209
210 Create a folder in your distribution root called "patch" and place the
211 "mypackage.patch" file in there. Since the "patch" command will be
212 executed in the package root instead of the distribution root, you need
213 to use a relative path prefixed by "../..". Here we use Alien::patch
214 to provide patch even in environments where it is not provided.
215
216 A more powerful approach to patching is to write a perl subroutine to
217 modify the source after it has been extracted. One way to do this is
218 to create a module in your distribution's inc directory that does the
219 patching (modules in inc can be used during build/test but won't be
220 installed):
221
222 # inc/My/AlienPatch.pm
223 package My::AlienPatch;
224
225 # add this sub to the main namespace
226 # so we don't need to quote or escape
227 # anything below
228 sub main::alien_patch {
229 # is executed in the package root,
230 # make what ever changes you need to
231 # to the source here.
232 }
233
234 1;
235
236 # Build.PL
237 use Alien::Base::ModuleBuild;
238
239 Alien::Base::ModuleBuild->new(
240 ...
241 alien_build_commands => [
242 # %x will be replaced by path for calling Perl
243 # from the command line
244 "%x -I../../inc -MMy::AlienPatch -e alien_patch",
245 ...
246 ],
247 ...
248 )->create_build_script;
249
250 How do I build a package that uses build system?
251 autoconf
252
253 By default Alien::Base::ModuleBuild assumes a package with an autoconf
254 style "configure" script. The default is
255
256 # Build.PL
257 use Alien::Base::ModuleBuild;
258 Alien::Base::ModuleBuild->new(
259 ...
260 alien_build_commands => [
261 '%c --prefix=%s',
262 'make',
263 ],
264 alien_install_commands => [
265 'make install',
266 ],
267 ...
268 )->create_build_script;
269
270 There are a couple of short cuts here, %c indicates the platform
271 independent method for executing the "configure" script, plus any
272 normal autoconf flags that are appropriate for Perl Alien libraries.
273 The %c also tells Alien::Base::ModuleBuild to use Alien::MSYS on
274 Windows platforms and to add that as a dependency. The %s is a
275 placeholder for the location to which the package will be installed.
276 This is normally in a share directory specific to your distribution.
277
278 autoconf-like
279
280 If you see an error like this:
281
282 Unknown option "--with-pic".
283
284 It may be because your package provides a "configure" script that
285 provides an autoconf-style interface, but is not actually autoconf.
286 Alien::Base::ModuleBuild is aggressive in using the "--with-pic" option
287 because when supported by autoconf it produces position independent
288 code (important for reliably building XS extensions), and when not
289 supported autoconf simply ignores the option. Unfortunately some
290 autoconf-style "configure" scripts consider it an error when they see
291 options that they do not recognize. You can tell
292 Alien::Base::ModuleBuild to not use the "--with-pic" option via the
293 "alien_autoconf_with_pic" property:
294
295 # Build.PL
296 use Alien::Base::ModuleBuild;
297 Alien::Base::ModuleBuild->new(
298 ...
299 alien_autoconf_with_pic => 0,
300 ...
301 )->create_build_script;
302
303 CMAKE
304
305 You probably cannot count on CMake being available on most platforms.
306 Fortunately, there is an alien distribution Alien::CMake which will
307 either use the CMake provided by the operating system, or download and
308 install it for you. You can use this from your "Build.PL" with the
309 "alien_bin_requires" property:
310
311 # Build.PL
312 use Alien::Base::ModuleBuild;
313 use Config;
314 Alien::Base::ModuleBuild->new(
315 ...
316 alien_bin_requires => {
317 'Alien::CMake' => 0.07,
318 },
319 alien_build_commands => [
320 # acutal required arguments may vary
321 "cmake -G 'Unix Makefiles' -DCMAKE_MAKE_PROGRAM=$Config{make} -DCMAKE_INSTALL_PREFIX:PATH=%s",
322 "$Config{make}",
323 ],
324 alien_install_commands => [
325 "$Config{make} install",
326 ],
327 ...
328 )->create_build_script;
329
330 vanilla Makefiles?
331
332 If you want to use the same "make" as Perl, you can use Config:
333
334 # Build.PL
335 use Alien::Base::ModuleBuild;
336 use Config;
337 Alien::Base::ModuleBuild->new(
338 ...
339 alien_build_commands => [
340 "$Config{make}",
341 ],
342 alien_install_commands => [
343 "$Config{make} install",
344 ],
345 ...
346 )->create_build_script;
347
348 GNU Makefiles?
349
350 Some packages require GNU Make's unique syntax. Perl's Config provides
351 an entry for "gmake", but it is frequently wrong. Do not depend on it.
352 Instead you can use Alien::gmake to provide a real GNU Make (either
353 from the operating system, or built from source):
354
355 # Build.PL
356 use Alien::Base::ModuleBuild;
357
358 Alien::Base::ModuleBuild->new(
359 ...
360 alien_bin_requires => {
361 'Alien::gmake' => 0.11, # needed for %{gmake} helper
362 },
363 alien_build_commands => [
364 "%{gmake}",
365 ],
366 alien_install_commands => [
367 "%{gmake} install",
368 ],
369 ...
370 )->create_build_script;
371
372 When debugging my package build, I get different results!
373 If you get results from running the commands in your shell different to
374 what happens when your "Alien::" distribution attempts to build, it may
375 be because your environment is different than the one that your
376 distribution is using. For example, if you use Alien::CMake or
377 Alien::gmake to build with specific tools that are provided by your
378 operating system, Alien::Base::ModuleBuild will adjust the path before
379 executing build and install commands.
380
381 In the alien build directory (usually "_alien") you will find
382 environment files that you can source into your shell ("env.csh" for
383 tcsh and "env.sh" for bourne based shells), which should provide the
384 identical environment used by the build process in order to
385 troubleshoot the build manually.
386
387 % source _alien/env.sh
388
389 Can/Should I write a tool oriented Alien module using "Alien::Base" that
390 provides executables instead of a library?
391 Certainly. The original intent was to provide libraries, but tools are
392 also quite doable using the "Alien::Base" tool set. A simple minded
393 example of this which is fairly easy to replicate is Alien::m4.
394
395 In general, this means specifying a subclass in your "Build.PL" and
396 bundling it in your distribution "inc" directory.
397
398 "Build.PL":
399
400 ...
401 use lib 'inc';
402 use My::ModuleBuild;
403
404 My::ModuleBuild->new(
405 ...
406 )->create_build_script;
407
408 "inc/My/ModuleBuild.pm":
409
410 package My::ModuleBuild;
411
412 use strict;
413 use warnings;
414 use parent 'Alien::Base::ModuleBuild';
415 use Capture::Tiny qw( capture );
416
417 sub alien_check_installed_version
418 {
419 # see Alien::Base::ModuleBuild#alien_check_installed_version for details
420
421 my($self) = @_;
422 my($stdout, $stderr) = capture { system 'mytool', '--version' };
423
424 # return empty list if the tool is unavailable on the system,
425 # or unacceptable.
426 return if $! || ...;
427
428 # parse from stdout or stderr
429 my $version = ...;
430 return $version;
431 }
432
433 sub alien_check_built_version
434 {
435 # see Alien::Base::ModuleBuild#alien_check_built_version for details
436
437 # return empty list if the tool version cannot be found, or if it
438 # is unacceptable. Note that this will cause a failure, so "unknown"
439 # may be reasonable if the tool version cannot be determined.
440 return if ...;
441
442 # determine from the tool itself, or the current directory.
443 my $version = ...;
444 return $version;
445 }
446
447 1;
448
449 As usual your "Alien::MyTool" class will simply be a subclass of
450 Alien::Base. If you tool is installed in a "bin" directory, you are
451 done, the default "bin_dir" implementation should work for you.
452 Otherwise you may need to provide an alternate implementation:
453
454 package Alien::MyTool;
455
456 use strict;
457 use warnings;
458 use parent 'Alien::Base';
459
460 sub bin_dir
461 {
462 # see Alien::Base#bin_dir for details
463 # You only need to override the default implementation if your tool
464 # does not install into the standard "bin" directory.
465
466 my($class) = @_;
467
468 # normally for system installs the tool should already be in your
469 # PATH, so return an empty list.
470 return if $class->install_type eq 'system';
471
472 # install_type = share
473 my $dist_dir = $class->dist_dir;
474 return ("$dist_dir/some/bin", "$dist_dir/some/other/bin");
475 }
476
477 1;
478
479 Now once your tool based Alien is installed you can use the "bin_dir"
480 method to update the "PATH" as necessary:
481
482 use Alien::MyTool;
483 use Env qw( @PATH );
484
485 unshift @PATH, Alien::MyTool->bin_dir;
486 system 'mytool';
487
488 How do I use "Alien::Base" from "Dist::Zilla"
489 For creating Alien::Base based dists from Dist::Zilla you can use the
490 plugin Dist::Zilla::Plugin::Alien.
491
492 How do I check the built version if my library doesn't provide a ".pc"
493 file.
494 The default implementation of "alien_check_built_version" uses several
495 heuristics, but leans heavily on "pkg-config" style ".pc" files, so if
496 your library or tool does not provide a ".pc", the version may not be
497 detected and your build may fail.
498
499 A lot of libraries are bundled as tarballs with the version in the
500 directory name that they are extracted into, and the current directory
501 when "alien_check_built_version" is called is the build root, so you
502 can use "File::chdir" as an easy way to determine the version number:
503
504 package My::ModuleBuild;
505
506 use strict;
507 use warnings;
508 use parent 'Alien::Base::ModuleBuild';
509 use File::chdir; # provides @CWD
510
511 sub alien_check_built_version
512 {
513 my $dir_name = $CWD[-1];
514
515 if($dir_name =~ /^libfoo-([0-9\.]+)$/) {
516 return $1;
517 } else {
518 # Note that this will trigger a build failure
519 return;
520 }
521 }
522
523 1;
524
525 Using File::chdir and @CWD is a common idiom in Alien::Base, because
526 File::chdir is already a dependency of Alien::Base. For packages that
527 do not provide a version number in the extracted directory, you may
528 require some creativity.
529
530 I have question not listed here!
531 There are a number of forums available to people working on Alien and
532 Alien::Base modules:
533
534 "#native" on irc.perl.org
535 This is intended for native interfaces in general and so is a good
536 place for questions about Alien generally or Alien::Base
537 specifically.
538
539 mailing list
540 The "perl5-alien" google group is intended for Alien issues
541 generally, including Alien::Base.
542
543 <https://groups.google.com/forum/#!forum/perl5-alien>
544
545 Open a support ticket
546 If you have an issue with Alien::Base itself, then please open a
547 support ticket on the project's GitHub issue tracker.
548
549 <https://github.com/PerlAlien/Alien-Base-ModuleBuild/issues>
550
552 • Alien::Base
553
554 • Alien::Base::ModuleBuild
555
556 • Alien::Base::ModuleBuild::API
557
559 Original author: Joel A Berger <joel.a.berger@gmail.com>
560
561 Current maintainer: Graham Ollis <plicease@cpan.org>
562
563 Contributors:
564
565 David Mertens (run4flat)
566
567 Mark Nunberg (mordy, mnunberg)
568
569 Christian Walde (Mithaldu)
570
571 Brian Wightman (MidLifeXis)
572
573 Graham Ollis (plicease)
574
575 Zaki Mughal (zmughal)
576
577 mohawk2
578
579 Vikas N Kumar (vikasnkumar)
580
581 Flavio Poletti (polettix)
582
583 Salvador Fandiño (salva)
584
585 Gianni Ceccarelli (dakkar)
586
587 Pavel Shaydo (zwon, trinitum)
588
589 Kang-min Liu (劉康民, gugod)
590
591 Nicholas Shipp (nshp)
592
593 Petr Písař (ppisar)
594
595 Alberto Simões (ambs)
596
598 This software is copyright (c) 2012-2022 by Joel A Berger.
599
600 This is free software; you can redistribute it and/or modify it under
601 the same terms as the Perl 5 programming language system itself.
602
603
604
605perl v5.38.0 2023-07-20Alien::Base::ModuleBuild::FAQ(3pm)