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