| 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__ |