This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix $Config{ccflags} for Win32 perls built with dmake
[perl5.git] / configpm
index 3f4cb46..874e3f3 100755 (executable)
--- a/configpm
+++ b/configpm
@@ -2,14 +2,17 @@
 use strict;
 use vars qw(%Config $Config_SH_expanded);
 
-# commonly used names to put first (and hence lookup fastest)
-my %Common = map {($_,$_)}
-             qw(archname osname osvers prefix libs libpth
-                dynamic_ext static_ext dlsrc so
-                cc ccflags cppflags
-                privlibexp archlibexp installprivlib installarchlib
-                sharpbang startsh shsharp
-               );
+my $how_many_common = 22;
+
+# commonly used names to precache (and hence lookup fastest)
+my %Common;
+
+while ($how_many_common--) {
+    $_ = <DATA>;
+    chomp;
+    /^(\S+):\s*(\d+)$/ or die "Malformed line '$_'";
+    $Common{$1} = $1;
+}
 
 # names of things which may need to have slashes changed to double-colons
 my %Extensions = map {($_,$_)}
@@ -79,7 +82,7 @@ use strict;
 # use vars pulls in Carp
 ENDOFBEG
 
-my $myver = sprintf "v%vd", $^V;
+my $myver = sprintf "%vd", $^V;
 
 printf CONFIG <<'ENDOFBEG', ($myver) x 3;
 # This file was created by configpm when Perl was built. Any changes
@@ -92,6 +95,14 @@ use strict;
 @Config::EXPORT = qw(%%Config);
 @Config::EXPORT_OK = qw(myconfig config_sh config_vars config_re);
 
+# Need to stub all the functions to make code such as print Config::config_sh
+# keep working
+
+sub myconfig;
+sub config_sh;
+sub config_vars;
+sub config_re;
+
 my %%Export_Cache = map {($_ => 1)} (@Config::EXPORT, @Config::EXPORT_OK);
 
 our %%Config;
@@ -127,60 +138,12 @@ ENDOFBEG
 
 
 my @non_v    = ();
-my @v_fast   = ();
-my %v_fast   = ();
 my @v_others = ();
 my $in_v     = 0;
 my %Data     = ();
 
-# This is somewhat grim, but I want the code for parsing config.sh here and
-# now so that I can expand $Config{ivsize} and $Config{ivtype}
-
-my $fetch_string = <<'EOT';
-
-# Search for it in the big string 
-sub fetch_string {
-    my($self, $key) = @_;
-
-    my $quote_type = "'";
-    my $marker = "$key=";
-
-    # Check for the common case, ' delimited
-    my $start = index($Config_SH_expanded, "\n$marker$quote_type");
-    # If that failed, check for " delimited
-    if ($start == -1) {
-        $quote_type = '"';
-        $start = index($Config_SH_expanded, "\n$marker$quote_type");
-    }
-    # Start can never be -1 now, as we've rigged the long string we're
-    # searching with an initial dummy newline.
-    return undef if $start == -1;
-
-    $start += length($marker) + 2;
-
-    my $value = substr($Config_SH_expanded, $start, 
-                       index($Config_SH_expanded, "$quote_type\n", $start)
-                      - $start);
-
-    # If we had a double-quote, we'd better eval it so escape
-    # sequences and such can be interpolated. Since the incoming
-    # value is supposed to follow shell rules and not perl rules,
-    # we escape any perl variable markers
-    if ($quote_type eq '"') {
-       $value =~ s/\$/\\\$/g;
-       $value =~ s/\@/\\\@/g;
-       eval "\$value = \"$value\"";
-    }
-
-    # So we can say "if $Config{'foo'}".
-    $value = undef if $value eq 'undef';
-    $self->{$key} = $value; # cache it
-}
-EOT
-
-eval $fetch_string;
-die if $@;
 
+my %seen_quotes;
 {
   my ($name, $val);
   open(CONFIG_SH, 'config.sh') || die "Can't open config.sh: $!";
@@ -224,21 +187,88 @@ die if $@;
     $val =~ s/$quote\n?\z//;
 
     my $line = "$name=$quote$val$quote\n";
-    if (!$Common{$name}){
-        push(@v_others, $line);
-    }
-    else {
-        push(@v_fast, $line);
-        $v_fast{$name} = "'$name' => $quote$val$quote";
-    }
+    push(@v_others, $line);
+    $seen_quotes{$quote}++;
   }
   close CONFIG_SH;
 }
 
+# This is somewhat grim, but I want the code for parsing config.sh here and
+# now so that I can expand $Config{ivsize} and $Config{ivtype}
+
+my $fetch_string = <<'EOT';
+
+# Search for it in the big string
+sub fetch_string {
+    my($self, $key) = @_;
+
+EOT
+
+if ($seen_quotes{'"'}) {
+    # We need the full ' and " code
+    $fetch_string .= <<'EOT';
+    my $quote_type = "'";
+    my $marker = "$key=";
+
+    # Check for the common case, ' delimited
+    my $start = index($Config_SH_expanded, "\n$marker$quote_type");
+    # If that failed, check for " delimited
+    if ($start == -1) {
+        $quote_type = '"';
+        $start = index($Config_SH_expanded, "\n$marker$quote_type");
+    }
+EOT
+} else {
+    $fetch_string .= <<'EOT';
+    # We only have ' delimted.
+    my $start = index($Config_SH_expanded, "\n$key=\'");
+EOT
+}
+$fetch_string .= <<'EOT';
+    # Start can never be -1 now, as we've rigged the long string we're
+    # searching with an initial dummy newline.
+    return undef if $start == -1;
+
+    $start += length($key) + 3;
+
+EOT
+if (!$seen_quotes{'"'}) {
+    # Don't need the full ' and " code, or the eval expansion.
+    $fetch_string .= <<'EOT';
+    my $value = substr($Config_SH_expanded, $start,
+                       index($Config_SH_expanded, "'\n", $start)
+                      - $start);
+EOT
+} else {
+    $fetch_string .= <<'EOT';
+    my $value = substr($Config_SH_expanded, $start,
+                       index($Config_SH_expanded, "$quote_type\n", $start)
+                      - $start);
+
+    # If we had a double-quote, we'd better eval it so escape
+    # sequences and such can be interpolated. Since the incoming
+    # value is supposed to follow shell rules and not perl rules,
+    # we escape any perl variable markers
+    if ($quote_type eq '"') {
+       $value =~ s/\$/\\\$/g;
+       $value =~ s/\@/\\\@/g;
+       eval "\$value = \"$value\"";
+    }
+EOT
+}
+$fetch_string .= <<'EOT';
+    # So we can say "if $Config{'foo'}".
+    $value = undef if $value eq 'undef';
+    $self->{$key} = $value; # cache it
+}
+EOT
+
+eval $fetch_string;
+die if $@;
 
 # Calculation for the keys for byteorder
 # This is somewhat grim, but I need to run fetch_string here.
-our $Config_SH_expanded = join "\n", '', @v_fast, @v_others;
+our $Config_SH_expanded = join "\n", '', @v_others;
 
 my $t = fetch_string ({}, 'ivtype');
 my $s = fetch_string ({}, 'ivsize');
@@ -255,6 +285,7 @@ if ($s == 4 || $s == 8) {
     my $list = join ',', reverse(2..$s);
     my $format = 'a'x$s;
     $byteorder_code = <<"EOT";
+
 my \$i = 0;
 foreach my \$c ($list) { \$i |= ord(\$c); \$i <<= 8 }
 \$i |= ord(1);
@@ -263,21 +294,80 @@ EOT
 } else {
     $byteorder_code = "our \$byteorder = '?'x$s;\n";
 }
-print CONFIG $byteorder_code;
+
+my @need_relocation;
+
+if (fetch_string({},'userelocatableinc')) {
+    foreach my $what (qw(archlibexp
+                        privlibexp
+                        sitearchexp
+                        sitelibexp
+                        sitelib_stem
+                        vendorarchexp
+                        vendorlibexp
+                        vendorlib_stem)) {
+       push @need_relocation, $what if fetch_string({}, $what) =~ m!^\.\.\./!;
+    }
+}
+
+my %need_relocation;
+@need_relocation{@need_relocation} = @need_relocation;
+
+# This can have .../ anywhere:
+if (fetch_string({}, 'otherlibdirs') =~ m!\.\.\./!) {
+    $need_relocation{otherlibdirs} = 'otherlibdirs';
+}
+
+my $relocation_code = <<'EOT';
+
+sub relocate_inc {
+  my $libdir = shift;
+  return $libdir unless $libdir =~ s!^\.\.\./!!;
+  my $prefix = $^X;
+  if ($prefix =~ s!/[^/]*$!!) {
+    while ($libdir =~ m!^\.\./!) {
+      # Loop while $libdir starts "../" and $prefix still has a trailing
+      # directory
+      last unless $prefix =~ s!/([^/]+)$!!;
+      # but bail out if the directory we picked off the end of $prefix is .
+      # or ..
+      if ($1 eq '.' or $1 eq '..') {
+       # Undo! This should be rare, hence code it this way rather than a
+       # check each time before the s!!! above.
+       $prefix = "$prefix/$1";
+       last;
+      }
+      # Remove that leading ../ and loop again
+      substr ($libdir, 0, 3, '');
+    }
+    $libdir = "$prefix/$libdir";
+  }
+  $libdir;
+}
+EOT
+
+if (%need_relocation) {
+  my $relocations_in_common;
+  # otherlibdirs only features in the hash
+  foreach (keys %need_relocation) {
+    $relocations_in_common++ if $Common{$_};
+  }
+  if ($relocations_in_common) {
+    print CONFIG $relocation_code;
+  } else {
+    print CONFIG_HEAVY $relocation_code;
+  }
+}
 
 print CONFIG_HEAVY @non_v, "\n";
 
 # copy config summary format from the myconfig.SH script
-print CONFIG_HEAVY "our \$summary : unique = <<'!END!';\n";
+print CONFIG_HEAVY "our \$summary = <<'!END!';\n";
 open(MYCONFIG,"<myconfig.SH") || die "open myconfig.SH failed: $!";
 1 while defined($_ = <MYCONFIG>) && !/^Summary of/;
 do { print CONFIG_HEAVY $_ } until !defined($_ = <MYCONFIG>) || /^\s*$/;
 close(MYCONFIG);
 
-# NB. as $summary is unique, we need to copy it in a lexical variable
-# before expanding it, because may have been made readonly if a perl
-# interpreter has been cloned.
-
 print CONFIG_HEAVY "\n!END!\n", <<'EOT';
 my $summary_expanded;
 
@@ -292,25 +382,54 @@ local *_ = \my $a;
 $_ = <<'!END!';
 EOT
 
-print CONFIG_HEAVY join("", @v_fast, sort @v_others);
+print CONFIG_HEAVY join('', sort @v_others), "!END!\n";
+
+# Only need the dynamic byteorder code in Config.pm if 'byteorder' is one of
+# the precached keys
+if ($Common{byteorder}) {
+    print CONFIG $byteorder_code;
+} else {
+    print CONFIG_HEAVY $byteorder_code;
+}
+
+if (@need_relocation) {
+print CONFIG_HEAVY 'foreach my $what (qw(', join (' ', @need_relocation),
+      ")) {\n", <<'EOT';
+    s/^($what=)(['"])(.*?)\2/$1 . $2 . relocate_inc($3) . $2/me;
+}
+EOT
+# Currently it only makes sense to do the ... relocation on Unix, so there's
+# no need to emulate the "which separator for this platform" logic in perl.c -
+# ':' will always be applicable
+if ($need_relocation{otherlibdirs}) {
+print CONFIG_HEAVY << 'EOT';
+s{^(otherlibdirs=)(['"])(.*?)\2}
+ {$1 . $2 . join ':', map {relocate_inc($_)} split ':', $3 . $2}me;
+EOT
+}
+}
 
 print CONFIG_HEAVY <<'EOT';
-!END!
 s/(byteorder=)(['"]).*?\2/$1$2$Config::byteorder$2/m;
-our $Config_SH : unique = $_;
 
-our $Config_SH_expanded : unique = "\n$_" . << 'EOVIRTUAL';
+my $config_sh_len = length $_;
+
+our $Config_SH_expanded = "\n$_" . << 'EOVIRTUAL';
 EOT
 
 foreach my $prefix (qw(ccflags ldflags)) {
     my $value = fetch_string ({}, $prefix);
     my $withlargefiles = fetch_string ({}, $prefix . "_uselargefiles");
-    $value =~ s/\Q$withlargefiles\E\b//;
-    print CONFIG_HEAVY "${prefix}_nolargefiles='$value'\n";
+    if (defined $withlargefiles) {
+        $value =~ s/\Q$withlargefiles\E\b//;
+        print CONFIG_HEAVY "${prefix}_nolargefiles='$value'\n";
+    }
 }
 
 foreach my $prefix (qw(libs libswanted)) {
     my $value = fetch_string ({}, $prefix);
+    my $withlf = fetch_string ({}, 'libswanted_uselargefiles');
+    next unless defined $withlf;
     my @lflibswanted
        = split(' ', fetch_string ({}, 'libswanted_uselargefiles'));
     if (@lflibswanted) {
@@ -347,6 +466,7 @@ sub FETCH {
 ENDOFEND
 
 print CONFIG_HEAVY <<'ENDOFEND';
+
 my $prevpos = 0;
 
 sub FIRSTKEY {
@@ -355,10 +475,21 @@ sub FIRSTKEY {
 }
 
 sub NEXTKEY {
+ENDOFEND
+if ($seen_quotes{'"'}) {
+print CONFIG_HEAVY <<'ENDOFEND';
     # Find out how the current key's quoted so we can skip to its end.
     my $quote = substr($Config_SH_expanded,
                       index($Config_SH_expanded, "=", $prevpos)+1, 1);
     my $pos = index($Config_SH_expanded, qq($quote\n), $prevpos) + 2;
+ENDOFEND
+} else {
+    # Just ' quotes, so it's much easier.
+print CONFIG_HEAVY <<'ENDOFEND';
+    my $pos = index($Config_SH_expanded, qq('\n), $prevpos) + 2;
+ENDOFEND
+}
+print CONFIG_HEAVY <<'ENDOFEND';
     my $len = index($Config_SH_expanded, "=", $pos) - $pos;
     $prevpos = $pos;
     $len > 0 ? substr($Config_SH_expanded, $pos, $len) : undef;
@@ -367,8 +498,14 @@ sub NEXTKEY {
 sub EXISTS {
     return 1 if exists($_[0]->{$_[1]});
 
-    return(index($Config_SH_expanded, "\n$_[1]='") != -1 or
-           index($Config_SH_expanded, "\n$_[1]=\"") != -1
+    return(index($Config_SH_expanded, "\n$_[1]='") != -1
+ENDOFEND
+if ($seen_quotes{'"'}) {
+print CONFIG_HEAVY <<'ENDOFEND';
+           or index($Config_SH_expanded, "\n$_[1]=\"") != -1
+ENDOFEND
+}
+print CONFIG_HEAVY <<'ENDOFEND';
           );
 }
 
@@ -378,7 +515,7 @@ sub STORE  { die "\%Config::Config is read-only\n" }
 
 
 sub config_sh {
-    $Config_SH
+    substr $Config_SH_expanded, 1, $config_sh_len;
 }
 
 sub config_re {
@@ -451,24 +588,46 @@ sub TIEHASH {
 ENDOFSET
 }
 
-my $fast_config = join '', map { "    $_,\n" }
-    sort values (%v_fast), 'byteorder => $byteorder' ;
+foreach my $key (keys %Common) {
+    my $value = fetch_string ({}, $key);
+    # Is it safe on the LHS of => ?
+    my $qkey = $key =~ /^[A-Za-z_][A-Za-z0-9_]*$/ ? $key : "'$key'";
+    if (defined $value) {
+       # Quote things for a '' string
+       $value =~ s!\\!\\\\!g;
+       $value =~ s!'!\\'!g;
+       $value = "'$value'";
+       if ($key eq 'otherlibdirs') {
+           $value = "join (':', map {relocate_inc(\$_)} split (':', $value))";
+       } elsif ($need_relocation{$key}) {
+           $value = "relocate_inc($value)";
+       }
+    } else {
+       $value = "undef";
+    }
+    $Common{$key} = "$qkey => $value";
+}
 
+if ($Common{byteorder}) {
+    $Common{byteorder} = 'byteorder => $byteorder';
+}
+my $fast_config = join '', map { "    $_,\n" } sort values %Common;
+
+# Sanity check needed to stop an infite loop if Config_heavy.pl fails to define
+# &launcher for some reason (eg it got truncated)
 print CONFIG sprintf <<'ENDOFTIE', $fast_config;
 
 sub DESTROY { }
 
 sub AUTOLOAD {
-    require 'config_heavy.pl';
-    goto \&launcher;
+    require 'Config_heavy.pl';
+    goto \&launcher unless $Config::AUTOLOAD =~ /launcher$/;
     die "&Config::AUTOLOAD failed on $Config::AUTOLOAD";
 }
 
+# tie returns the object, so the value returned to require will be true.
 tie %%Config, 'Config', {
-%s
-};
-
-1;
+%s};
 ENDOFTIE
 
 
@@ -704,7 +863,9 @@ EOS
 
 # Now do some simple tests on the Config.pm file we have created
 unshift(@INC,'lib');
+unshift(@INC,'xlib/symbian') if $Opts{cross};
 require $Config_PM;
+require $Config_heavy;
 import Config;
 
 die "$0: $Config_PM not valid"
@@ -722,3 +883,106 @@ die "$0: error processing $Config_PM"
 
 
 exit 0;
+# Popularity of various entries in %Config, based on a large build and test
+# run of code in the Fotango build system:
+__DATA__
+path_sep:      8490
+d_readlink:    7101
+d_symlink:     7101
+archlibexp:    4318
+sitearchexp:   4305
+sitelibexp:    4305
+privlibexp:    4163
+ldlibpthname:  4041
+libpth:        2134
+archname:      1591
+exe_ext:       1256
+scriptdir:     1155
+version:       1116
+useithreads:   1002
+osvers:        982
+osname:        851
+inc_version_list:      783
+dont_use_nlink:        779
+intsize:       759
+usevendorprefix:       642
+dlsrc: 624
+cc:    541
+lib_ext:       520
+so:    512
+ld:    501
+ccdlflags:     500
+ldflags:       495
+obj_ext:       495
+cccdlflags:    493
+lddlflags:     493
+ar:    492
+dlext: 492
+libc:  492
+ranlib:        492
+full_ar:       491
+vendorarchexp: 491
+vendorlibexp:  491
+installman1dir:        489
+installman3dir:        489
+installsitebin:        489
+installsiteman1dir:    489
+installsiteman3dir:    489
+installvendorman1dir:  489
+installvendorman3dir:  489
+d_flexfnam:    474
+eunicefix:     360
+d_link:        347
+installsitearch:       344
+installscript: 341
+installprivlib:        337
+binexp:        336
+installarchlib:        336
+installprefixexp:      336
+installsitelib:        336
+installstyle:  336
+installvendorarch:     336
+installvendorbin:      336
+installvendorlib:      336
+man1ext:       336
+man3ext:       336
+sh:    336
+siteprefixexp: 336
+installbin:    335
+usedl: 332
+ccflags:       285
+startperl:     232
+optimize:      231
+usemymalloc:   229
+cpprun:        228
+sharpbang:     228
+perllibs:      225
+usesfio:       224
+usethreads:    220
+perlpath:      218
+extensions:    217
+usesocks:      208
+shellflags:    198
+make:  191
+d_pwage:       189
+d_pwchange:    189
+d_pwclass:     189
+d_pwcomment:   189
+d_pwexpire:    189
+d_pwgecos:     189
+d_pwpasswd:    189
+d_pwquota:     189
+gccversion:    189
+libs:  186
+useshrplib:    186
+cppflags:      185
+ptrsize:       185
+shrpenv:       185
+static_ext:    185
+use5005threads:        185
+uselargefiles: 185
+alignbytes:    184
+byteorder:     184
+ccversion:     184
+config_args:   184
+cppminus:      184