File Coverage

blib/lib/Alien/Base.pm
Criterion Covered Total %
statement 249 310 80.3
branch 87 146 59.5
condition 16 36 44.4
subroutine 40 43 93.0
pod 22 26 84.6
total 414 561 73.8


line stmt bran cond sub pod time code
1             package Alien::Base;
2              
3 12     12   8490 use strict;
  12         24  
  12         359  
4 12     12   67 use warnings;
  12         103  
  12         309  
5 12     12   252 use 5.008004;
  12         45  
6 12     12   56 use Carp;
  12         19  
  12         927  
7 12     12   857 use Path::Tiny ();
  12         10806  
  12         245  
8 12     12   59 use Scalar::Util qw/blessed/;
  12         22  
  12         778  
9 12     12   1154 use Capture::Tiny 0.17 qw/capture_stdout/;
  12         40046  
  12         615  
10 12     12   1894 use Text::ParseWords qw/shellwords/;
  12         5013  
  12         1451  
11              
12             # ABSTRACT: Base classes for Alien:: modules
13             our $VERSION = '2.47'; # VERSION
14              
15              
16             sub import {
17 3     3   34 my $class = shift;
18              
19 3 50       9 return if $class eq __PACKAGE__;
20              
21 3 50       16 return if $class->runtime_prop;
22              
23 0 0       0 return if $class->install_type('system');
24              
25 0         0 require DynaLoader;
26              
27             # Sanity check in order to ensure that dist_dir can be found.
28             # This will throw an exception otherwise.
29 0         0 $class->dist_dir;
30              
31             # get a reference to %Alien::MyLibrary::AlienLoaded
32             # which contains names of already loaded libraries
33             # this logic may be replaced by investigating the DynaLoader arrays
34 0         0 my $loaded = do {
35 12     12   81 no strict 'refs';
  12         28  
  12         463  
36 12     12   60 no warnings 'once';
  12         26  
  12         43756  
37 0         0 \%{ $class . "::AlienLoaded" };
  0         0  
38             };
39              
40 0         0 my @libs = $class->split_flags( $class->libs );
41              
42 0         0 my @L = grep { s/^-L// } map { "$_" } @libs; ## no critic (ControlStructures::ProhibitMutatingListFunctions)
  0         0  
  0         0  
43 0         0 my @l = grep { /^-l/ } @libs;
  0         0  
44              
45 0         0 unshift @DynaLoader::dl_library_path, @L;
46              
47 0         0 my @libpaths;
48 0         0 foreach my $l (@l) {
49 0 0       0 next if $loaded->{$l};
50              
51 0         0 my $path = DynaLoader::dl_findfile( $l );
52 0 0       0 unless ($path) {
53 0         0 carp "Could not resolve $l";
54 0         0 next;
55             }
56              
57 0         0 push @libpaths, $path;
58 0         0 $loaded->{$l} = $path;
59             }
60              
61 0         0 push @DynaLoader::dl_resolve_using, @libpaths;
62              
63 0         0 my @librefs = map { DynaLoader::dl_load_file( $_, 0x01 ) } grep !/\.(a|lib)$/, @libpaths;
  0         0  
64 0         0 push @DynaLoader::dl_librefs, @librefs;
65              
66             }
67              
68              
69             sub _dist_dir ($)
70             {
71 32     32   61 my($dist_name) = @_;
72              
73 32         93 my @pm = split /-/, $dist_name;
74 32         57 $pm[-1] .= ".pm";
75              
76 32         70 foreach my $inc (@INC)
77             {
78 32         160 my $pm = Path::Tiny->new($inc, @pm);
79 32 50       1269 if(-f $pm)
80             {
81 32         581 my $share = Path::Tiny->new($inc, qw( auto share dist ), $dist_name );
82 32 100       1020 if(-d $share)
83             {
84 31         497 return $share->absolute->stringify;
85             }
86 1         36 last;
87             }
88             }
89 1         213 Carp::croak("unable to find dist share directory for $dist_name");
90             }
91              
92             sub dist_dir {
93 22     22 1 55 my $class = shift;
94              
95 22   33     80 my $dist = blessed $class || $class;
96 22         77 $dist =~ s/::/-/g;
97              
98 22 50       52 my $dist_dir =
99             $class->config('finished_installing')
100             ? _dist_dir $dist
101             : $class->config('working_directory');
102              
103 22 50 33     2091 croak "Failed to find share dir for dist '$dist'"
104             unless defined $dist_dir && -d $dist_dir;
105              
106 22         293 return $dist_dir;
107             }
108              
109              
110 6     6 1 14 sub new { return bless {}, $_[0] }
111              
112             sub _flags
113             {
114 38     38   65 my($class, $key) = @_;
115              
116 38         61 my $config = $class->runtime_prop;
117 38         64 my $flags = $config->{$key};
118              
119 38         49 my $prefix = $config->{prefix};
120 38 50       151 $prefix =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
121 38         56 my $distdir = $config->{distdir};
122 38 50       86 $distdir =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
123              
124 38 100       69 if($prefix ne $distdir)
125             {
126             $flags = join ' ', map {
127 34         70 my $flag = $_;
  86         3074  
128 86         342 $flag =~ s/^(-I|-L|-LIBPATH:)?\Q$prefix\E/$1$distdir/;
129 86         148 $flag =~ s/(\s)/\\$1/g;
130 86         192 $flag;
131             } $class->split_flags($flags);
132             }
133              
134 38         269 $flags;
135             }
136              
137              
138             sub cflags {
139 12     12 1 6120 my $class = shift;
140 12 100       47 return $class->runtime_prop ? $class->_flags('cflags') : $class->_pkgconfig_keyword('Cflags');
141             }
142              
143              
144             sub cflags_static {
145 8     8 1 1605 my $class = shift;
146 8 50       16 return $class->runtime_prop ? $class->_flags('cflags_static') : $class->_pkgconfig_keyword('Cflags', 'static');
147             }
148              
149              
150             sub libs {
151 14     14 1 2691 my $class = shift;
152 14 100       29 return $class->runtime_prop ? $class->_flags('libs') : $class->_pkgconfig_keyword('Libs');
153             }
154              
155              
156             sub libs_static {
157 8     8 1 1838 my $class = shift;
158 8 50       16 return $class->runtime_prop ? $class->_flags('libs_static') : $class->_pkgconfig_keyword('Libs', 'static');
159             }
160              
161              
162             sub version {
163 13     13 1 1590 my $self = shift;
164             return $self->runtime_prop
165             ? $self->runtime_prop->{version}
166 13 100       129 : do {
167 2         29 my $version = $self->config('version');
168 2         8 chomp $version;
169 2         8 $version;
170             };
171             }
172              
173              
174             sub atleast_version {
175 3     3 1 520 my $self = shift;
176 3         6 my ($wantver) = @_;
177              
178 3 100       7 defined(my $version = $self->version) or
179             croak "$self has no defined ->version";
180              
181 2         11 return $self->version_cmp($version, $wantver) >= 0;
182             }
183              
184             sub exact_version {
185 2     2 1 445 my $self = shift;
186 2         3 my ($wantver) = @_;
187              
188 2 100       5 defined(my $version = $self->version) or
189             croak "$self has no defined ->version";
190              
191 1         3 return $self->version_cmp($version, $wantver) == 0;
192             }
193              
194             sub max_version {
195 2     2 1 307 my $self = shift;
196 2         5 my ($wantver) = @_;
197              
198 2 100       5 defined(my $version = $self->version) or
199             croak "$self has no defined ->version";
200              
201 1         3 return $self->version_cmp($version, $wantver) <= 0;
202             }
203              
204              
205             # Sort::Versions isn't quite the same algorithm because it differs in
206             # behaviour with leading zeroes.
207             # See also https://dev.gentoo.org/~mgorny/pkg-config-spec.html#version-comparison
208             sub version_cmp {
209 4     4 1 5 shift;
210 4         26 my @x = (shift =~ m/([0-9]+|[a-z]+)/ig);
211 4         14 my @y = (shift =~ m/([0-9]+|[a-z]+)/ig);
212              
213 4   100     15 while(@x and @y) {
214 9         14 my $x = shift @x; my $x_isnum = $x =~ m/[0-9]/;
  9         25  
215 9         11 my $y = shift @y; my $y_isnum = $y =~ m/[0-9]/;
  9         14  
216              
217 9 50 33     20 if($x_isnum and $y_isnum) {
    0 0        
218             # Numerical comparison
219 9 100       39 return $x <=> $y if $x != $y;
220             }
221             elsif(!$x_isnum && !$y_isnum) {
222             # Alphabetic comparison
223 0 0       0 return $x cmp $y if $x ne $y;
224             }
225             else {
226             # Of differing types, the numeric one is newer
227 0         0 return $x_isnum - $y_isnum;
228             }
229             }
230              
231             # Equal so far; the longer is newer
232 2         22 return @x <=> @y;
233             }
234              
235              
236             sub install_type {
237 24     24 1 1242 my $self = shift;
238 24         80 my $type = $self->config('install_type');
239 24 100       125 return @_ ? $type eq $_[0] : $type;
240             }
241              
242             sub _pkgconfig_keyword {
243 4     4   52 my $self = shift;
244 4         8 my $keyword = shift;
245 4         6 my $static = shift;
246              
247             # use pkg-config if installed system-wide
248 4 100       29 if ($self->install_type('system')) {
249 2         6 my $name = $self->config('name');
250 2         386 require Alien::Base::PkgConfig;
251 2 50       19 my $command = Alien::Base::PkgConfig->pkg_config_command . " @{[ $static ? '--static' : '' ]} --\L$keyword\E $name";
  2         37  
252              
253 2         14 $! = 0;
254 2     2   140 chomp ( my $pcdata = capture_stdout { system( $command ) } );
  2         283411  
255              
256             # if pkg-config fails for whatever reason, then we try to
257             # fallback on alien_provides_*
258 2 50 33     3020 $pcdata = '' if $! || $?;
259              
260 2         60 $pcdata =~ s/\s*$//;
261              
262 2 50       79 if($self->config('system_provides')) {
263 2 50       30 if(my $system_provides = $self->config('system_provides')->{$keyword}) {
264 0 0       0 $pcdata = length $pcdata ? "$pcdata $system_provides" : $system_provides;
265             }
266             }
267              
268 2         64 return $pcdata;
269             }
270              
271             # use parsed info from build .pc file
272 2         23 my $dist_dir = $self->dist_dir;
273 2         11 my @pc = $self->_pkgconfig(@_);
274             my @strings =
275             grep defined,
276 2         4 map { $_->keyword($keyword,
  2         9  
277             #{ pcfiledir => $dist_dir }
278             ) }
279             @pc;
280              
281 2 50 33     10 if(defined $self->config('original_prefix') && $self->config('original_prefix') ne $self->dist_dir)
282             {
283 2         6 my $dist_dir = $self->dist_dir;
284 2 50       9 $dist_dir =~ s{\\}{/}g if $^O eq 'MSWin32';
285 2         5 my $old = quotemeta $self->config('original_prefix');
286             @strings = map {
287 3         361 my $flag = $_;
288 3         49 $flag =~ s{^(-I|-L|-LIBPATH:)?($old)}{$1.$dist_dir}e;
  2         10  
289 3         6 $flag =~ s/(\s)/\\$1/g;
290 3         8 $flag;
291 2         5 } map { $self->split_flags($_) } @strings;
  2         16  
292             }
293              
294 2         13 return join( ' ', @strings );
295             }
296              
297             sub _pkgconfig {
298 2     2   4 my $self = shift;
299 2         2 my %all = %{ $self->config('pkgconfig') };
  2         5  
300              
301             # merge in found pc files
302 2         8 require File::Find;
303             my $wanted = sub {
304 14 50 66 14   776 return if ( -d or not /\.pc$/ );
305 0         0 require Alien::Base::PkgConfig;
306 0         0 my $pkg = Alien::Base::PkgConfig->new($_);
307 0         0 $all{$pkg->{package}} = $pkg;
308 2         14 };
309 2         7 File::Find::find( $wanted, $self->dist_dir );
310              
311 2 50       11 croak "No Alien::Base::PkgConfig objects are stored!"
312             unless keys %all;
313              
314             # Run through all pkgconfig objects and ensure that their modules are loaded:
315 2         5 for my $pkg_obj (values %all) {
316 4         15 my $perl_module_name = blessed $pkg_obj;
317 4         8 my $pm = "$perl_module_name.pm";
318 4         19 $pm =~ s/::/\//g;
319 4         6 eval { require $pm };
  4         17  
320             }
321              
322 2 50       5 return @all{@_} if @_;
323              
324 2         4 my $manual = delete $all{_manual};
325              
326 2 50       6 if (keys %all) {
327 2         12 return values %all;
328             } else {
329 0         0 return $manual;
330             }
331             }
332              
333              
334             # helper method to call Alien::MyLib::ConfigData->config(@_)
335             sub config {
336 72     72 1 119 my $class = shift;
337 72   33     273 $class = blessed $class || $class;
338              
339 72 100       173 if(my $ab_config = $class->runtime_prop)
340             {
341 44         76 my $key = shift;
342 44         159 return $ab_config->{legacy}->{$key};
343             }
344              
345 28         74 my $config = $class . '::ConfigData';
346 28         58 my $pm = "$class/ConfigData.pm";
347 28         110 $pm =~ s{::}{/}g;
348 28         47 eval { require $pm };
  28         878  
349              
350 28 50       89 if($@)
351             {
352 0         0 warn "Cannot find either a share directory or a ConfigData module for $class.\n";
353 0         0 my $pm = "$class.pm";
354 0         0 $pm =~ s{::}{/}g;
355 0 0       0 warn "($class loaded from $INC{$pm})\n" if $INC{$pm};
356 0         0 warn "Please see https://metacpan.org/pod/distribution/Alien-Build/lib/Alien/Build/Manual/FAQ.pod#Cannot-find-either-a-share-directory-or-a-ConfigData-module\n";
357 0         0 die $@;
358             }
359              
360 28         115 return $config->config(@_);
361             }
362              
363             # helper method to split flags based on the OS
364             sub split_flags {
365 39     39 0 56 my ($class, $line) = @_;
366 39 50       82 if( $^O eq 'MSWin32' ) {
367 0         0 $class->split_flags_windows($line);
368             } else {
369             # $os eq 'Unix'
370 39         72 $class->split_flags_unix($line);
371             }
372             }
373              
374             sub split_flags_unix {
375 40     40 0 4317 my ($class, $line) = @_;
376 40         103 shellwords($line);
377             }
378              
379             sub split_flags_windows {
380             # NOTE a better approach would be to write a function that understands cmd.exe metacharacters.
381 3     3 0 3199 my ($class, $line) = @_;
382              
383             # Double the backslashes so that when they are unescaped by shellwords(),
384             # they become a single backslash. This should be fine on Windows since
385             # backslashes are not used to escape metacharacters in cmd.exe.
386 3         11 $line =~ s,\\,\\\\,g;
387 3         8 shellwords($line);
388             }
389              
390              
391             sub dynamic_libs {
392 5     5 1 10799 my ($class) = @_;
393              
394 5         25 require FFI::CheckLib;
395              
396 5         8 my @find_lib_flags;
397              
398 5 100       12 if($class->install_type('system')) {
399              
400 4 50       9 if(my $prop = $class->runtime_prop)
401             {
402 4 50       14 if($prop->{ffi_checklib}->{system})
403             {
404 0         0 push @find_lib_flags, @{ $prop->{ffi_checklib}->{system} };
  0         0  
405             }
406             return FFI::CheckLib::find_lib( lib => $prop->{ffi_name}, @find_lib_flags )
407 4 100       16 if defined $prop->{ffi_name};
408             }
409              
410 3         7 my $name = $class->config('ffi_name');
411 3 50       8 unless(defined $name)
412             {
413 3         4 $name = $class->config('name');
414 3 50       8 $name = '' unless defined $name;
415             # strip leading lib from things like libarchive or libffi
416 3         14 $name =~ s/^lib//;
417             # strip trailing version numbers
418 3         5 $name =~ s/-[0-9\.]+$//;
419             }
420              
421 3         3 my @libpath;
422 3         9 foreach my $flag ($class->split_flags($class->libs))
423             {
424 4 100       181 if($flag =~ /^-L(.*)$/)
425             {
426 1         3 push @libpath, $1;
427             }
428             }
429              
430 3         18 return FFI::CheckLib::find_lib(lib => $name, libpath => \@libpath, @find_lib_flags );
431              
432             } else {
433              
434 1         5 my $dir = $class->dist_dir;
435 1         6 my $dynamic = Path::Tiny->new($class->dist_dir, 'dynamic');
436              
437 1 50       36 if(my $prop = $class->runtime_prop)
438             {
439 1 50       5 if($prop->{ffi_checklib}->{share})
440             {
441 0         0 push @find_lib_flags, @{ $prop->{ffi_checklib}->{share_flags} };
  0         0  
442             }
443             }
444              
445 1 50       4 if(-d $dynamic)
446             {
447 1         20 return FFI::CheckLib::find_lib(
448             lib => '*',
449             libpath => "$dynamic",
450             systempath => [],
451             );
452             }
453              
454 0         0 return FFI::CheckLib::find_lib(
455             lib => '*',
456             libpath => $dir,
457             systempath => [],
458             recursive => 1,
459             );
460             }
461             }
462              
463              
464             sub bin_dir {
465 7     7 1 1912 my ($class) = @_;
466 7 100       41 if($class->install_type('system'))
467             {
468 4         13 my $prop = $class->runtime_prop;
469 4 50       11 return () unless defined $prop;
470 4 50       22 return () unless defined $prop->{system_bin_dir};
471 0 0       0 return ref $prop->{system_bin_dir} ? @{ $prop->{system_bin_dir} } : ($prop->{system_bin_dir});
  0         0  
472             }
473             else
474             {
475 3         23 my $dir = Path::Tiny->new($class->dist_dir, 'bin');
476 3 50       89 return -d $dir ? ("$dir") : ();
477             }
478             }
479              
480              
481              
482             sub dynamic_dir {
483 2     2 1 1478 my ($class) = @_;
484 2 100       6 if($class->install_type('system'))
485             {
486 1         4 return ();
487             }
488             else
489             {
490 1         3 my $dir = Path::Tiny->new($class->dist_dir, 'dynamic');
491 1 50       30 return -d $dir ? ("$dir") : ();
492             }
493             }
494              
495              
496             sub alien_helper {
497 0     0 1 0 {};
498             }
499              
500              
501             sub inline_auto_include {
502 0     0 1 0 my ($class) = @_;
503 0 0       0 return [] unless $class->config('inline_auto_include');
504 0         0 $class->config('inline_auto_include')
505             }
506              
507             sub Inline {
508 0     0 0 0 my ($class, $language) = @_;
509 0 0       0 return unless defined $language;
510 0 0       0 return if $language !~ /^(C|CPP)$/;
511 0         0 my $config = {
512             # INC should arguably be for -I flags only, but
513             # this improves compat with ExtUtils::Depends.
514             # see gh#107, gh#108
515             INC => $class->cflags,
516             LIBS => $class->libs,
517             };
518              
519 0 0       0 if (@{ $class->inline_auto_include } > 0) {
  0         0  
520 0         0 $config->{AUTO_INCLUDE} = join "\n", map { "#include \"$_\"" } @{ $class->inline_auto_include };
  0         0  
  0         0  
521             }
522              
523 0         0 $config;
524             }
525              
526              
527             {
528             my %alien_build_config_cache;
529              
530             sub runtime_prop
531             {
532 201     201 1 764 my($class) = @_;
533              
534 201 100       373 if(ref($class))
535             {
536             # called as an instance method.
537 44         74 my $self = $class;
538 44         63 $class = ref $self;
539 44 50       142 return $self->{_alt}->{runtime_prop} if defined $self->{_alt};
540             }
541              
542             return $alien_build_config_cache{$class} if
543 157 100       484 exists $alien_build_config_cache{$class};
544              
545 10   33     59 $alien_build_config_cache{$class} ||= do {
546 10 50       41 my $dist = ref $class ? ref $class : $class;
547 10         51 $dist =~ s/::/-/g;
548 10         21 my $dist_dir = eval { _dist_dir $dist };
  10         27  
549 10 100       777 return if $@;
550 9         28 my $alien_json = Path::Tiny->new($dist_dir, '_alien', 'alien.json');
551 9 100       253 return unless -r $alien_json;
552 8         202 my $json = $alien_json->slurp;
553 8         3295 require JSON::PP;
554 8         36542 my $config = JSON::PP::decode_json($json);
555 8         36277 $config->{distdir} = $dist_dir;
556 8         149 $config;
557             };
558             }
559             }
560              
561              
562             sub alt
563             {
564 6     6 1 8214 my($old, $name) = @_;
565 6 100       30 my $new = ref $old ? (ref $old)->new : $old->new;
566              
567 6         8 my $orig;
568              
569 6 100 66     24 if(ref($old) && defined $old->{_alt})
570 1         4 { $orig = $old->{_alt}->{orig} }
571             else
572 5         11 { $orig = $old->runtime_prop }
573              
574 6         606 require Storable;
575 6         3416 my $runtime_prop = Storable::dclone($orig);
576              
577 6 100       22 if($runtime_prop->{alt}->{$name})
578             {
579 5         8 foreach my $key (keys %{ $runtime_prop->{alt}->{$name} })
  5         22  
580             {
581 23         36 $runtime_prop->{$key} = $runtime_prop->{alt}->{$name}->{$key};
582             }
583             }
584             else
585             {
586 1         157 Carp::croak("no such alt: $name");
587             }
588              
589             $new->{_alt} = {
590 5         28 runtime_prop => $runtime_prop,
591             orig => $orig,
592             };
593              
594 5         23 $new;
595             }
596              
597              
598             sub alt_names
599             {
600 3     3 1 1759 my($class) = @_;
601 3         17 my $alts = $class->runtime_prop->{alt};
602 3 100       48 defined $alts
603             ? sort keys %$alts
604             : ();
605             }
606              
607              
608             sub alt_exists
609             {
610 4     4 1 2850 my($class, $alt_name) = @_;
611 4         9 my $alts = $class->runtime_prop->{alt};
612             defined $alts
613 4 100 66     39 ? exists $alts->{$alt_name} && defined $alts->{$alt_name}
614             : 0;
615             }
616              
617             1;
618              
619             =pod
620              
621             =encoding UTF-8
622              
623             =head1 NAME
624              
625             Alien::Base - Base classes for Alien:: modules
626              
627             =head1 VERSION
628              
629             version 2.47
630              
631             =head1 SYNOPSIS
632              
633             package Alien::MyLibrary;
634            
635             use strict;
636             use warnings;
637            
638             use parent 'Alien::Base';
639            
640             1;
641              
642             (for details on the C or C and L
643             that should be bundled with your L subclass, please see
644             L).
645              
646             Then a C can use C in its C:
647              
648             use Alien::MyLibrary
649             use ExtUtils::MakeMaker;
650             use Alien::Base::Wrapper qw( Alien::MyLibrary !export );
651             use Config;
652            
653             WriteMakefile(
654             ...
655             Alien::Base::Wrapper->mm_args,
656             ...
657             );
658              
659             Or if you prefer L, in its C:
660              
661             use Alien::MyLibrary;
662             use Module::Build 0.28; # need at least 0.28
663             use Alien::Base::Wrapper qw( Alien::MyLibrary !export );
664            
665             my $builder = Module::Build->new(
666             ...
667             Alien::Base::Wrapper->mb_args,
668             ...
669             );
670            
671             $builder->create_build_script;
672              
673             Or if you are using L:
674              
675             use ExtUtils::MakeMaker;
676             use ExtUtils::Depends;
677             my $eud = ExtUtils::Depends->new(qw( MyLibrary::XS Alien::MyLibrary ));
678             WriteMakefile(
679             ...
680             $eud->get_makefile_vars
681             );
682              
683             If you are using L instead of the recommended L
684             and L, then in your C module, you may need something like
685             this in your main C<.pm> file IF your library uses dynamic libraries:
686              
687             package MyLibrary::XS;
688            
689             use Alien::MyLibrary; # may only be needed if you are using Alien::Base::ModuleBuild
690            
691             ...
692              
693             Or you can use it from an FFI module:
694              
695             package MyLibrary::FFI;
696            
697             use Alien::MyLibrary;
698             use FFI::Platypus;
699             use FFI::CheckLib 0.28 qw( find_lib_or_die );
700            
701             my $ffi = FFI::Platypus->new;
702             $ffi->lib(find_lib_or_die lib => 'mylib', alien => ['Alien::MyLibrary']);
703            
704             $ffi->attach( 'my_library_function' => [] => 'void' );
705              
706             You can even use it with L (C and C++ languages are supported):
707              
708             package MyLibrary::Inline;
709            
710             use Alien::MyLibrary;
711             # Inline 0.56 or better is required
712             use Inline 0.56 with => 'Alien::MyLibrary';
713             ...
714              
715             =head1 DESCRIPTION
716              
717             B: L is no longer bundled with L and has been spun off into a separate distribution.
718             L will be a prerequisite for L until October 1, 2017. If you are using L
719             you need to make sure it is declared as a C in your C. You may want to also consider using L and
720             L as a more modern alternative.
721              
722             L comprises base classes to help in the construction of C modules. Modules in the L namespace are used to locate and install (if necessary) external libraries needed by other Perl modules.
723              
724             This is the documentation for the L module itself. If you
725             are starting out you probably want to do so from one of these documents:
726              
727             =over 4
728              
729             =item L
730              
731             For users of an C that is implemented using L.
732             (The developer of C I provide the documentation
733             necessary, but if not, this is the place to start).
734              
735             =item L
736              
737             If you are writing your own L based on L and L.
738              
739             =item L
740              
741             If you have a common question that has already been answered, like
742             "How do I use L with some build system".
743              
744             =item L
745              
746             This is for the brave souls who want to write plugins that will work with
747             L + L.
748              
749             =back
750              
751             Before using an L based L directly, please consider the following advice:
752              
753             If you are wanting to use an L based L with an XS module using L or L, it is highly
754             recommended that you use L, rather than using the L directly, because it handles a number of sharp edges and avoids
755             pitfalls common when trying to use an L directly with L.
756              
757             In the same vein, if you are wanting to use an L based L with an XS module using L it is highly recommended
758             that you use L for the same reasons.
759              
760             As of version 0.28, L has a good interface for working with L based Ls in fallback mode, which is
761             recommended.
762              
763             You should typically only be using an L based L directly, if you need to integrate it with some other system, or if it
764             is a tool based L that you don't need to link.
765              
766             The above synopsis and linked manual documents will lead you down the right path, but it is worth knowing before you read further in this
767             document.
768              
769             =head1 METHODS
770              
771             In the example snippets here, C represents any
772             subclass of L.
773              
774             =head2 dist_dir
775              
776             my $dir = Alien::MyLibrary->dist_dir;
777              
778             Returns the directory that contains the install root for
779             the packaged software, if it was built from install (i.e., if
780             C is C).
781              
782             =head2 new
783              
784             my $alien = Alien::MyLibrary->new;
785              
786             Creates an instance of an L object. This is typically
787             unnecessary.
788              
789             =head2 cflags
790              
791             my $cflags = Alien::MyLibrary->cflags;
792            
793             use Text::ParseWords qw( shellwords );
794             my @cflags = shellwords( Alien::MyLibrary->cflags );
795              
796             Returns the C compiler flags necessary to compile an XS
797             module using the alien software. If you need this in list
798             form (for example if you are calling system with a list
799             argument) you can pass this value into C from
800             the Perl core L module.
801              
802             =head2 cflags_static
803              
804             my $cflags = Alien::MyLibrary->cflags_static;
805              
806             Same as C above, but gets the static compiler flags,
807             if they are different.
808              
809             =head2 libs
810              
811             my $libs = Alien::MyLibrary->libs;
812            
813             use Text::ParseWords qw( shellwords );
814             my @cflags = shellwords( Alien::MyLibrary->libs );
815              
816             Returns the library linker flags necessary to link an XS
817             module against the alien software. If you need this in list
818             form (for example if you are calling system with a list
819             argument) you can pass this value into C from
820             the Perl core L module.
821              
822             =head2 libs_static
823              
824             my $libs = Alien::MyLibrary->libs_static;
825              
826             Same as C above, but gets the static linker flags,
827             if they are different.
828              
829             =head2 version
830              
831             my $version = Alien::MyLibrary->version;
832              
833             Returns the version of the alienized library or tool that was
834             determined at install time.
835              
836             =head2 atleast_version
837              
838             =head2 exact_version
839              
840             =head2 max_version
841              
842             my $ok = Alien::MyLibrary->atleast_version($wanted_version);
843             my $ok = Alien::MyLibrary->exact_version($wanted_version);
844             my $ok = Alien::MyLibrary->max_version($wanted_version);
845              
846             Returns true if the version of the alienized library or tool is at least,
847             exactly, or at most the version specified, respectively.
848              
849             =head2 version_cmp
850              
851             $cmp = Alien::MyLibrary->version_cmp($x, $y)
852              
853             Comparison method used by L, L and
854             L. May be useful to implement custom comparisons, or for
855             subclasses to overload to get different version comparison semantics than the
856             default rules, for packages that have some other rules than the F
857             behaviour.
858              
859             Should return a number less than, equal to, or greater than zero; similar in
860             behaviour to the C<< <=> >> and C operators.
861              
862             =head2 install_type
863              
864             my $install_type = Alien::MyLibrary->install_type;
865             my $bool = Alien::MyLibrary->install_type($install_type);
866              
867             Returns the install type that was used when C was
868             installed. If a type is provided (the second form in the synopsis)
869             returns true if the actual install type matches. Types include:
870              
871             =over 4
872              
873             =item system
874              
875             The library was provided by the operating system
876              
877             =item share
878              
879             The library was not available when C was installed, so
880             it was built from source code, either downloaded from the Internet
881             or bundled with C.
882              
883             =back
884              
885             =head2 config
886              
887             my $value = Alien::MyLibrary->config($key);
888              
889             Returns the configuration data as determined during the install
890             of L. For the appropriate config keys, see
891             L.
892              
893             This is not typically used by L and L,
894             but a compatible interface will be provided.
895              
896             =head2 dynamic_libs
897              
898             my @dlls = Alien::MyLibrary->dynamic_libs;
899             my($dll) = Alien::MyLibrary->dynamic_libs;
900              
901             Returns a list of the dynamic library or shared object files for the
902             alien software.
903              
904             =head2 bin_dir
905              
906             my(@dir) = Alien::MyLibrary->bin_dir
907              
908             Returns a list of directories with executables in them. For a C
909             install this will be an empty list. For a C install this will be
910             a directory under C named C if it exists. You may wish
911             to override the default behavior if you have executables or scripts that
912             get installed into non-standard locations.
913              
914             Example usage:
915              
916             use Env qw( @PATH );
917            
918             unshift @PATH, Alien::MyLibrary->bin_dir;
919              
920             =head2 dynamic_dir
921              
922             my(@dir) = Alien::MyLibrary->dynamic_dir
923              
924             Returns the dynamic dir for a dynamic build (if the main
925             build is static). For a C install this will be a
926             directory under C named C if it exists.
927             System builds return an empty list.
928              
929             Example usage:
930              
931             use Env qw( @PATH );
932            
933             unshift @PATH, Alien::MyLibrary->dynamic_dir;
934              
935             =head2 alien_helper
936              
937             my $helpers = Alien::MyLibrary->alien_helper;
938              
939             Returns a hash reference of helpers provided by the Alien module.
940             The keys are helper names and the values are code references. The
941             code references will be executed at command time and the return value
942             will be interpolated into the command before execution. The default
943             implementation returns an empty hash reference, and you are expected
944             to override the method to create your own helpers.
945              
946             For use with commands specified in and L or in your C
947             when used with L.
948              
949             Helpers allow users of your Alien module to use platform or environment
950             determined logic to compute command names or arguments in your installer
951             logic. Helpers allow you to do this without making your Alien module a
952             requirement when a build from source code is not necessary.
953              
954             As a concrete example, consider L, which provides the
955             helper C:
956              
957             package Alien::gmake;
958            
959             ...
960            
961             sub alien_helper {
962             my($class) = @_;
963             return {
964             gmake => sub {
965             # return the executable name for GNU make,
966             # usually either make or gmake depending on
967             # the platform and environment
968             $class->exe;
969             }
970             },
971             }
972              
973             Now consider L. C requires GNU Make to build from
974             source code, but if the system C package is installed we don't
975             need it. From the L of C:
976              
977             use alienfile;
978            
979             plugin 'Probe::CommandLine' => (
980             command => 'nasm',
981             args => ['-v'],
982             match => qr/NASM version/,
983             );
984            
985             share {
986             ...
987             plugin 'Extract' => 'tar.gz';
988             plugin 'Build::MSYS';
989            
990             build [
991             'sh configure --prefix=%{alien.install.prefix}',
992             '%{gmake}',
993             '%{gmake} install',
994             ];
995             };
996            
997             ...
998              
999             =head2 inline_auto_include
1000              
1001             my(@headers) = Alien::MyLibrary->inline_auto_include;
1002              
1003             List of header files to automatically include in inline C and C++
1004             code when using L or L. This is provided
1005             as a public interface primarily so that it can be overridden at run
1006             time. This can also be specified in your C with
1007             L using the C
1008             property.
1009              
1010             =head2 runtime_prop
1011              
1012             my $hashref = Alien::MyLibrary->runtime_prop;
1013              
1014             Returns a hash reference of the runtime properties computed by L during its
1015             install process. If the L based L was not built using L,
1016             then this will return undef.
1017              
1018             =head2 alt
1019              
1020             my $new_alien = Alien::MyLibrary->alt($alt_name);
1021             my $new_alien = $old_alien->alt($alt_name);
1022              
1023             Returns an L instance with the alternate configuration.
1024              
1025             Some packages come with multiple libraries, and multiple C<.pc> files to
1026             use with them. This method can be used with C plugins to
1027             access different configurations. (It could also be used with non-pkg-config
1028             based packages too, though there are not as of this writing any build
1029             time plugins that take advantage of this feature).
1030              
1031             From your L
1032              
1033             use alienfile;
1034            
1035             plugin 'PkgConfig' => (
1036             pkg_name => [ 'libfoo', 'libbar', ],
1037             );
1038              
1039             Then in your base class works like normal:
1040              
1041             package Alien::MyLibrary;
1042            
1043             use parent qw( Alien::Base );
1044            
1045             1;
1046              
1047             Then you can use it:
1048              
1049             use Alien::MyLibrary;
1050            
1051             my $cflags = Alien::MyLibrary->alt('foo1')->cflags;
1052             my $libs = Alien::MyLibrary->alt('foo1')->libs;
1053              
1054             =head2 alt_names
1055              
1056             my @alt_names = Alien::MyLibrary->alt_names
1057              
1058             Returns the list of all available alternative configuration names.
1059              
1060             =head2 alt_exists
1061              
1062             my $bool = Alien::MyLibrary->alt_exists($alt_name)
1063              
1064             Returns true if the given alternative configuration exists.
1065              
1066             =head1 SUPPORT AND CONTRIBUTING
1067              
1068             First check the L for questions that have already been answered.
1069              
1070             IRC: #native on irc.perl.org
1071              
1072             L<(click for instant chatroom login)|http://chat.mibbit.com/#native@irc.perl.org>
1073              
1074             If you find a bug, please report it on the projects issue tracker on GitHub:
1075              
1076             =over 4
1077              
1078             =item L
1079              
1080             =back
1081              
1082             Development is discussed on the projects google groups. This is also
1083             a reasonable place to post a question if you don't want to open an issue
1084             in GitHub.
1085              
1086             =over 4
1087              
1088             =item L
1089              
1090             =back
1091              
1092             If you have implemented a new feature or fixed a bug, please open a pull
1093             request.
1094              
1095             =over 4
1096              
1097             =item L
1098              
1099             =back
1100              
1101             =head1 SEE ALSO
1102              
1103             =over
1104              
1105             =item *
1106              
1107             L
1108              
1109             =item *
1110              
1111             L
1112              
1113             =item *
1114              
1115             L
1116              
1117             =item *
1118              
1119             L
1120              
1121             =back
1122              
1123             =head1 THANKS
1124              
1125             C was originally written by Joel Berger, and that
1126             code is still Copyright (C) 2012-2017 Joel Berger. It has the
1127             same license as the rest of the L.
1128              
1129             Special thanks for the early development of C go to:
1130              
1131             =over
1132              
1133             =item Christian Walde (Mithaldu)
1134              
1135             For productive conversations about component interoperability.
1136              
1137             =item kmx
1138              
1139             For writing Alien::Tidyp from which I drew many of my initial ideas.
1140              
1141             =item David Mertens (run4flat)
1142              
1143             For productive conversations about implementation.
1144              
1145             =item Mark Nunberg (mordy, mnunberg)
1146              
1147             For graciously teaching me about rpath and dynamic loading,
1148              
1149             =back
1150              
1151             =head1 AUTHOR
1152              
1153             Author: Graham Ollis Eplicease@cpan.orgE
1154              
1155             Contributors:
1156              
1157             Diab Jerius (DJERIUS)
1158              
1159             Roy Storey (KIWIROY)
1160              
1161             Ilya Pavlov
1162              
1163             David Mertens (run4flat)
1164              
1165             Mark Nunberg (mordy, mnunberg)
1166              
1167             Christian Walde (Mithaldu)
1168              
1169             Brian Wightman (MidLifeXis)
1170              
1171             Zaki Mughal (zmughal)
1172              
1173             mohawk (mohawk2, ETJ)
1174              
1175             Vikas N Kumar (vikasnkumar)
1176              
1177             Flavio Poletti (polettix)
1178              
1179             Salvador Fandiño (salva)
1180              
1181             Gianni Ceccarelli (dakkar)
1182              
1183             Pavel Shaydo (zwon, trinitum)
1184              
1185             Kang-min Liu (劉康民, gugod)
1186              
1187             Nicholas Shipp (nshp)
1188              
1189             Juan Julián Merelo Guervós (JJ)
1190              
1191             Joel Berger (JBERGER)
1192              
1193             Petr Písař (ppisar)
1194              
1195             Lance Wicks (LANCEW)
1196              
1197             Ahmad Fatoum (a3f, ATHREEF)
1198              
1199             José Joaquín Atria (JJATRIA)
1200              
1201             Duke Leto (LETO)
1202              
1203             Shoichi Kaji (SKAJI)
1204              
1205             Shawn Laffan (SLAFFAN)
1206              
1207             Paul Evans (leonerd, PEVANS)
1208              
1209             Håkon Hægland (hakonhagland, HAKONH)
1210              
1211             nick nauwelaerts (INPHOBIA)
1212              
1213             =head1 COPYRIGHT AND LICENSE
1214              
1215             This software is copyright (c) 2011-2020 by Graham Ollis.
1216              
1217             This is free software; you can redistribute it and/or modify it under
1218             the same terms as the Perl 5 programming language system itself.
1219              
1220             =cut
1221              
1222             __END__