File Coverage

blib/lib/XS/Loader.pm
Criterion Covered Total %
statement 24 71 33.8
branch 0 30 0.0
condition 0 25 0.0
subroutine 8 12 66.6
pod 2 3 66.6
total 34 141 24.1


line stmt bran cond sub pod time code
1             package XS::Loader;
2 11     11   81 use strict;
  11         25  
  11         348  
3 11     11   63 use warnings;
  11         21  
  11         388  
4 11     11   60 use Config();
  11         23  
  11         168  
5 11     11   53 use DynaLoader;
  11         23  
  11         329  
6 11     11   4744 use XS::Install::Payload;
  11         31  
  11         341  
7 11     11   4929 use XS::Install::Util;
  11         31  
  11         1115  
8              
9             our $UNIQUE_LIBNAME = ($^O eq 'MSWin32');
10              
11             sub load {
12 0 0 0 0 1   shift if $_[0] && $_[0] eq __PACKAGE__;
13 0           my ($module, $version, $flags, $noboot) = @_;
14              
15 0   0       $module ||= caller(0);
16 0   0       $version ||= XS::Install::Payload::loaded_module_version($module);
17 0   0       $flags //= 0x01;
18 0 0         $noboot = 1 if $module eq 'MyTest';
19              
20 0 0         if ($flags) {
21 11     11   82 no strict 'refs';
  11         153  
  11         3585  
22 0     0     *{"${module}::dl_load_flags"} = sub { $flags };
  0            
  0            
23             }
24              
25 0 0         if (my $info = XS::Install::Payload::binary_module_info($module)) {{
26 0 0         my $bin_deps = $info->{BIN_DEPS} or last;
  0            
27 0           foreach my $dep_module (keys %$bin_deps) {
28 0 0         next if $dep_module eq 'XS::Install';
29 0           my $path = $dep_module;
30 0           $path =~ s!::!/!g;
31 0 0         require $path.".pm" or next; # in what cases it returns false without croaking?
32 0           my $dep_version = XS::Install::Payload::loaded_module_version($dep_module);
33 0 0         next if $dep_version eq $bin_deps->{$dep_module};
34 0   0       my $dep_info = XS::Install::Payload::binary_module_info($dep_module) || {};
35 0           my $bin_dependent = $dep_info->{BIN_DEPENDENT};
36 0 0 0       $bin_dependent = [$module] if !$bin_dependent or !@$bin_dependent;
37 0           $bin_dependent = XS::Install::Util::linearize_dependent($bin_dependent);
38 0           die << "EOF";
39             ******************************************************************************
40             XS::Loader: XS module $module binary depends on XS module $dep_module.
41             $module was compiled with $dep_module version $bin_deps->{$dep_module}, but current version is $dep_version.
42             Please reinstall all modules that binary depend on $dep_module:
43             cpanm --reinstall @$bin_dependent
44             ******************************************************************************
45             EOF
46             }
47             }}
48              
49 0 0         local *DynaLoader::mod2fname = \&mod2fname_unique if $UNIQUE_LIBNAME;
50              
51 0           my $ok = eval {
52 0           DynaLoader::bootstrap_inherit($module, $version);
53 0           1;
54             };
55 0 0 0       die($@) if !$ok and !($noboot and $@ and $@ =~ /Can't find 'boot_/i);
      0        
      0        
56              
57 0 0         if ($flags) {
58 11     11   80 no strict 'refs';
  11         31  
  11         3596  
59 0           my $stash = \%{"${module}::"};
  0            
60 0           delete $stash->{dl_load_flags};
61             }
62             }
63              
64             sub load_noboot {
65 0     0 1   @_ = ($_[0], $_[1], $_[2], 1);
66 0           goto &load;
67             }
68              
69             *bootstrap = *load;
70              
71             ############## taken from DynaLoader_pm.PL, needed on Windows #####################
72             sub mod2fname_unique {
73 0     0 0   my $parts = shift;
74 0           my $so_len = length($Config::Config{dlext}) + 1;
75 0           my $name_max = 255; # No easy way to get this here
76              
77 0           my $libname = "PL_".join("__", @$parts);
78              
79 0 0         return $libname if (length($libname)+$so_len) <= $name_max;
80              
81             # It's too darned big, so we need to go strip. We use the same
82             # algorithm as xsubpp does. First, strip out doubled __
83 0           $libname =~ s/__/_/g;
84 0 0         return $libname if (length($libname)+$so_len) <= $name_max;
85              
86             # Strip duplicate letters
87 0           1 while $libname =~ s/(.)\1/\U$1/i;
88 0 0         return $libname if (length($libname)+$so_len) <= $name_max;
89              
90             # Still too long. Truncate.
91 0           $libname = substr($libname, 0, $name_max - $so_len);
92 0           return $libname;
93             }
94              
95             1;