Generate the virtual entries at Config.pm build time, as they
[p5sagit/p5-mst-13.2.git] / configpm
1 #!./miniperl -w
2
3 # commonly used names to put first (and hence lookup fastest)
4 my %Common = map {($_,$_)}
5              qw(archname osname osvers prefix libs libpth
6                 dynamic_ext static_ext dlsrc so
7                 cc ccflags cppflags
8                 privlibexp archlibexp installprivlib installarchlib
9                 sharpbang startsh shsharp
10                );
11
12 # names of things which may need to have slashes changed to double-colons
13 my %Extensions = map {($_,$_)}
14                  qw(dynamic_ext static_ext extensions known_extensions);
15
16 # allowed opts as well as specifies default and initial values
17 my %Allowed_Opts = (
18     'cross'    => '', # --cross=PALTFORM - crosscompiling for PLATFORM
19     'glossary' => 1,  # --no-glossary  - no glossary file inclusion, 
20                       #                  for compactness
21 );
22
23 sub opts {
24     # user specified options
25     my %given_opts = (
26         # --opt=smth
27         (map {/^--([\-_\w]+)=(.*)$/} @ARGV),
28         # --opt --no-opt --noopt
29         (map {/^no-?(.*)$/i?($1=>0):($_=>1)} map {/^--([\-_\w]+)$/} @ARGV),
30     );
31
32     my %opts = (%Allowed_Opts, %given_opts);
33
34     for my $opt (grep {!exists $Allowed_Opts{$_}} keys %given_opts) {
35         die "option '$opt' is not recognized";
36     }
37     @ARGV = grep {!/^--/} @ARGV;
38
39     return %opts;
40 }
41
42
43 my %Opts = opts();
44
45 my $Config_PM;
46 my $Glossary = $ARGV[1] || 'Porting/Glossary';
47
48 if ($Opts{cross}) {
49   # creating cross-platform config file
50   mkdir "xlib";
51   mkdir "xlib/$Opts{cross}";
52   $Config_PM = $ARGV[0] || "xlib/$Opts{cross}/Config.pm";
53 }
54 else {
55   $Config_PM = $ARGV[0] || 'lib/Config.pm';
56 }
57
58
59 open CONFIG, ">$Config_PM" or die "Can't open $Config_PM: $!\n";
60
61 my $myver = sprintf "v%vd", $^V;
62
63 printf CONFIG <<'ENDOFBEG', ($myver) x 3;
64 # This file was created by configpm when Perl was built. Any changes
65 # made to this file will be lost the next time perl is built.
66
67 package Config;
68 @EXPORT = qw(%%Config);
69 @EXPORT_OK = qw(myconfig config_sh config_vars config_re);
70
71 my %%Export_Cache = map {($_ => 1)} (@EXPORT, @EXPORT_OK);
72
73 # Define our own import method to avoid pulling in the full Exporter:
74 sub import {
75     my $pkg = shift;
76     @_ = @EXPORT unless @_;
77
78     my @funcs = grep $_ ne '%%Config', @_;
79     my $export_Config = @funcs < @_ ? 1 : 0;
80
81     my $callpkg = caller(0);
82     foreach my $func (@funcs) {
83         die sprintf qq{"%%s" is not exported by the %%s module\n},
84             $func, __PACKAGE__ unless $Export_Cache{$func};
85         *{$callpkg.'::'.$func} = \&{$func};
86     }
87
88     *{"$callpkg\::Config"} = \%%Config if $export_Config;
89     return;
90 }
91
92 die "Perl lib version (%s) doesn't match executable version ($])"
93     unless $^V;
94
95 $^V eq %s
96     or die "Perl lib version (%s) doesn't match executable version (" .
97         sprintf("v%%vd",$^V) . ")";
98
99 ENDOFBEG
100
101
102 my @non_v    = ();
103 my @v_fast   = ();
104 my %v_fast   = ();
105 my @v_others = ();
106 my $in_v     = 0;
107 my %Data     = ();
108
109 # This is somewhat grim, but I want the code for parsing config.sh here and
110 # now so that I can expand $Config{ivsize} and $Config{ivtype}
111
112 my $fetch_string = <<'EOT';
113
114 # Search for it in the big string 
115 sub fetch_string {
116     my($self, $key) = @_;
117
118     my $quote_type = "'";
119     my $marker = "$key=";
120
121     # Check for the common case, ' delimited
122     my $start = index($Config_SH_expanded, "\n$marker$quote_type");
123     # If that failed, check for " delimited
124     if ($start == -1) {
125         $quote_type = '"';
126         $start = index($Config_SH_expanded, "\n$marker$quote_type");
127     }
128     # Start can never be -1 now, as we've rigged the long string we're
129     # searching with an initial dummy newline.
130     return undef if $start == -1;
131
132     $start += length($marker) + 2;
133
134     my $value = substr($Config_SH_expanded, $start, 
135                        index($Config_SH_expanded, "$quote_type\n", $start)
136                        - $start);
137
138     # If we had a double-quote, we'd better eval it so escape
139     # sequences and such can be interpolated. Since the incoming
140     # value is supposed to follow shell rules and not perl rules,
141     # we escape any perl variable markers
142     if ($quote_type eq '"') {
143         $value =~ s/\$/\\\$/g;
144         $value =~ s/\@/\\\@/g;
145         eval "\$value = \"$value\"";
146     }
147
148     # So we can say "if $Config{'foo'}".
149     $value = undef if $value eq 'undef';
150     $self->{$key} = $value; # cache it
151 }
152 EOT
153
154 eval $fetch_string;
155 die if $@;
156
157 open(CONFIG_SH, 'config.sh') || die "Can't open config.sh: $!";
158 while (<CONFIG_SH>) {
159     next if m:^#!/bin/sh:;
160
161     # Catch PERL_CONFIG_SH=true and PERL_VERSION=n line from Configure.
162     s/^(\w+)=(true|\d+)\s*$/$1='$2'\n/ or m/^(\w+)='(.*)'$/;
163     my($k, $v) = ($1, $2);
164
165     # grandfather PATCHLEVEL and SUBVERSION and CONFIG
166     if ($k) {
167         if ($k eq 'PERL_VERSION') {
168             push @v_others, "PATCHLEVEL='$v'\n";
169         }
170         elsif ($k eq 'PERL_SUBVERSION') {
171             push @v_others, "SUBVERSION='$v'\n";
172         }
173         elsif ($k eq 'PERL_CONFIG_SH') {
174             push @v_others, "CONFIG='$v'\n";
175         }
176     }
177
178     # We can delimit things in config.sh with either ' or ". 
179     unless ($in_v or m/^(\w+)=(['"])(.*\n)/){
180         push(@non_v, "#$_"); # not a name='value' line
181         next;
182     }
183     $quote = $2;
184     if ($in_v) { 
185         $val .= $_;
186     }
187     else { 
188         ($name,$val) = ($1,$3); 
189     }
190     $in_v = $val !~ /$quote\n/;
191     next if $in_v;
192
193     s,/,::,g if $Extensions{$name};
194
195     $val =~ s/$quote\n?\z//;
196
197     my $line = "$name=$quote$val$quote\n";
198     if (!$Common{$name}){
199         push(@v_others, $line);
200     }
201     else {
202         push(@v_fast, $line);
203         $v_fast{$name} = "'$name' => $quote$val$quote";
204     }
205 }
206 close CONFIG_SH;
207
208 # Calculation for the keys for byteorder
209 # This is somewhat grim, but I need to run fetch_string here.
210 our $Config_SH_expanded = join "\n", '', @v_fast, @v_others;
211
212 my $t = fetch_string ({}, 'ivtype');
213 my $s = fetch_string ({}, 'ivsize');
214
215 # byteorder does exist on its own but we overlay a virtual
216 # dynamically recomputed value.
217
218 # However, ivtype and ivsize will not vary for sane fat binaries
219
220 my $f = $t eq 'long' ? 'L!' : $s == 8 ? 'Q': 'I';
221
222 my $byteorder_code;
223 if ($s == 4 || $s == 8) {
224     my $list = join ',', reverse(2..$s);
225     my $format = 'a'x$s;
226     $byteorder_code = <<"EOT";
227 my \$i = 0;
228 foreach my \$c ($list) { \$i |= ord(\$c); \$i <<= 8 }
229 \$i |= ord(1);
230 my \$byteorder = join('', unpack('$format', pack('$f', \$i)));
231 EOT
232 } else {
233     $byteorder_code = "my \$byteorder = '?'x$s;\n";
234 }
235
236 print CONFIG @non_v, "\n";
237
238 # copy config summary format from the myconfig.SH script
239 print CONFIG "our \$summary : unique = <<'!END!';\n";
240 open(MYCONFIG,"<myconfig.SH") || die "open myconfig.SH failed: $!";
241 1 while defined($_ = <MYCONFIG>) && !/^Summary of/;
242 do { print CONFIG $_ } until !defined($_ = <MYCONFIG>) || /^\s*$/;
243 close(MYCONFIG);
244
245 # NB. as $summary is unique, we need to copy it in a lexical variable
246 # before expanding it, because may have been made readonly if a perl
247 # interpreter has been cloned.
248
249 print CONFIG "\n!END!\n", $byteorder_code, <<'EOT';
250 my $summary_expanded;
251
252 sub myconfig {
253     return $summary_expanded if $summary_expanded;
254     ($summary_expanded = $summary) =~ s{\$(\w+)}
255                  { my $c = $Config{$1}; defined($c) ? $c : 'undef' }ge;
256     $summary_expanded;
257 }
258
259 local *_ = \my $a;
260 $_ = <<'!END!';
261 EOT
262
263 print CONFIG join("", @v_fast, sort @v_others);
264
265 print CONFIG <<'EOT';
266 !END!
267 s/(byteorder=)(['"]).*?\2/$1$2$byteorder$2/m;
268 our $Config_SH : unique = $_;
269
270 our $Config_SH_expanded : unique = "\n$_" . << 'EOVIRTUAL';
271 EOT
272
273 foreach my $prefix (qw(ccflags ldflags)) {
274     my $value = fetch_string ({}, $prefix);
275     my $withlargefiles = fetch_string ({}, $prefix . "_uselargefiles");
276     $value =~ s/\Q$withlargefiles\E\b//;
277     print CONFIG "${prefix}_nolargefiles='$value'\n";
278 }
279
280 foreach my $prefix (qw(libs libswanted)) {
281     my $value = fetch_string ({}, $prefix);
282     my @lflibswanted
283        = split(' ', fetch_string ({}, 'libswanted_uselargefiles'));
284     if (@lflibswanted) {
285         my %lflibswanted;
286         @lflibswanted{@lflibswanted} = ();
287         if ($prefix eq 'libs') {
288             my @libs = grep { /^-l(.+)/ &&
289                             not exists $lflibswanted{$1} }
290                                     split(' ', fetch_string ({}, 'libs'));
291             $value = join(' ', @libs);
292         } else {
293             my @libswanted = grep { not exists $lflibswanted{$_} }
294                                   split(' ', fetch_string ({}, 'libswanted'));
295             $value = join(' ', @libswanted);
296         }
297     }
298     print CONFIG "${prefix}_nolargefiles='$value'\n";
299 }
300
301 print CONFIG "EOVIRTUAL\n";
302
303 print CONFIG $fetch_string;
304
305 print CONFIG <<'ENDOFEND';
306
307 sub FETCH { 
308     my($self, $key) = @_;
309
310     # check for cached value (which may be undef so we use exists not defined)
311     return $self->{$key} if exists $self->{$key};
312
313     return $self->fetch_string($key);
314 }
315  
316 my $prevpos = 0;
317
318 sub FIRSTKEY {
319     $prevpos = 0;
320     substr($Config_SH_expanded, 0, index($Config_SH_expanded, '=') );
321 }
322
323 sub NEXTKEY {
324     # Find out how the current key's quoted so we can skip to its end.
325     my $quote = substr($Config_SH_expanded,
326                        index($Config_SH_expanded, "=", $prevpos)+1, 1);
327     my $pos = index($Config_SH_expanded, qq($quote\n), $prevpos) + 2;
328     my $len = index($Config_SH_expanded, "=", $pos) - $pos;
329     $prevpos = $pos;
330     $len > 0 ? substr($Config_SH_expanded, $pos, $len) : undef;
331 }
332
333 sub EXISTS { 
334     return 1 if exists($_[0]->{$_[1]});
335
336     return(index($Config_SH_expanded, "\n$_[1]='") != -1 or
337            substr($Config_SH_expanded, 0, length($_[1])+2) eq "$_[1]='" or
338            index($Config_SH_expanded, "\n$_[1]=\"") != -1 or
339            substr($Config_SH_expanded, 0, length($_[1])+2) eq "$_[1]=\"" or
340            $_[1] =~ /^(?:(?:cc|ld)flags|libs(?:wanted)?)_nolargefiles$/
341           );
342 }
343
344 sub STORE  { die "\%Config::Config is read-only\n" }
345 *DELETE = \&STORE;
346 *CLEAR  = \&STORE;
347
348
349 sub config_sh {
350     $Config_SH
351 }
352
353 sub config_re {
354     my $re = shift;
355     return map { chomp; $_ } grep eval{ /^(?:$re)=/ }, split /^/,
356     $Config_SH_expanded;
357 }
358
359 sub config_vars {
360     # implements -V:cfgvar option (see perlrun -V:)
361     foreach (@_) {
362         # find optional leading, trailing colons; and query-spec
363         my ($notag,$qry,$lncont) = m/^(:)?(.*?)(:)?$/;  # flags fore and aft, 
364         # map colon-flags to print decorations
365         my $prfx = $notag ? '': "$qry=";                # tag-prefix for print
366         my $lnend = $lncont ? ' ' : ";\n";              # line ending for print
367
368         # all config-vars are by definition \w only, any \W means regex
369         if ($qry =~ /\W/) {
370             my @matches = config_re($qry);
371             print map "$_$lnend", @matches ? @matches : "$qry: not found"               if !$notag;
372             print map { s/\w+=//; "$_$lnend" } @matches ? @matches : "$qry: not found"  if  $notag;
373         } else {
374             my $v = (exists $Config{$qry}) ? $Config{$qry} : 'UNKNOWN';
375             $v = 'undef' unless defined $v;
376             print "${prfx}'${v}'$lnend";
377         }
378     }
379 }
380
381 ENDOFEND
382
383 if ($^O eq 'os2') {
384     print CONFIG <<'ENDOFSET';
385 my %preconfig;
386 if ($OS2::is_aout) {
387     my ($value, $v) = $Config_SH_expanded =~ m/^used_aout='(.*)'\s*$/m;
388     for (split ' ', $value) {
389         ($v) = $Config_SH_expanded =~ m/^aout_$_='(.*)'\s*$/m;
390         $preconfig{$_} = $v eq 'undef' ? undef : $v;
391     }
392 }
393 $preconfig{d_fork} = undef unless $OS2::can_fork; # Some funny cases can't
394 sub TIEHASH { bless {%preconfig} }
395 ENDOFSET
396     # Extract the name of the DLL from the makefile to avoid duplication
397     my ($f) = grep -r, qw(GNUMakefile Makefile);
398     my $dll;
399     if (open my $fh, '<', $f) {
400         while (<$fh>) {
401             $dll = $1, last if /^PERL_DLL_BASE\s*=\s*(\S*)\s*$/;
402         }
403     }
404     print CONFIG <<ENDOFSET if $dll;
405 \$preconfig{dll_name} = '$dll';
406 ENDOFSET
407 } else {
408     print CONFIG <<'ENDOFSET';
409 sub TIEHASH {
410     bless $_[1], $_[0];
411 }
412 ENDOFSET
413 }
414
415 my $fast_config = join '', map { "    $_,\n" }
416     sort values (%v_fast), 'byteorder => $byteorder' ;
417
418 print CONFIG sprintf <<'ENDOFTIE', $fast_config;
419
420 # avoid Config..Exporter..UNIVERSAL search for DESTROY then AUTOLOAD
421 sub DESTROY { }
422
423 tie %%Config, 'Config', {
424 %s
425 };
426
427 1;
428 ENDOFTIE
429
430
431 open(CONFIG_POD, ">lib/Config.pod") or die "Can't open lib/Config.pod: $!";
432 print CONFIG_POD <<'ENDOFTAIL';
433 =head1 NAME
434
435 Config - access Perl configuration information
436
437 =head1 SYNOPSIS
438
439     use Config;
440     if ($Config{usethreads}) {
441         print "has thread support\n"
442     } 
443
444     use Config qw(myconfig config_sh config_vars config_re);
445
446     print myconfig();
447
448     print config_sh();
449
450     print config_re();
451
452     config_vars(qw(osname archname));
453
454
455 =head1 DESCRIPTION
456
457 The Config module contains all the information that was available to
458 the C<Configure> program at Perl build time (over 900 values).
459
460 Shell variables from the F<config.sh> file (written by Configure) are
461 stored in the readonly-variable C<%Config>, indexed by their names.
462
463 Values stored in config.sh as 'undef' are returned as undefined
464 values.  The perl C<exists> function can be used to check if a
465 named variable exists.
466
467 =over 4
468
469 =item myconfig()
470
471 Returns a textual summary of the major perl configuration values.
472 See also C<-V> in L<perlrun/Switches>.
473
474 =item config_sh()
475
476 Returns the entire perl configuration information in the form of the
477 original config.sh shell variable assignment script.
478
479 =item config_re($regex)
480
481 Like config_sh() but returns, as a list, only the config entries who's
482 names match the $regex.
483
484 =item config_vars(@names)
485
486 Prints to STDOUT the values of the named configuration variable. Each is
487 printed on a separate line in the form:
488
489   name='value';
490
491 Names which are unknown are output as C<name='UNKNOWN';>.
492 See also C<-V:name> in L<perlrun/Switches>.
493
494 =back
495
496 =head1 EXAMPLE
497
498 Here's a more sophisticated example of using %Config:
499
500     use Config;
501     use strict;
502
503     my %sig_num;
504     my @sig_name;
505     unless($Config{sig_name} && $Config{sig_num}) {
506         die "No sigs?";
507     } else {
508         my @names = split ' ', $Config{sig_name};
509         @sig_num{@names} = split ' ', $Config{sig_num};
510         foreach (@names) {
511             $sig_name[$sig_num{$_}] ||= $_;
512         }   
513     }
514
515     print "signal #17 = $sig_name[17]\n";
516     if ($sig_num{ALRM}) { 
517         print "SIGALRM is $sig_num{ALRM}\n";
518     }   
519
520 =head1 WARNING
521
522 Because this information is not stored within the perl executable
523 itself it is possible (but unlikely) that the information does not
524 relate to the actual perl binary which is being used to access it.
525
526 The Config module is installed into the architecture and version
527 specific library directory ($Config{installarchlib}) and it checks the
528 perl version number when loaded.
529
530 The values stored in config.sh may be either single-quoted or
531 double-quoted. Double-quoted strings are handy for those cases where you
532 need to include escape sequences in the strings. To avoid runtime variable
533 interpolation, any C<$> and C<@> characters are replaced by C<\$> and
534 C<\@>, respectively. This isn't foolproof, of course, so don't embed C<\$>
535 or C<\@> in double-quoted strings unless you're willing to deal with the
536 consequences. (The slashes will end up escaped and the C<$> or C<@> will
537 trigger variable interpolation)
538
539 =head1 GLOSSARY
540
541 Most C<Config> variables are determined by the C<Configure> script
542 on platforms supported by it (which is most UNIX platforms).  Some
543 platforms have custom-made C<Config> variables, and may thus not have
544 some of the variables described below, or may have extraneous variables
545 specific to that particular port.  See the port specific documentation
546 in such cases.
547
548 ENDOFTAIL
549
550 if ($Opts{glossary}) {
551   open(GLOS, "<$Glossary") or die "Can't open $Glossary: $!";
552 }
553 %seen = ();
554 $text = 0;
555 $/ = '';
556
557 sub process {
558   if (s/\A(\w*)\s+\(([\w.]+)\):\s*\n(\t?)/=item C<$1>\n\nFrom F<$2>:\n\n/m) {
559     my $c = substr $1, 0, 1;
560     unless ($seen{$c}++) {
561       print CONFIG_POD <<EOF if $text;
562 =back
563
564 EOF
565       print CONFIG_POD <<EOF;
566 =head2 $c
567
568 =over 4
569
570 EOF
571      $text = 1;
572     }
573   }
574   elsif (!$text || !/\A\t/) {
575     warn "Expected a Configure variable header",
576       ($text ? " or another paragraph of description" : () );
577   }
578   s/n't/n\00t/g;                # leave can't, won't etc untouched
579   s/^\t\s+(.*)/\n$1/gm;         # Indented lines ===> new paragraph
580   s/^(?<!\n\n)\t(.*)/$1/gm;     # Not indented lines ===> text
581   s{([\'\"])(?=[^\'\"\s]*[./][^\'\"\s]*\1)([^\'\"\s]+)\1}(F<$2>)g; # '.o'
582   s{([\'\"])([^\'\"\s]+)\1}(C<$2>)g; # "date" command
583   s{\'([A-Za-z_\- *=/]+)\'}(C<$1>)g; # 'ln -s'
584   s{
585      (?<! [\w./<\'\"] )         # Only standalone file names
586      (?! e \. g \. )            # Not e.g.
587      (?! \. \. \. )             # Not ...
588      (?! \d )                   # Not 5.004
589      (?! read/ )                # Not read/write
590      (?! etc\. )                # Not etc.
591      (?! I/O )                  # Not I/O
592      (
593         \$ ?                    # Allow leading $
594         [\w./]* [./] [\w./]*    # Require . or / inside
595      )
596      (?<! \. (?= [\s)] ) )      # Do not include trailing dot
597      (?! [\w/] )                # Include all of it
598    }
599    (F<$1>)xg;                   # /usr/local
600   s/((?<=\s)~\w*)/F<$1>/g;      # ~name
601   s/(?<![.<\'\"])\b([A-Z_]{2,})\b(?![\'\"])/C<$1>/g;    # UNISTD
602   s/(?<![.<\'\"])\b(?!the\b)(\w+)\s+macro\b/C<$1> macro/g; # FILE_cnt macro
603   s/n[\0]t/n't/g;               # undo can't, won't damage
604 }
605
606 if ($Opts{glossary}) {
607     <GLOS>;                             # Skip the "DO NOT EDIT"
608     <GLOS>;                             # Skip the preamble
609   while (<GLOS>) {
610     process;
611     print CONFIG_POD;
612   }
613 }
614
615 print CONFIG_POD <<'ENDOFTAIL';
616
617 =back
618
619 =head1 NOTE
620
621 This module contains a good example of how to use tie to implement a
622 cache and an example of how to make a tied variable readonly to those
623 outside of it.
624
625 =cut
626
627 ENDOFTAIL
628
629 close(CONFIG);
630 close(GLOS);
631 close(CONFIG_POD);
632
633 # Now create Cross.pm if needed
634 if ($Opts{cross}) {
635   open CROSS, ">lib/Cross.pm" or die "Can not open >lib/Cross.pm: $!";
636   my $cross = <<'EOS';
637 # typical invocation:
638 #   perl -MCross Makefile.PL
639 #   perl -MCross=wince -V:cc
640 package Cross;
641
642 sub import {
643   my ($package,$platform) = @_;
644   unless (defined $platform) {
645     # if $platform is not specified, then use last one when
646     # 'configpm; was invoked with --cross option
647     $platform = '***replace-marker***';
648   }
649   @INC = map {/\blib\b/?(do{local $_=$_;s/\blib\b/xlib\/$platform/;$_},$_):($_)} @INC;
650   $::Cross::platform = $platform;
651 }
652
653 1;
654 EOS
655   $cross =~ s/\*\*\*replace-marker\*\*\*/$Opts{cross}/g;
656   print CROSS $cross;
657   close CROSS;
658 }
659
660 # Now do some simple tests on the Config.pm file we have created
661 unshift(@INC,'lib');
662 require $Config_PM;
663 import Config;
664
665 die "$0: $Config_PM not valid"
666         unless $Config{'PERL_CONFIG_SH'} eq 'true';
667
668 die "$0: error processing $Config_PM"
669         if defined($Config{'an impossible name'})
670         or $Config{'PERL_CONFIG_SH'} ne 'true' # test cache
671         ;
672
673 die "$0: error processing $Config_PM"
674         if eval '$Config{"cc"} = 1'
675         or eval 'delete $Config{"cc"}'
676         ;
677
678
679 exit 0;