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   8786 use strict;
  12         33  
  12         407  
4 12     12   60 use warnings;
  12         89  
  12         308  
5 12     12   248 use 5.008004;
  12         43  
6 12     12   73 use Carp;
  12         24  
  12         942  
7 12     12   918 use Path::Tiny ();
  12         11944  
  12         295  
8 12     12   60 use Scalar::Util qw/blessed/;
  12         36  
  12         826  
9 12     12   1198 use Capture::Tiny 0.17 qw/capture_stdout/;
  12         49808  
  12         741  
10 12     12   1967 use Text::ParseWords qw/shellwords/;
  12         5577  
  12         1492  
11              
12             # ABSTRACT: Base classes for Alien:: modules
13             our $VERSION = '2.45'; # VERSION
14              
15              
16             sub import {
17 3     3   44 my $class = shift;
18              
19 3 50       14 return if $class eq __PACKAGE__;
20              
21 3 50       19 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   157 no strict 'refs';
  12         31  
  12         468  
36 12     12   69 no warnings 'once';
  12         31  
  12         49512  
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   73 my($dist_name) = @_;
72              
73 32         118 my @pm = split /-/, $dist_name;
74 32         74 $pm[-1] .= ".pm";
75              
76 32         81 foreach my $inc (@INC)
77             {
78 32         205 my $pm = Path::Tiny->new($inc, @pm);
79 32 50       1552 if(-f $pm)
80             {
81 32         788 my $share = Path::Tiny->new($inc, qw( auto share dist ), $dist_name );
82 32 100       1358 if(-d $share)
83             {
84 31         641 return $share->absolute->stringify;
85             }
86 1         45 last;
87             }
88             }
89 1         212 Carp::croak("unable to find dist share directory for $dist_name");
90             }
91              
92             sub dist_dir {
93 22     22 1 68 my $class = shift;
94              
95 22   33     108 my $dist = blessed $class || $class;
96 22         97 $dist =~ s/::/-/g;
97              
98 22 50       64 my $dist_dir =
99             $class->config('finished_installing')
100             ? _dist_dir $dist
101             : $class->config('working_directory');
102              
103 22 50 33     2276 croak "Failed to find share dir for dist '$dist'"
104             unless defined $dist_dir && -d $dist_dir;
105              
106 22         372 return $dist_dir;
107             }
108              
109              
110 6     6 1 15 sub new { return bless {}, $_[0] }
111              
112             sub _flags
113             {
114 38     38   93 my($class, $key) = @_;
115              
116 38         82 my $config = $class->runtime_prop;
117 38         86 my $flags = $config->{$key};
118              
119 38         61 my $prefix = $config->{prefix};
120 38 50       210 $prefix =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
121 38         74 my $distdir = $config->{distdir};
122 38 50       109 $distdir =~ s{\\}{/}g if $^O =~ /^(MSWin32|msys)$/;
123              
124 38 100       89 if($prefix ne $distdir)
125             {
126             $flags = join ' ', map {
127 34         91 my $flag = $_;
  86         3806  
128 86         437 $flag =~ s/^(-I|-L|-LIBPATH:)?\Q$prefix\E/$1$distdir/;
129 86         172 $flag =~ s/(\s)/\\$1/g;
130 86         248 $flag;
131             } $class->split_flags($flags);
132             }
133              
134 38         277 $flags;
135             }
136              
137              
138             sub cflags {
139 12     12 1 7959 my $class = shift;
140 12 100       51 return $class->runtime_prop ? $class->_flags('cflags') : $class->_pkgconfig_keyword('Cflags');
141             }
142              
143              
144             sub cflags_static {
145 8     8 1 1984 my $class = shift;
146 8 50       22 return $class->runtime_prop ? $class->_flags('cflags_static') : $class->_pkgconfig_keyword('Cflags', 'static');
147             }
148              
149              
150             sub libs {
151 14     14 1 3319 my $class = shift;
152 14 100       61 return $class->runtime_prop ? $class->_flags('libs') : $class->_pkgconfig_keyword('Libs');
153             }
154              
155              
156             sub libs_static {
157 8     8 1 2229 my $class = shift;
158 8 50       21 return $class->runtime_prop ? $class->_flags('libs_static') : $class->_pkgconfig_keyword('Libs', 'static');
159             }
160              
161              
162             sub version {
163 13     13 1 1853 my $self = shift;
164             return $self->runtime_prop
165             ? $self->runtime_prop->{version}
166 13 100       86 : do {
167 2         16 my $version = $self->config('version');
168 2         12 chomp $version;
169 2         15 $version;
170             };
171             }
172              
173              
174             sub atleast_version {
175 3     3 1 673 my $self = shift;
176 3         8 my ($wantver) = @_;
177              
178 3 100       9 defined(my $version = $self->version) or
179             croak "$self has no defined ->version";
180              
181 2         8 return $self->version_cmp($version, $wantver) >= 0;
182             }
183              
184             sub exact_version {
185 2     2 1 554 my $self = shift;
186 2         4 my ($wantver) = @_;
187              
188 2 100       6 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 419 my $self = shift;
196 2         5 my ($wantver) = @_;
197              
198 2 100       6 defined(my $version = $self->version) or
199             croak "$self has no defined ->version";
200              
201 1         4 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 6 shift;
210 4         44 my @x = (shift =~ m/([0-9]+|[a-z]+)/ig);
211 4         19 my @y = (shift =~ m/([0-9]+|[a-z]+)/ig);
212              
213 4   100     20 while(@x and @y) {
214 9         17 my $x = shift @x; my $x_isnum = $x =~ m/[0-9]/;
  9         21  
215 9         14 my $y = shift @y; my $y_isnum = $y =~ m/[0-9]/;
  9         17  
216              
217 9 50 33     28 if($x_isnum and $y_isnum) {
    0 0        
218             # Numerical comparison
219 9 100       48 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         16 return @x <=> @y;
233             }
234              
235              
236             sub install_type {
237 24     24 1 1541 my $self = shift;
238 24         95 my $type = $self->config('install_type');
239 24 100       168 return @_ ? $type eq $_[0] : $type;
240             }
241              
242             sub _pkgconfig_keyword {
243 4     4   61 my $self = shift;
244 4         15 my $keyword = shift;
245 4         9 my $static = shift;
246              
247             # use pkg-config if installed system-wide
248 4 100       25 if ($self->install_type('system')) {
249 2         7 my $name = $self->config('name');
250 2         484 require Alien::Base::PkgConfig;
251 2 50       17 my $command = Alien::Base::PkgConfig->pkg_config_command . " @{[ $static ? '--static' : '' ]} --\L$keyword\E $name";
  2         41  
252              
253 2         7 $! = 0;
254 2     2   153 chomp ( my $pcdata = capture_stdout { system( $command ) } );
  2         325985  
255              
256             # if pkg-config fails for whatever reason, then we try to
257             # fallback on alien_provides_*
258 2 50 33     2734 $pcdata = '' if $! || $?;
259              
260 2         55 $pcdata =~ s/\s*$//;
261              
262 2 50       80 if($self->config('system_provides')) {
263 2 50       22 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         45 return $pcdata;
269             }
270              
271             # use parsed info from build .pc file
272 2         23 my $dist_dir = $self->dist_dir;
273 2         15 my @pc = $self->_pkgconfig(@_);
274             my @strings =
275             grep defined,
276 2         5 map { $_->keyword($keyword,
  2         11  
277             #{ pcfiledir => $dist_dir }
278             ) }
279             @pc;
280              
281 2 50 33     11 if(defined $self->config('original_prefix') && $self->config('original_prefix') ne $self->dist_dir)
282             {
283 2         7 my $dist_dir = $self->dist_dir;
284 2 50       11 $dist_dir =~ s{\\}{/}g if $^O eq 'MSWin32';
285 2         7 my $old = quotemeta $self->config('original_prefix');
286             @strings = map {
287 3         429 my $flag = $_;
288 3         63 $flag =~ s{^(-I|-L|-LIBPATH:)?($old)}{$1.$dist_dir}e;
  2         11  
289 3         8 $flag =~ s/(\s)/\\$1/g;
290 3         11 $flag;
291 2         6 } map { $self->split_flags($_) } @strings;
  2         19  
292             }
293              
294 2         13 return join( ' ', @strings );
295             }
296              
297             sub _pkgconfig {
298 2     2   4 my $self = shift;
299 2         8 my %all = %{ $self->config('pkgconfig') };
  2         7  
300              
301             # merge in found pc files
302 2         8 require File::Find;
303             my $wanted = sub {
304 14 50 66 14   964 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         20 };
309 2         7 File::Find::find( $wanted, $self->dist_dir );
310              
311 2 50       12 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         7 for my $pkg_obj (values %all) {
316 4         18 my $perl_module_name = blessed $pkg_obj;
317 4         11 my $pm = "$perl_module_name.pm";
318 4         15 $pm =~ s/::/\//g;
319 4         8 eval { require $pm };
  4         20  
320             }
321              
322 2 50       7 return @all{@_} if @_;
323              
324 2         4 my $manual = delete $all{_manual};
325              
326 2 50       6 if (keys %all) {
327 2         17 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 135 my $class = shift;
337 72   33     317 $class = blessed $class || $class;
338              
339 72 100       194 if(my $ab_config = $class->runtime_prop)
340             {
341 44         98 my $key = shift;
342 44         171 return $ab_config->{legacy}->{$key};
343             }
344              
345 28         66 my $config = $class . '::ConfigData';
346 28         60 my $pm = "$class/ConfigData.pm";
347 28         116 $pm =~ s{::}{/}g;
348 28         50 eval { require $pm };
  28         1105  
349              
350 28 50       71 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         104 return $config->config(@_);
361             }
362              
363             # helper method to split flags based on the OS
364             sub split_flags {
365 39     39 0 76 my ($class, $line) = @_;
366 39 50       92 if( $^O eq 'MSWin32' ) {
367 0         0 $class->split_flags_windows($line);
368             } else {
369             # $os eq 'Unix'
370 39         89 $class->split_flags_unix($line);
371             }
372             }
373              
374             sub split_flags_unix {
375 40     40 0 5481 my ($class, $line) = @_;
376 40         124 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 3979 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         21 $line =~ s,\\,\\\\,g;
387 3         11 shellwords($line);
388             }
389              
390              
391             sub dynamic_libs {
392 5     5 1 13639 my ($class) = @_;
393              
394 5         38 require FFI::CheckLib;
395              
396 5         10 my @find_lib_flags;
397              
398 5 100       19 if($class->install_type('system')) {
399              
400 4 50       11 if(my $prop = $class->runtime_prop)
401             {
402 4 50       24 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       15 if defined $prop->{ffi_name};
408             }
409              
410 3         9 my $name = $class->config('ffi_name');
411 3 50       18 unless(defined $name)
412             {
413 3         10 $name = $class->config('name');
414 3 50       10 $name = '' unless defined $name;
415             # strip leading lib from things like libarchive or libffi
416 3         12 $name =~ s/^lib//;
417             # strip trailing version numbers
418 3         8 $name =~ s/-[0-9\.]+$//;
419             }
420              
421 3         4 my @libpath;
422 3         14 foreach my $flag ($class->split_flags($class->libs))
423             {
424 4 100       247 if($flag =~ /^-L(.*)$/)
425             {
426 1         5 push @libpath, $1;
427             }
428             }
429              
430 3         23 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         5 my $dynamic = Path::Tiny->new($class->dist_dir, 'dynamic');
436              
437 1 50       38 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       5 if(-d $dynamic)
446             {
447 1         28 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 2418 my ($class) = @_;
466 7 100       47 if($class->install_type('system'))
467             {
468 4         16 my $prop = $class->runtime_prop;
469 4 50       12 return () unless defined $prop;
470 4 50       35 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         26 my $dir = Path::Tiny->new($class->dist_dir, 'bin');
476 3 50       110 return -d $dir ? ("$dir") : ();
477             }
478             }
479              
480              
481              
482             sub dynamic_dir {
483 2     2 1 1818 my ($class) = @_;
484 2 100       16 if($class->install_type('system'))
485             {
486 1         7 return ();
487             }
488             else
489             {
490 1         7 my $dir = Path::Tiny->new($class->dist_dir, 'dynamic');
491 1 50       37 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 874 my($class) = @_;
533              
534 201 100       432 if(ref($class))
535             {
536             # called as an instance method.
537 44         108 my $self = $class;
538 44         71 $class = ref $self;
539 44 50       175 return $self->{_alt}->{runtime_prop} if defined $self->{_alt};
540             }
541              
542             return $alien_build_config_cache{$class} if
543 157 100       607 exists $alien_build_config_cache{$class};
544              
545 10   33     102 $alien_build_config_cache{$class} ||= do {
546 10 50       56 my $dist = ref $class ? ref $class : $class;
547 10         65 $dist =~ s/::/-/g;
548 10         25 my $dist_dir = eval { _dist_dir $dist };
  10         41  
549 10 100       995 return if $@;
550 9         37 my $alien_json = Path::Tiny->new($dist_dir, '_alien', 'alien.json');
551 9 100       308 return unless -r $alien_json;
552 8         248 my $json = $alien_json->slurp;
553 8         4213 require JSON::PP;
554 8         42769 my $config = JSON::PP::decode_json($json);
555 8         44416 $config->{distdir} = $dist_dir;
556 8         233 $config;
557             };
558             }
559             }
560              
561              
562             sub alt
563             {
564 6     6 1 10265 my($old, $name) = @_;
565 6 100       35 my $new = ref $old ? (ref $old)->new : $old->new;
566              
567 6         12 my $orig;
568              
569 6 100 66     27 if(ref($old) && defined $old->{_alt})
570 1         4 { $orig = $old->{_alt}->{orig} }
571             else
572 5         12 { $orig = $old->runtime_prop }
573              
574 6         1998 require Storable;
575 6         4493 my $runtime_prop = Storable::dclone($orig);
576              
577 6 100       31 if($runtime_prop->{alt}->{$name})
578             {
579 5         10 foreach my $key (keys %{ $runtime_prop->{alt}->{$name} })
  5         32  
580             {
581 23         47 $runtime_prop->{$key} = $runtime_prop->{alt}->{$name}->{$key};
582             }
583             }
584             else
585             {
586 1         176 Carp::croak("no such alt: $name");
587             }
588              
589             $new->{_alt} = {
590 5         34 runtime_prop => $runtime_prop,
591             orig => $orig,
592             };
593              
594 5         20 $new;
595             }
596              
597              
598             sub alt_names
599             {
600 3     3 1 2173 my($class) = @_;
601 3         28 my $alts = $class->runtime_prop->{alt};
602 3 100       59 defined $alts
603             ? sort keys %$alts
604             : ();
605             }
606              
607              
608             sub alt_exists
609             {
610 4     4 1 3512 my($class, $alt_name) = @_;
611 4         13 my $alts = $class->runtime_prop->{alt};
612             defined $alts
613 4 100 66     42 ? 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.45
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__