1#!perl -w 2use strict; 3use FindExt; 4 5# take a semicolon separated path list and turn it into a quoted 6# list of paths that Text::Parsewords will grok 7sub mungepath { 8 my $p = shift; 9 # remove leading/trailing semis/spaces 10 $p =~ s/^[ ;]+//; 11 $p =~ s/[ ;]+$//; 12 $p =~ s/'/"/g; 13 my @p = map { $_ = "\"$_\"" if /\s/ and !/^".*"$/; $_ } split /;/, $p; 14 return wantarray ? @p : join(' ', @p); 15} 16 17# check that the directories in the provided var exist 18sub check_path { 19 my $opt = shift; 20 my $p = shift; 21 my @paths = mungepath($p); 22 my $header_seen = 0; 23 foreach my $path (@paths) { 24 $path =~ s/^"(.*)"$/$1/; 25 next, if -d $path; 26 27 if (not $header_seen++) { 28 print STDERR "'$opt' contains the following non-existing paths:\n"; 29 } 30 print STDERR "\t$path\n"; 31 } 32 if ($header_seen) { 33 print STDERR <<EOF; 34Did you provide a correct value for the 'CCHOME' option? 35 36(This check can be skipped by using the SKIP_CCHOME_CHECK=1 option) 37EOF 38 exit 1; 39 } 40} 41 42# generate an array of option strings from command-line args 43# or an option file 44# -- added by BKS, 10-17-1999 to fix command-line overflow problems 45sub loadopts { 46 if ($ARGV[0] =~ /--cfgsh-option-file/) { 47 shift @ARGV; 48 my $optfile = shift @ARGV; 49 local (*OPTF); 50 open OPTF, '<', $optfile or die "Can't open $optfile: $!\n"; 51 my @opts; 52 chomp(my $line = <OPTF>); 53 my @vars = split(/\t+~\t+/, $line); 54 for (@vars) { 55 push(@opts, $_) unless (/^\s*$/); 56 } 57 close OPTF; 58 return \@opts; 59 } 60 else { 61 return \@ARGV; 62 } 63} 64 65sub replace_template { 66 my ($template, %opt) = @_; 67 68 open my $fh, "<", $template 69 or die "$0: Cannot open $template: $!\n"; 70 my $result = ''; 71 local $_; 72 while (<$fh>) { 73 s/~([\w_]+)~/exists $opt{$1} ? $opt{$1} : ''/eg; 74 if (/^([\w_]+)=(.*)$/) { 75 my($k,$v) = ($1,$2); 76 # this depends on cf_time being empty in the template (or we'll 77 # get a loop) 78 if (exists $opt{$k}) { 79 $_ = "$k='$opt{$k}'\n"; 80 } 81 } 82 $result .= $_; 83 } 84 close $fh; 85 86 $result; 87} 88 89my $out = '-'; 90if (@ARGV >= 2 && $ARGV[0] eq '-o') { 91 shift; 92 $out = shift; 93} 94 95my $prebuilt; # are we making the prebuilt config used to bootstrap? 96if (@ARGV && $ARGV[0] eq '--prebuilt') { 97 ++$prebuilt; 98 shift; 99} 100 101my %opt; 102 103my $optref = loadopts(); 104while (@{$optref} && $optref->[0] =~ /^([\w_]+)=(.*)$/) { 105 $opt{$1}=$2; 106 shift(@{$optref}); 107} 108 109FindExt::scan_ext("../cpan"); 110FindExt::scan_ext("../dist"); 111FindExt::scan_ext("../ext"); 112FindExt::set_static_extensions(split ' ', $opt{static_ext}); 113 114$opt{nonxs_ext} = join(' ',FindExt::nonxs_ext()) || ' '; 115$opt{static_ext} = join(' ',FindExt::static_ext()) || ' '; 116$opt{dynamic_ext} = join(' ',FindExt::dynamic_ext()) || ' '; 117$opt{extensions} = join(' ',FindExt::extensions()) || ' '; 118$opt{known_extensions} = join(' ',FindExt::known_extensions()) || ' '; 119 120my $pl_h = '../patchlevel.h'; 121 122if (-e $pl_h) { 123 open PL, "<", $pl_h or die "Can't open $pl_h: $!"; 124 while (<PL>) { 125 if (/^#\s*define\s+(PERL_\w+)\s+([\d.]+)/) { 126 $opt{$1} = $2; 127 } 128 } 129 close PL; 130} 131else { 132 die "Can't find $pl_h: $!"; 133} 134 135my $patch_file = '../.patch'; 136 137if (-e $patch_file) { 138 open my $fh, "<", $patch_file or die "Can't open $patch_file: $!"; 139 chomp($opt{PERL_PATCHLEVEL} = <$fh>); 140 close $fh; 141} 142 143$opt{version} = "$opt{PERL_REVISION}.$opt{PERL_VERSION}.$opt{PERL_SUBVERSION}"; 144$opt{version_patchlevel_string} = "version $opt{PERL_VERSION} subversion $opt{PERL_SUBVERSION}"; 145$opt{version_patchlevel_string} .= " patch $opt{PERL_PATCHLEVEL}" if exists $opt{PERL_PATCHLEVEL}; 146 147my $ver = `ver 2>nul`; 148$opt{osvers} = $ver =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '4.0'; 149 150if (exists $opt{cc}) { 151 # cl version detection borrowed from Test::Smoke's configsmoke.pl 152 if ($opt{cc} =~ /\b(?:cl|icl)/) { #MSVC can come as clarm.exe, icl=Intel C 153 my $output = `$opt{cc} 2>&1`; 154 $opt{ccversion} = $output =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '?'; 155 } 156 elsif ($opt{cc} =~ /\bgcc\b/) { 157 chomp($opt{gccversion} = `$opt{cc} -dumpversion`); 158 chomp($opt{libc} = `$opt{cc} -o rt.exe configure/rt.c 1>nul 2>&1 && rt`); 159 if(-e 'rt.exe') { unlink 'rt.exe' } # rt.exe no longer needed 160 else { die "Failed to identify default runtime" } 161 } 162} 163 164$opt{cf_by} = $ENV{USERNAME} unless $opt{cf_by}; 165if (!$opt{cf_email}) { 166 my $computername = eval{(gethostbyname('localhost'))[0]}; 167# gethostbyname might not be implemented in miniperl 168 $computername = $ENV{COMPUTERNAME} if $@; 169 $opt{cf_email} = $opt{cf_by} . '@' . $computername; 170} 171$opt{usemymalloc} = 'y' if $opt{d_mymalloc} eq 'define'; 172 173unless ($opt{SKIP_CCHOME_CHECK}) { 174 check_path('CCLIBDIR', $opt{libpth}); 175 check_path('CCINCDIR', $opt{incpath}); 176} 177 178$opt{libpth} = mungepath($opt{libpth}) if exists $opt{libpth}; 179$opt{incpath} = mungepath($opt{incpath}) if exists $opt{incpath}; 180 181my $int64; 182if ($opt{cc} =~ /\b(?:cl|icl)/) { 183 $int64 = '__int64'; 184} 185elsif ($opt{cc} =~ /\bgcc\b/) { 186 $int64 = 'long long'; 187} 188 189# set 64-bit options 190if ($opt{WIN64} eq 'define') { 191 $opt{d_atoll} = 'define'; 192 $opt{d_strtoll} = 'define'; 193 $opt{d_strtoull} = 'define'; 194 $opt{ptrsize} = 8; 195 $opt{sizesize} = 8; 196 $opt{ssizetype} = $int64; 197 $opt{st_ino_size} = 8; 198} 199else { 200 $opt{d_atoll} = 'undef'; 201 $opt{d_strtoll} = 'undef'; 202 $opt{d_strtoull} = 'undef'; 203 $opt{ptrsize} = 4; 204 $opt{sizesize} = 4; 205 $opt{ssizetype} = 'int'; 206 $opt{st_ino_size} = 4; 207} 208 209# set 64-bit-int options 210if ($opt{use64bitint} eq 'define') { 211 if ($opt{uselongdouble} eq 'define' || $opt{usequadmath} eq 'define') { 212 $opt{d_nv_preserves_uv} = 'define'; 213 $opt{nv_preserves_uv_bits} = 64; 214 } 215 else { 216 $opt{d_nv_preserves_uv} = 'undef'; 217 $opt{nv_preserves_uv_bits} = 53; 218 } 219 $opt{ivdformat} = qq{"I64d"}; 220 $opt{ivsize} = 8; 221 $opt{ivtype} = $int64; 222 $opt{sPRIXU64} = qq{"I64X"}; 223 $opt{sPRId64} = qq{"I64d"}; 224 $opt{sPRIi64} = qq{"I64i"}; 225 $opt{sPRIo64} = qq{"I64o"}; 226 $opt{sPRIu64} = qq{"I64u"}; 227 $opt{sPRIx64} = qq{"I64x"}; 228 $opt{uvXUformat} = qq{"I64X"}; 229 $opt{uvoformat} = qq{"I64o"}; 230 $opt{uvsize} = 8; 231 $opt{uvtype} = qq{unsigned $int64}; 232 $opt{uvuformat} = qq{"I64u"}; 233 $opt{uvxformat} = qq{"I64x"}; 234} 235else { 236 $opt{d_nv_preserves_uv} = 'define'; 237 $opt{ivdformat} = '"ld"'; 238 $opt{ivsize} = 4; 239 $opt{ivtype} = 'long'; 240 $opt{nv_preserves_uv_bits} = 32; 241 $opt{sPRIXU64} = '"lX"'; 242 $opt{sPRId64} = '"ld"'; 243 $opt{sPRIi64} = '"li"'; 244 $opt{sPRIo64} = '"lo"'; 245 $opt{sPRIu64} = '"lu"'; 246 $opt{sPRIx64} = '"lx"'; 247 $opt{uvXUformat} = '"lX"'; 248 $opt{uvoformat} = '"lo"'; 249 $opt{uvsize} = 4; 250 $opt{uvtype} = 'unsigned long'; 251 $opt{uvuformat} = '"lu"'; 252 $opt{uvxformat} = '"lx"'; 253} 254 255unless ($opt{cc} =~ /\bcl/) { 256 if ($opt{WIN64} eq 'define') { 257 $opt{longdblsize} = 16; 258 $opt{longdblinfbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'; 259 $opt{longdblnanbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00'; 260 } 261 else { 262 $opt{longdblsize} = 12; 263 $opt{longdblinfbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00'; 264 $opt{longdblnanbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x00, 0x00'; 265 } 266} 267 268# set long double options 269if ($opt{uselongdouble} eq 'define') { 270 $opt{d_Gconvert} = 'sprintf((b),"%.*""Lg",(n),(x))'; 271 $opt{d_PRIEUldbl} = 'define'; 272 $opt{d_PRIFUldbl} = 'define'; 273 $opt{d_PRIGUldbl} = 'define'; 274 $opt{d_modflproto} = 'define'; 275 $opt{d_strtold} = 'define'; 276 $opt{d_PRIeldbl} = 'define'; 277 $opt{d_PRIfldbl} = 'define'; 278 $opt{d_PRIgldbl} = 'define'; 279 $opt{d_SCNfldbl} = 'define'; 280 $opt{nvsize} = $opt{longdblsize}; 281 $opt{nvtype} = 'long double'; 282 $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*256.0*2.0*2.0*2.0*2.0*2.0*2.0*2.0*2.0'; 283 $opt{nvEUformat} = '"LE"'; 284 $opt{nvFUformat} = '"LF"'; 285 $opt{nvGUformat} = '"LG"'; 286 $opt{nveformat} = '"Le"'; 287 $opt{nvfformat} = '"Lf"'; 288 $opt{nvgformat} = '"Lg"'; 289 $opt{nvmantbits} = 64; 290 $opt{longdblkind} = 3; 291 $opt{longdblmantbits} = 64; 292} 293# set __float128 options 294elsif ($opt{usequadmath} eq 'define') { 295 $opt{d_Gconvert} = 'sprintf((b),"%.*""Lg",(n),(x))'; 296 $opt{d_PRIEUldbl} = 'define'; 297 $opt{d_PRIFUldbl} = 'define'; 298 $opt{d_PRIGUldbl} = 'define'; 299 $opt{d_modflproto} = 'define'; 300 $opt{d_strtold} = 'define'; 301 $opt{d_PRIeldbl} = 'define'; 302 $opt{d_PRIfldbl} = 'define'; 303 $opt{d_PRIgldbl} = 'define'; 304 $opt{d_SCNfldbl} = 'define'; 305 $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*2.0'; 306 $opt{nvsize} = 16; 307 $opt{nvtype} = '__float128'; 308 $opt{nvEUformat} = '"QE"'; 309 $opt{nvFUformat} = '"QF"'; 310 $opt{nvGUformat} = '"QG"'; 311 $opt{nveformat} = '"Qe"'; 312 $opt{nvfformat} = '"Qf"'; 313 $opt{nvgformat} = '"Qg"'; 314 $opt{nvmantbits} = 112; 315 $opt{longdblkind} = 3; 316 $opt{longdblmantbits} = 64; 317 $opt{i_quadmath} = 'define'; 318} 319else { 320 $opt{d_Gconvert} = 'sprintf((b),"%.*g",(n),(x))'; 321 $opt{d_PRIEUldbl} = 'undef'; 322 $opt{d_PRIFUldbl} = 'undef'; 323 $opt{d_PRIGUldbl} = 'undef'; 324 325 if($opt{cc} =~ /\b(?:cl|icl)/) { 326 $opt{d_modflproto} = 'undef'; 327 } 328 else { 329 $opt{d_modflproto} = 'define'; 330 } 331 332 $opt{d_strtold} = 'undef'; 333 $opt{d_PRIeldbl} = 'undef'; 334 $opt{d_PRIfldbl} = 'undef'; 335 $opt{d_PRIgldbl} = 'undef'; 336 $opt{d_SCNfldbl} = 'undef'; 337 $opt{nvsize} = 8; 338 $opt{nvtype} = 'double'; 339 $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*2.0*2.0*2.0*2.0*2.0'; 340 $opt{nvEUformat} = '"E"'; 341 $opt{nvFUformat} = '"F"'; 342 $opt{nvGUformat} = '"G"'; 343 $opt{nveformat} = '"e"'; 344 $opt{nvfformat} = '"f"'; 345 $opt{nvgformat} = '"g"'; 346} 347 348# change some configuration variables based on compiler version 349if ($opt{cc} =~ /\bcl/ and $opt{ccversion} =~ /^(\d+)/) { 350 my $ccversion = $1; 351 if ($ccversion >= 14) { # VC8+ 352 $opt{sGMTIME_max} = 32535291599; 353 $opt{sLOCALTIME_max} = 32535244799; 354 } 355 if ($ccversion >= 16 && !$prebuilt) { # VC10+ 356 $opt{i_stdint} = 'define'; 357 } 358 if ($ccversion >= 19) { # VC14+ 359 $opt{i_stdbool} = 'define' unless $prebuilt; 360 } 361} 362# find out which MSVC this ICC is using 363elsif ($opt{cc} =~ /\bicl/) { 364 my $output = `cl 2>&1`; 365 my $num_ver = $output =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '?'; 366 if ($num_ver =~ /^(\d+)/ && $1 >= 14) { # VC8+ 367 $opt{sGMTIME_max} = 32535291599; 368 $opt{sLOCALTIME_max} = 32535244799; 369 } 370 if ($num_ver =~ /^(\d+)/ && $1 >= 16) { # VC10+ 371 $opt{i_stdint} = 'define'; 372 } 373 if ($num_ver =~ /^(\d+)/ && $1 >= 19) { # VC14+ 374 $opt{i_stdbool} = 'define'; 375 } 376 $opt{ar} ='xilib'; 377} 378 379# win32.h always defines these, and those definitions 380# depend on the current CRT 381$opt{stdio_base} = 'PERLIO_FILE_base(fp)'; 382$opt{stdio_bufsiz} = '(PERLIO_FILE_cnt(fp) + PERLIO_FILE_ptr(fp) - PERLIO_FILE_base(fp))'; 383$opt{stdio_cnt} = 'PERLIO_FILE_cnt(fp)'; 384$opt{stdio_ptr} = 'PERLIO_FILE_ptr(fp)'; 385 386if ($opt{useithreads} eq 'define' && $opt{ccflags} =~ /-DPERL_IMPLICIT_SYS\b/) { 387 $opt{d_pseudofork} = 'define'; 388} 389 390if ($opt{usecplusplus} eq 'define') { 391 $opt{d_cplusplus} = 'define'; 392 $opt{extern_C} = 'extern "C"'; 393} 394 395#if the fields above are defined, they override the defaults in the premade 396#config file 397my $template = shift 398 or die "$0: No template supplied\n"; 399if ($out ne '-') { 400 # preserve cf_time to avoid generating a new config.sh with no changes 401 my $cf_time; 402 if (open my $fh, "<", $out) { 403 my $old = ''; 404 # scan for cf_time while reading in the whole file 405 while (<$fh>) { 406 $old .= $_; 407 if (/^cf_time='(.*)'/) { 408 $cf_time = $1; 409 } 410 } 411 close $fh; 412 413 my $replaced = replace_template($template, %opt, cf_time => $cf_time); 414 if ($replaced eq $old) { 415 # no configuration change, skip updating 416 print "$0: No changes for $out\n"; 417 exit; 418 } 419 } 420 open my $fh, ">", $out 421 or die "$0: Cannot create $out: $!\n"; 422 print $fh replace_template($template, %opt, cf_time => scalar localtime); 423 close $fh 424 or die "$0: Failed to close $template: $!\n"; 425} 426else { 427 print replace_template($template, %opt, cf_time => scalar localtime); 428} 429