MakeMaker sync 5.48_03 -> 5.53_01
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / Liblist / Kid.pm
1 package ExtUtils::Liblist::Kid;
2
3 # XXX Splitting this out into its own .pm is a temporary solution.
4
5 # This kid package is to be used by MakeMaker.  It will not work if
6 # $self is not a Makemaker.
7
8 use 5.006;
9 # Broken out of MakeMaker from version 4.11
10
11 our $VERSION = 1.28_01;
12
13 use Config;
14 use Cwd 'cwd';
15 use File::Basename;
16 use File::Spec;
17
18 sub ext {
19   if   ($^O eq 'VMS')     { return &_vms_ext;      }
20   elsif($^O eq 'MSWin32') { return &_win32_ext;    }
21   else                    { return &_unix_os2_ext; }
22 }
23
24 sub _unix_os2_ext {
25     my($self,$potential_libs, $verbose, $give_libs) = @_;
26     if ($^O =~ 'os2' and $Config{perllibs}) { 
27         # Dynamic libraries are not transitive, so we may need including
28         # the libraries linked against perl.dll again.
29
30         $potential_libs .= " " if $potential_libs;
31         $potential_libs .= $Config{perllibs};
32     }
33     return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;
34     warn "Potential libraries are '$potential_libs':\n" if $verbose;
35
36     my($so)   = $Config{'so'};
37     my($libs) = $Config{'perllibs'};
38     my $Config_libext = $Config{lib_ext} || ".a";
39
40
41     # compute $extralibs, $bsloadlibs and $ldloadlibs from
42     # $potential_libs
43     # this is a rewrite of Andy Dougherty's extliblist in perl
44
45     my(@searchpath); # from "-L/path" entries in $potential_libs
46     my(@libpath) = split " ", $Config{'libpth'};
47     my(@ldloadlibs, @bsloadlibs, @extralibs, @ld_run_path, %ld_run_path_seen);
48     my(@libs, %libs_seen);
49     my($fullname, $thislib, $thispth, @fullname);
50     my($pwd) = cwd(); # from Cwd.pm
51     my($found) = 0;
52
53     foreach $thislib (split ' ', $potential_libs){
54
55         # Handle possible linker path arguments.
56         if ($thislib =~ s/^(-[LR]|-Wl,-R)//){   # save path flag type
57             my($ptype) = $1;
58             unless (-d $thislib){
59                 warn "$ptype$thislib ignored, directory does not exist\n"
60                         if $verbose;
61                 next;
62             }
63             my($rtype) = $ptype;
64             if (($ptype eq '-R') or ($ptype eq '-Wl,-R')) {
65                 if ($Config{'lddlflags'} =~ /-Wl,-R/) {
66                     $rtype = '-Wl,-R';
67                 } elsif ($Config{'lddlflags'} =~ /-R/) {
68                     $rtype = '-R';
69                 }
70             }
71             unless (File::Spec->file_name_is_absolute($thislib)) {
72               warn "Warning: $ptype$thislib changed to $ptype$pwd/$thislib\n";
73               $thislib = $self->catdir($pwd,$thislib);
74             }
75             push(@searchpath, $thislib);
76             push(@extralibs,  "$ptype$thislib");
77             push(@ldloadlibs, "$rtype$thislib");
78             next;
79         }
80
81         # Handle possible library arguments.
82         unless ($thislib =~ s/^-l//){
83           warn "Unrecognized argument in LIBS ignored: '$thislib'\n";
84           next;
85         }
86
87         my($found_lib)=0;
88         foreach $thispth (@searchpath, @libpath){
89
90                 # Try to find the full name of the library.  We need this to
91                 # determine whether it's a dynamically-loadable library or not.
92                 # This tends to be subject to various os-specific quirks.
93                 # For gcc-2.6.2 on linux (March 1995), DLD can not load
94                 # .sa libraries, with the exception of libm.sa, so we
95                 # deliberately skip them.
96             if (@fullname =
97                     $self->lsdir($thispth,"^\Qlib$thislib.$so.\E[0-9]+")){
98                 # Take care that libfoo.so.10 wins against libfoo.so.9.
99                 # Compare two libraries to find the most recent version
100                 # number.  E.g.  if you have libfoo.so.9.0.7 and
101                 # libfoo.so.10.1, first convert all digits into two
102                 # decimal places.  Then we'll add ".00" to the shorter
103                 # strings so that we're comparing strings of equal length
104                 # Thus we'll compare libfoo.so.09.07.00 with
105                 # libfoo.so.10.01.00.  Some libraries might have letters
106                 # in the version.  We don't know what they mean, but will
107                 # try to skip them gracefully -- we'll set any letter to
108                 # '0'.  Finally, sort in reverse so we can take the
109                 # first element.
110
111                 #TODO: iterate through the directory instead of sorting
112
113                 $fullname = "$thispth/" .
114                 (sort { my($ma) = $a;
115                         my($mb) = $b;
116                         $ma =~ tr/A-Za-z/0/s;
117                         $ma =~ s/\b(\d)\b/0$1/g;
118                         $mb =~ tr/A-Za-z/0/s;
119                         $mb =~ s/\b(\d)\b/0$1/g;
120                         while (length($ma) < length($mb)) { $ma .= ".00"; }
121                         while (length($mb) < length($ma)) { $mb .= ".00"; }
122                         # Comparison deliberately backwards
123                         $mb cmp $ma;} @fullname)[0];
124             } elsif (-f ($fullname="$thispth/lib$thislib.$so")
125                  && (($Config{'dlsrc'} ne "dl_dld.xs") || ($thislib eq "m"))){
126             } elsif (-f ($fullname="$thispth/lib${thislib}_s$Config_libext")
127                  && (! $Config{'archname'} =~ /RM\d\d\d-svr4/)
128                  && ($thislib .= "_s") ){ # we must explicitly use _s version
129             } elsif (-f ($fullname="$thispth/lib$thislib$Config_libext")){
130             } elsif (-f ($fullname="$thispth/$thislib$Config_libext")){
131             } elsif (-f ($fullname="$thispth/Slib$thislib$Config_libext")){
132             } elsif ($^O eq 'dgux'
133                  && -l ($fullname="$thispth/lib$thislib$Config_libext")
134                  && readlink($fullname) =~ /^elink:/s) {
135                  # Some of DG's libraries look like misconnected symbolic
136                  # links, but development tools can follow them.  (They
137                  # look like this:
138                  #
139                  #    libm.a -> elink:${SDE_PATH:-/usr}/sde/\
140                  #    ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a
141                  #
142                  # , the compilation tools expand the environment variables.)
143             } else {
144                 warn "$thislib not found in $thispth\n" if $verbose;
145                 next;
146             }
147             warn "'-l$thislib' found at $fullname\n" if $verbose;
148             my($fullnamedir) = dirname($fullname);
149             push @ld_run_path, $fullnamedir 
150               unless $ld_run_path_seen{$fullnamedir}++;
151             push @libs, $fullname unless $libs_seen{$fullname}++;
152             $found++;
153             $found_lib++;
154
155             # Now update library lists
156
157             # what do we know about this library...
158             my $is_dyna = ($fullname !~ /\Q$Config_libext\E\z/);
159             my $in_perl = ($libs =~ /\B-l\Q$ {thislib}\E\b/s);
160
161             # Do not add it into the list if it is already linked in
162             # with the main perl executable.
163             # We have to special-case the NeXT, because math and ndbm 
164             # are both in libsys_s
165             unless ($in_perl || 
166                 ($Config{'osname'} eq 'next' &&
167                     ($thislib eq 'm' || $thislib eq 'ndbm')) ){
168                 push(@extralibs, "-l$thislib");
169             }
170
171             # We might be able to load this archive file dynamically
172             if ( ($Config{'dlsrc'} =~ /dl_next/ && $Config{'osvers'} lt '4_0')
173             ||   ($Config{'dlsrc'} =~ /dl_dld/) )
174             {
175                 # We push -l$thislib instead of $fullname because
176                 # it avoids hardwiring a fixed path into the .bs file.
177                 # Mkbootstrap will automatically add dl_findfile() to
178                 # the .bs file if it sees a name in the -l format.
179                 # USE THIS, when dl_findfile() is fixed: 
180                 # push(@bsloadlibs, "-l$thislib");
181                 # OLD USE WAS while checking results against old_extliblist
182                 push(@bsloadlibs, "$fullname");
183             } else {
184                 if ($is_dyna){
185                     # For SunOS4, do not add in this shared library if
186                     # it is already linked in the main perl executable
187                     push(@ldloadlibs, "-l$thislib")
188                         unless ($in_perl and $^O eq 'sunos');
189                 } else {
190                     push(@ldloadlibs, "-l$thislib");
191                 }
192             }
193             last;       # found one here so don't bother looking further
194         }
195         warn "Note (probably harmless): "
196                      ."No library found for -l$thislib\n"
197             unless $found_lib>0;
198     }
199
200     unless( $found ) {
201         return ('','','','', ($give_libs ? \@libs : ()));
202     }
203     else {
204         return ("@extralibs", "@bsloadlibs", "@ldloadlibs",
205                 join(":",@ld_run_path), ($give_libs ? \@libs : ()));
206     }
207 }
208
209 sub _win32_ext {
210
211     require Text::ParseWords;
212
213     my($self, $potential_libs, $verbose, $give_libs) = @_;
214
215     # If user did not supply a list, we punt.
216     # (caller should probably use the list in $Config{libs})
217     return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;
218
219     my $cc              = $Config{cc};
220     my $VC              = 1 if $cc =~ /^cl/i;
221     my $BC              = 1 if $cc =~ /^bcc/i;
222     my $GC              = 1 if $cc =~ /^gcc/i;
223     my $so              = $Config{'so'};
224     my $libs            = $Config{'perllibs'};
225     my $libpth          = $Config{'libpth'};
226     my $libext          = $Config{'lib_ext'} || ".lib";
227     my(@libs, %libs_seen);
228
229     if ($libs and $potential_libs !~ /:nodefault/i) { 
230         # If Config.pm defines a set of default libs, we always
231         # tack them on to the user-supplied list, unless the user
232         # specified :nodefault
233
234         $potential_libs .= " " if $potential_libs;
235         $potential_libs .= $libs;
236     }
237     warn "Potential libraries are '$potential_libs':\n" if $verbose;
238
239     # normalize to forward slashes
240     $libpth =~ s,\\,/,g;
241     $potential_libs =~ s,\\,/,g;
242
243     # compute $extralibs from $potential_libs
244
245     my @searchpath;                 # from "-L/path" in $potential_libs
246     my @libpath         = Text::ParseWords::quotewords('\s+', 0, $libpth);
247     my @extralibs;
248     my $pwd             = cwd();    # from Cwd.pm
249     my $lib             = '';
250     my $found           = 0;
251     my $search          = 1;
252     my($fullname, $thislib, $thispth);
253
254     # add "$Config{installarchlib}/CORE" to default search path
255     push @libpath, "$Config{installarchlib}/CORE";
256
257     if ($VC and exists $ENV{LIB} and $ENV{LIB}) {
258         push @libpath, split /;/, $ENV{LIB};
259     }
260
261     foreach (Text::ParseWords::quotewords('\s+', 0, $potential_libs)){
262
263         $thislib = $_;
264
265         # see if entry is a flag
266         if (/^:\w+$/) {
267             $search     = 0 if lc eq ':nosearch';
268             $search     = 1 if lc eq ':search';
269             warn "Ignoring unknown flag '$thislib'\n"
270                 if $verbose and !/^:(no)?(search|default)$/i;
271             next;
272         }
273
274         # if searching is disabled, do compiler-specific translations
275         unless ($search) {
276             s/^-l(.+)$/$1.lib/ unless $GC;
277             s/^-L/-libpath:/ if $VC;
278             push(@extralibs, $_);
279             $found++;
280             next;
281         }
282
283         # handle possible linker path arguments
284         if (s/^-L// and not -d) {
285             warn "$thislib ignored, directory does not exist\n"
286                 if $verbose;
287             next;
288         }
289         elsif (-d) {
290             unless (File::Spec->file_name_is_absolute($_)) {
291               warn "Warning: '$thislib' changed to '-L$pwd/$_'\n";
292               $_ = $self->catdir($pwd,$_);
293             }
294             push(@searchpath, $_);
295             next;
296         }
297
298         # handle possible library arguments
299         if (s/^-l// and $GC and !/^lib/i) {
300             $_ = "lib$_";
301         }
302         $_ .= $libext if !/\Q$libext\E$/i;
303
304         my $secondpass = 0;
305     LOOKAGAIN:
306
307         # look for the file itself
308         if (-f) {
309             warn "'$thislib' found as '$_'\n" if $verbose;
310             $found++;
311             push(@extralibs, $_);
312             next;
313         }
314
315         my $found_lib = 0;
316         foreach $thispth (@searchpath, @libpath){
317             unless (-f ($fullname="$thispth\\$_")) {
318                 warn "'$thislib' not found as '$fullname'\n" if $verbose;
319                 next;
320             }
321             warn "'$thislib' found as '$fullname'\n" if $verbose;
322             $found++;
323             $found_lib++;
324             push(@extralibs, $fullname);
325             push @libs, $fullname unless $libs_seen{$fullname}++;
326             last;
327         }
328
329         # do another pass with (or without) leading 'lib' if they used -l
330         if (!$found_lib and $thislib =~ /^-l/ and !$secondpass++) {
331             if ($GC) {
332                 goto LOOKAGAIN if s/^lib//i;
333             }
334             elsif (!/^lib/i) {
335                 $_ = "lib$_";
336                 goto LOOKAGAIN;
337             }
338         }
339
340         # give up
341         warn "Note (probably harmless): "
342                      ."No library found for '$thislib'\n"
343             unless $found_lib>0;
344
345     }
346
347     return ('','','','', ($give_libs ? \@libs : ())) unless $found;
348
349     # make sure paths with spaces are properly quoted
350     @extralibs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @extralibs;
351     @libs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @libs;
352     $lib = join(' ',@extralibs);
353
354     # normalize back to backward slashes (to help braindead tools)
355     # XXX this may break equally braindead GNU tools that don't understand
356     # backslashes, either.  Seems like one can't win here.  Cursed be CP/M.
357     $lib =~ s,/,\\,g;
358
359     warn "Result: $lib\n" if $verbose;
360     wantarray ? ($lib, '', $lib, '', ($give_libs ? \@libs : ())) : $lib;
361 }
362
363
364 sub _vms_ext {
365   my($self, $potential_libs,$verbose,$give_libs) = @_;
366   my(@crtls,$crtlstr);
367   my($dbgqual) = $self->{OPTIMIZE} || $Config{'optimize'} ||
368                  $self->{CCFLAS}   || $Config{'ccflags'};
369   @crtls = ( ($dbgqual =~ m-/Debug-i ? $Config{'dbgprefix'} : '')
370               . 'PerlShr/Share' );
371   push(@crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'});
372   push(@crtls, grep { not /\(/ } split /\s+/, $Config{'libc'});
373   # In general, we pass through the basic libraries from %Config unchanged.
374   # The one exception is that if we're building in the Perl source tree, and
375   # a library spec could be resolved via a logical name, we go to some trouble
376   # to insure that the copy in the local tree is used, rather than one to
377   # which a system-wide logical may point.
378   if ($self->{PERL_SRC}) {
379     my($lib,$locspec,$type);
380     foreach $lib (@crtls) { 
381       if (($locspec,$type) = $lib =~ m-^([\w$\-]+)(/\w+)?- and $locspec =~ /perl/i) {
382         if    (lc $type eq '/share')   { $locspec .= $Config{'exe_ext'}; }
383         elsif (lc $type eq '/library') { $locspec .= $Config{'lib_ext'}; }
384         else                           { $locspec .= $Config{'obj_ext'}; }
385         $locspec = $self->catfile($self->{PERL_SRC},$locspec);
386         $lib = "$locspec$type" if -e $locspec;
387       }
388     }
389   }
390   $crtlstr = @crtls ? join(' ',@crtls) : '';
391
392   unless ($potential_libs) {
393     warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
394     return ('', '', $crtlstr, '', ($give_libs ? [] : ()));
395   }
396
397   my(@dirs,@libs,$dir,$lib,%found,@fndlibs,$ldlib);
398   my $cwd = cwd();
399   my($so,$lib_ext,$obj_ext) = @Config{'so','lib_ext','obj_ext'};
400   # List of common Unix library names and there VMS equivalents
401   # (VMS equivalent of '' indicates that the library is automatially
402   # searched by the linker, and should be skipped here.)
403   my(@flibs, %libs_seen);
404   my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
405                  'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '',
406                  'socket' => '', 'X11' => 'DECW$XLIBSHR',
407                  'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR',
408                  'Xmu' => 'DECW$XMULIBSHR');
409   if ($Config{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; }
410
411   warn "Potential libraries are '$potential_libs'\n" if $verbose;
412
413   # First, sort out directories and library names in the input
414   foreach $lib (split ' ',$potential_libs) {
415     push(@dirs,$1),   next if $lib =~ /^-L(.*)/;
416     push(@dirs,$lib), next if $lib =~ /[:>\]]$/;
417     push(@dirs,$lib), next if -d $lib;
418     push(@libs,$1),   next if $lib =~ /^-l(.*)/;
419     push(@libs,$lib);
420   }
421   push(@dirs,split(' ',$Config{'libpth'}));
422
423   # Now make sure we've got VMS-syntax absolute directory specs
424   # (We don't, however, check whether someone's hidden a relative
425   # path in a logical name.)
426   foreach $dir (@dirs) {
427     unless (-d $dir) {
428       warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
429       $dir = '';
430       next;
431     }
432     warn "Resolving directory $dir\n" if $verbose;
433     if (File::Spec->file_name_is_absolute($dir)) { 
434         $dir = $self->fixpath($dir,1); 
435     }
436     else { 
437         $dir = $self->catdir($cwd,$dir); 
438     }
439   }
440   @dirs = grep { length($_) } @dirs;
441   unshift(@dirs,''); # Check each $lib without additions first
442
443   LIB: foreach $lib (@libs) {
444     if (exists $libmap{$lib}) {
445       next unless length $libmap{$lib};
446       $lib = $libmap{$lib};
447     }
448
449     my(@variants,$variant,$name,$test,$cand);
450     my($ctype) = '';
451
452     # If we don't have a file type, consider it a possibly abbreviated name and
453     # check for common variants.  We try these first to grab libraries before
454     # a like-named executable image (e.g. -lperl resolves to perlshr.exe
455     # before perl.exe).
456     if ($lib !~ /\.[^:>\]]*$/) {
457       push(@variants,"${lib}shr","${lib}rtl","${lib}lib");
458       push(@variants,"lib$lib") if $lib !~ /[:>\]]/;
459     }
460     push(@variants,$lib);
461     warn "Looking for $lib\n" if $verbose;
462     foreach $variant (@variants) {
463       foreach $dir (@dirs) {
464         my($type);
465
466         $name = "$dir$variant";
467         warn "\tChecking $name\n" if $verbose > 2;
468         if (-f ($test = VMS::Filespec::rmsexpand($name))) {
469           # It's got its own suffix, so we'll have to figure out the type
470           if    ($test =~ /(?:$so|exe)$/i)      { $type = 'SHR'; }
471           elsif ($test =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; }
472           elsif ($test =~ /(?:$obj_ext|obj)$/i) {
473             warn "Note (probably harmless): "
474                          ."Plain object file $test found in library list\n";
475             $type = 'OBJ';
476           }
477           else {
478             warn "Note (probably harmless): "
479                          ."Unknown library type for $test; assuming shared\n";
480             $type = 'SHR';
481           }
482         }
483         elsif (-f ($test = VMS::Filespec::rmsexpand($name,$so))      or
484                -f ($test = VMS::Filespec::rmsexpand($name,'.exe')))     {
485           $type = 'SHR';
486           $name = $test unless $test =~ /exe;?\d*$/i;
487         }
488         elsif (not length($ctype) and  # If we've got a lib already, don't bother
489                ( -f ($test = VMS::Filespec::rmsexpand($name,$lib_ext)) or
490                  -f ($test = VMS::Filespec::rmsexpand($name,'.olb'))))  {
491           $type = 'OLB';
492           $name = $test unless $test =~ /olb;?\d*$/i;
493         }
494         elsif (not length($ctype) and  # If we've got a lib already, don't bother
495                ( -f ($test = VMS::Filespec::rmsexpand($name,$obj_ext)) or
496                  -f ($test = VMS::Filespec::rmsexpand($name,'.obj'))))  {
497           warn "Note (probably harmless): "
498                        ."Plain object file $test found in library list\n";
499           $type = 'OBJ';
500           $name = $test unless $test =~ /obj;?\d*$/i;
501         }
502         if (defined $type) {
503           $ctype = $type; $cand = $name;
504           last if $ctype eq 'SHR';
505         }
506       }
507       if ($ctype) { 
508         # This has to precede any other CRTLs, so just make it first
509         if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; }  
510         else                      { push    @{$found{$ctype}}, $cand; }
511         warn "\tFound as $cand (really $test), type $ctype\n" if $verbose > 1;
512         push @flibs, $name unless $libs_seen{$fullname}++;
513         next LIB;
514       }
515     }
516     warn "Note (probably harmless): "
517                  ."No library found for $lib\n";
518   }
519
520   push @fndlibs, @{$found{OBJ}}                      if exists $found{OBJ};
521   push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB};
522   push @fndlibs, map { "$_/Share"   } @{$found{SHR}} if exists $found{SHR};
523   $lib = join(' ',@fndlibs);
524
525   $ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
526   warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
527   wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib;
528 }
529
530 1;