util/perl/OpenSSL/config.pm: Rework determining compiler information
[openssl.git] / util / perl / OpenSSL / config.pm
1 #! /usr/bin/env perl
2 # Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 # Determine the operating system and run ./Configure.  Far descendant from
10 # Apache's minarch and GuessOS.
11
12 package OpenSSL::config;
13
14 use strict;
15 use warnings;
16 use Getopt::Std;
17 use File::Basename;
18 use IPC::Cmd;
19 use POSIX;
20 use Carp;
21
22 # These control our behavior.
23 my $DRYRUN;
24 my $VERBOSE;
25 my $WAIT = 1;
26 my $WHERE = dirname($0);
27
28 # Machine type, etc., used to determine the platform
29 my $MACHINE;
30 my $RELEASE;
31 my $SYSTEM;
32 my $VERSION;
33 my $CCVENDOR;
34 my $CCVER;
35 my $GCC_BITS;
36 my $GCC_ARCH;
37
38 # Some environment variables; they will affect Configure
39 my $PERL = $ENV{PERL} // $^X // 'perl';
40 my $CONFIG_OPTIONS = $ENV{CONFIG_OPTIONS} // '';
41 my $CC = $ENV{CC} // '';
42 my $CROSS_COMPILE = $ENV{CROSS_COMPILE} // "";
43 my $KERNEL_BITS = $ENV{KERNEL_BITS} // '';
44
45 # For determine_compiler_settings, the list of known compilers
46 my @c_compilers = qw(clang gcc cc);
47 # Methods to determine compiler version.  The expected output is one of
48 # MAJOR or MAJOR.MINOR or MAJOR.MINOR.PATCH...  or false if the compiler
49 # isn't of the given brand.
50 # This is a list to ensure that gnu comes last, as we've made it a fallback
51 my @cc_version =
52     (
53      clang => sub {
54          my $v = `$CROSS_COMPILE$CC -v 2>&1`;
55          $v =~ m/(?:(?:^clang|LLVM) version|.*based on LLVM)\s+([0-9]+\.[0-9]+)/;
56          return $1;
57      },
58      gnu => sub {
59          my $v = `$CROSS_COMPILE$CC -dumpversion 2>/dev/null`;
60          # Strip off whatever prefix egcs prepends the number with.
61          # Hopefully, this will work for any future prefixes as well.
62          $v =~ s/^[a-zA-Z]*\-//;
63          return $v;
64      },
65     );
66
67 # This is what we will set as the target for calling Configure.
68 my $options = '';
69
70 # Environment that will be passed to Configure
71 my $__CNF_CPPDEFINES = '';
72 my $__CNF_CPPINCLUDES = '';
73 my $__CNF_CPPFLAGS = '';
74 my $__CNF_CFLAGS = '';
75 my $__CNF_CXXFLAGS = '';
76 my $__CNF_LDFLAGS = '';
77 my $__CNF_LDLIBS = '';
78
79 # Pattern matches against "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}"
80 my $simple_guess_patterns = [
81     [ 'A\/UX:',               'm68k-apple-aux3' ],
82     [ 'AIX:[3-9]:4:',         '${MACHINE}-ibm-aix' ],
83     [ 'AIX:.*:[5-9]:',        '${MACHINE}-ibm-aix' ],
84     [ 'AIX:',                 '${MACHINE}-ibm-aix3' ],
85     [ 'HI-UX:',               '${MACHINE}-hi-hiux' ],
86     [ 'IRIX:6.',              'mips3-sgi-irix' ],
87     [ 'IRIX64:',              'mips4-sgi-irix64' ],
88     [ 'Linux:[2-9]',          '${MACHINE}-whatever-linux2' ],
89     [ 'Linux:1',              '${MACHINE}-whatever-linux1' ],
90     [ 'GNU',                  'hurd-x86' ],
91     [ 'LynxOS:',              '${MACHINE}-lynx-lynxos' ],
92     # BSD/OS always says 386
93     [ 'BSD\/OS:4.*',          'i486-whatever-bsdi4' ],
94     [ 'BSD\/386:.*|BSD\/OS:', '${MACHINE}-whatever-bsdi' ],
95     [ 'DragonFly:',           '${MACHINE}-whatever-dragonfly' ],
96     [ 'FreeBSD:',             '${MACHINE}-whatever-freebsd' ],
97     [ 'Haiku:',               '${MACHINE}-whatever-haiku' ],
98     [ 'NetBSD:',              '${MACHINE}-whatever-netbsd' ],
99     [ 'OpenBSD:',             '${MACHINE}-whatever-openbsd' ],
100     [ 'OpenUNIX:',            '${MACHINE}-unknown-OpenUNIX${VERSION}' ],
101     [ 'Paragon.*:',           'i860-intel-osf1' ],
102     [ 'Rhapsody:',            'ppc-apple-rhapsody' ],
103     [ 'SunOS:5.',             '${MACHINE}-whatever-solaris2' ],
104     [ 'SunOS:',               '${MACHINE}-sun-sunos4' ],
105     [ 'UNIX_System_V:4.*:',   '${MACHINE}-whatever-sysv4' ],
106     [ 'VOS:.*:.*:i786',       'i386-stratus-vos' ],
107     [ 'VOS:.*:.*:',           'hppa1.1-stratus-vos' ],
108     [ '.*:4.*:R4.*:m88k',     '${MACHINE}-whatever-sysv4' ],
109     [ 'DYNIX\/ptx:4.*:',      '${MACHINE}-whatever-sysv4' ],
110     [ ':4.0:3.0:3[34]',       'i486-ncr-sysv4' ],
111     [ 'ULTRIX:',              '${MACHINE}-unknown-ultrix' ],
112     [ 'POSIX-BC',             'BS2000-siemens-sysv4' ],
113     [ 'machten:',             '${MACHINE}-tenon-${SYSTEM}' ],
114     [ 'library:',             '${MACHINE}-ncr-sysv4' ],
115     [ 'ConvexOS:.*:11.0:',    '${MACHINE}-v11-${SYSTEM}' ],
116     [ 'MINGW64.*:.*x86_64',   '${MACHINE}-whatever-mingw64' ],
117     [ 'MINGW',                '${MACHINE}-whatever-mingw' ],
118     [ 'CYGWIN',               '${MACHINE}-pc-cygwin' ],
119     [ 'vxworks',              '${MACHINE}-whatever-vxworks' ],
120     [ 'Darwin:.*Power',       'ppc-apple-darwin' ],
121     [ 'Darwin:.*x86_64',      'x86_64-apple-darwin' ],
122     [ 'Darwin:',              'i686-apple-darwin' ],
123
124     # Windows values found by looking at Perl 5's win32/win32.c
125     [ 'Windows NT:.*:amd64',  'VC-WIN64A' ],
126     [ 'Windows NT:.*:ia64',   'VC-WIN64I' ],
127     [ 'Windows NT:.*:x86',    'VC-WIN32' ],
128
129     # VMS values found by observation on existing machinery.  Unfortunately,
130     # the machine part is a bit...  overdone.  It seems, though, that 'Alpha'
131     # exists in that part, making it distinguishable from Itanium.  It will
132     # be interesting to see what we'll get in the upcoming x86_64 port...
133     [ 'OpenVMS:.*:.*:.*:.*Alpha*', 'vms-alpha' ],
134     [ 'OpenVMS:',             'vms-ia64' ],
135
136 ];
137
138 # More complex cases that require run-time code.
139 my $complex_sys_list = [
140     [ 'HP-UX:', sub {
141         my $HPUXVER = $RELEASE;
142         $HPUXVER = s/[^.]*.[0B]*//;
143         # HPUX 10 and 11 targets are unified
144         return "${MACHINE}-hp-hpux1x" if $HPUXVER =~ m@1[0-9]@;
145         return "${MACHINE}-hp-hpux";
146     } ],
147
148     [ 'BSD/386:.*:.*:.*486.*|BSD/OS:.*:.*:.*:.*486', sub {
149         my $BSDVAR = `/sbin/sysctl -n hw.model`;
150         return "i586-whatever-bsdi" if $BSDVAR =~ m@Pentium@;
151         return "i386-whatever-bsdi";
152     } ],
153
154     [ 'FreeBSD:.*:.*:.*386', sub {
155         my $VERS = $RELEASE;
156         $VERS =~ s/[-(].*//;
157         my $MACH = `sysctl -n hw.model`;
158         $MACH = "i386" if $MACH =~ m@386@;
159         $MACH = "i486" if $MACH =~ m@486@;
160         $MACH = "i686" if $MACH =~ m@Pentium II@;
161         $MACH = "i586" if $MACH =~ m@Pentium@;
162         $MACH = "$MACHINE" if $MACH !~ /i.86/;
163         my $ARCH = 'whatever';
164         $ARCH = "pc" if $MACH =~ m@i[0-9]86@;
165         return "${MACH}-${ARCH}-freebsd${VERS}";
166     } ],
167
168     [ 'NetBSD:.*:.*:.*386', sub {
169         my $hw = `/usr/sbin/sysctl -n hw.model || /sbin/sysctl -n hw.model`;
170         $hw =~  s@.*(.)86-class.*@i${1}86@;
171         return "${hw}-whatever-netbsd";
172     } ],
173
174     [ 'OSF1:.*:.*:.*alpha', sub {
175         my $OSFMAJOR = $RELEASE;
176         $OSFMAJOR =~ 's/^V([0-9]*)\..*$/\1/';
177         return "${MACHINE}-dec-tru64" if $OSFMAJOR =~ m@[45]@;
178         return "${MACHINE}-dec-osf";
179     } ],
180 ];
181
182
183 # Run a command, return true if exit zero else false.
184 # Multiple args are glued together into a pipeline.
185 # Name comes from OpenSSL tests, often written as "ok(run(...."
186 sub okrun {
187     my $command = join(' | ', @_);
188     my $status = system($command) >> 8;
189     return $status == 0;
190 }
191
192 # Give user a chance to abort/interrupt if interactive if interactive.
193 sub maybe_abort {
194     if ( $WAIT && -t 1 ) {
195         eval {
196             local $SIG{ALRM} = sub { die "Timeout"; };
197             local $| = 1;
198             alarm(5);
199             print "You have about five seconds to abort: ";
200             my $ignored = <STDIN>;
201             alarm(0);
202         };
203         print "\n" if $@ =~ /Timeout/;
204     }
205 }
206
207 # Expand variable references in a string.
208 sub expand {
209     my $var = shift;
210     $var =~ s/\$\{MACHINE\}/${MACHINE}/;
211     return $var;
212 }
213
214 # Look for ISC/SCO with its unique uname program
215 sub is_sco_uname {
216     open UNAME, "uname -X 2>/dev/null|" or return '';
217     my $line = "";
218     while ( <UNAME> ) {
219         chop;
220         $line = $_ if m@^Release@;
221     }
222     close UNAME;
223     return "" if $line eq '';
224     my @fields = split($line);
225     return $fields[2];
226 }
227
228 sub get_sco_type {
229     my $REL = shift;
230
231     if ( -f "/etc/kconfig" ) {
232         return "${MACHINE}-whatever-isc4" if $REL eq '4.0' || $REL eq '4.1';
233     } else {
234         return "whatever-whatever-sco3" if $REL eq '3.2v4.2';
235         return "whatever-whatever-sco5" if $REL =~ m@3\.2v5\.0.*@;
236         if ( $REL eq "4.2MP" ) {
237             return "whatever-whatever-unixware20" if $VERSION =~ m@2\.0.*@;
238             return "whatever-whatever-unixware21" if $VERSION =~ m@2\.1.*@;
239             return "whatever-whatever-unixware2" if $VERSION =~ m@2.*@;
240         }
241         return "whatever-whatever-unixware1" if $REL eq "4.2";
242         if ( $REL =~ m@5.*@ ) {
243             # We hardcode i586 in place of ${MACHINE} for the following
244             # reason: even though Pentium is minimum requirement for
245             # platforms in question, ${MACHINE} gets always assigned to
246             # i386. This means i386 gets passed to Configure, which will
247             # cause bad assembler code to be generated.
248             return "i586-sco-unixware7" if $VERSION =~ m@[678].*@;
249         }
250     }
251 }
252
253 # Return the cputype-vendor-osversion
254 sub guess_system {
255     ($SYSTEM, undef, $RELEASE, $VERSION, $MACHINE) = POSIX::uname();
256     my $sys = "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}";
257
258     # Special-cases for ISC, SCO, Unixware
259     my $REL = is_sco_uname();
260     if ( $REL ne "" ) {
261         my $result = get_sco_type($REL);
262         return expand($result) if $result ne '';
263     }
264
265     # Now pattern-match
266
267     # Simple cases
268     foreach my $tuple ( @$simple_guess_patterns ) {
269         my $pat = @$tuple[0];
270         # Trailing $ omitted on purpose.
271         next if $sys !~ /^$pat/;
272         my $result = @$tuple[1];
273         return expand($result);
274     }
275
276     # Complex cases.
277     foreach my $tuple ( @$complex_sys_list ) {
278         my $pat = @$tuple[0];
279         # Trailing $ omitted on purpose.
280         next if $sys !~ /^$pat/;
281         my $ref = @$tuple[1];
282         my $result = &$ref;
283         return expand($result);
284     }
285
286     # Oh well.
287     return "${MACHINE}-whatever-${SYSTEM}";
288 }
289
290 # We would use List::Util::pair() for this...  unfortunately, that function
291 # only appeared in perl v5.19.3, and we claim to support perl v5.10 and on.
292 # Therefore, we implement a quick cheap variant of our own.
293 sub _pairs (@) {
294     croak "Odd number of arguments" if @_ & 1;
295
296     my @pairlist = ();
297
298     while (@_) {
299         my $x = [ shift, shift ];
300         push @pairlist, $x;
301     }
302     return @pairlist;
303 }
304
305 # Figure out CC, GCCVAR, etc.
306 sub determine_compiler_settings {
307     # Make a copy and don't touch it.  That helps determine if we're
308     # finding the compiler here
309     my $cc = $CC;
310
311     # Set certain default
312     $CCVER = 0;                 # Unknown
313     $CCVENDOR = '';             # Dunno, don't care (unless found later)
314
315     # Find a compiler if we don't already have one
316     if ( ! $cc ) {
317         foreach (@c_compilers) {
318             next unless IPC::Cmd::can_run("$CROSS_COMPILE$_");
319             $CC = $_;
320             last;
321         }
322     }
323
324     # Find the compiler vendor and version number for certain compilers
325     foreach my $pair (_pairs @cc_version) {
326         # Try to get the version number.
327         # Failure gets us undef or an empty string
328         my ( $k, $v ) = @$pair;
329         $v = $v->();
330
331         # If we got a version number, process it
332         if ($v) {
333             $CCVENDOR = $k;
334
335             # The returned version is expected to be one of
336             #
337             # MAJOR
338             # MAJOR.MINOR
339             # MAJOR.MINOR.{whatever}
340             #
341             # We don't care what comes after MAJOR.MINOR.  All we need is to
342             # have them calculated into a single number, using this formula:
343             #
344             # MAJOR * 100 + MINOR
345             # Here are a few examples of what we should get:
346             #
347             # 2.95.1    => 295
348             # 3.1       => 301
349             # 9         => 900
350             my @numbers = split /\./, $v;
351             my @factors = (100, 1);
352             while (@numbers && @factors) {
353                 $CCVER += shift(@numbers) * shift(@factors)
354             }
355             last;
356         }
357     }
358
359     # If no C compiler has been determined at this point, we die.  Hard.
360     die <<_____
361 ERROR!
362 No C compiler found, please specify one with the environment variable CC,
363 or configure with an explicit configuration target.
364 _____
365         unless $CC;
366
367     # Vendor specific overrides, only if we determined the compiler here
368     if ( ! $cc ) {
369         if ( ${SYSTEM} eq 'AIX' ) {
370             # favor vendor cc over gcc
371             if (IPC::Cmd::can_run('cc')) {
372                 $CC = 'cc';
373                 $CCVENDOR = ''; # Determine later
374                 $CCVER = 0;
375             }
376         }
377
378         if ( $SYSTEM eq "SunOS" ) {
379             # check for WorkShop C, expected output is "cc: blah-blah C x.x"
380             my $v = `(cc -V 2>&1) 2>/dev/null | egrep -e '^cc: .* C [0-9]\.[0-9]'`;
381             chomp $v;
382             $v =~ s/.* C \([0-9]\)\.\([0-9]\).*/$1.$2/;
383             my @numbers = split /\./, $v;
384             my @factors = (100, 1);
385             $v = 0;
386             while (@numbers && @factors) {
387                 $v += shift(@numbers) * shift(@factors)
388             }
389
390             if ( $v > 40000 &&  $MACHINE ne 'i86pc' ) {
391                 $CC = 'cc';
392                 $CCVENDOR = ''; # Determine later
393                 $CCVER = $v;
394
395                 if ( $CCVER == 50000 ) {
396                     print <<'EOF';
397 WARNING! Found WorkShop C 5.0.
398          Make sure you have patch #107357-01 or later applied.
399 EOF
400                     maybe_abort();
401                 }
402             }
403         }
404     }
405
406     # On some systems, we assume a cc vendor if it's not already determined
407
408     if ( ! $CCVENDOR ) {
409         $CCVENDOR = 'aix' if $SYSTEM eq 'AIX';
410         $CCVENDOR = 'sun' if $SYSTEM eq 'SunOS';
411     }
412
413     # Some systems need to know extra details
414
415     if ( $SYSTEM eq "HP-UX" && $CCVENDOR eq 'gnu' ) {
416         # By default gcc is a ILP32 compiler (with long long == 64).
417         $GCC_BITS = "32";
418         if ( $CCVER >= 300 ) {
419             # PA64 support only came in with gcc 3.0.x.
420             # We check if the preprocessor symbol __LP64__ is defined.
421             if ( okrun('echo __LP64__',
422                        "$CC -v -E -x c - 2>/dev/null",
423                        'grep "^__LP64__" 2>&1 >/dev/null') ) {
424                 # __LP64__ has slipped through, it therefore is not defined
425             } else {
426                 $GCC_BITS = '64';
427             }
428         }
429     }
430
431     if ( $SYSTEM eq "SunOS" && $CCVENDOR eq 'gnu' ) {
432         if ( $CCVER >= 300 ) {
433             # 64-bit ABI isn't officially supported in gcc 3.0, but seems
434             # to be working; at the very least 'make test' passes.
435             if ( okrun("$CC -v -E -x c /dev/null 2>&1",
436                        'grep __arch64__ >/dev/null') ) {
437                 $GCC_ARCH = "-m64"
438             } else {
439                 $GCC_ARCH = "-m32"
440             }
441         }
442     }
443
444     if ($VERBOSE) {
445         my $vendor = $CCVENDOR ? $CCVENDOR : "(undetermined)";
446         my $version = $CCVER ? $CCVER : "(undetermined)";
447         print "C compiler: $CC\n";
448         print "C compiler vendor: $vendor\n";
449         print "C compiler version: $version\n";
450     }
451 }
452
453 # Map GUESSOS into OpenSSL terminology. Also sets some of variables
454 # like $options, $__CNX_xxx.  And uses some, like the KERNEL flags
455 # and MACHINE.
456 # It would be nice to fix this so that this weren't necessary. :( XXX
457 sub map_guess {
458     my $GUESSOS = shift;
459     my $OUT;
460     return 'uClinux-dist64' if $GUESSOS =~ 'uClinux.*64.*';
461     return 'uClinux-dist' if $GUESSOS =~ 'uClinux.*';
462     return "irix-mips3-$CC" if $GUESSOS =~ 'mips3-sgi-irix';
463     if ( $GUESSOS =~ 'mips4-sgi-irix64' ) {
464         print <<EOF;
465 WARNING! To build 64-bit package, do this:
466          $WHERE/Configure irix64-mips4-$CC
467 EOF
468         maybe_abort();
469         return "irix-mips3-$CC";
470     }
471     return "rhapsody-ppc-cc" if $GUESSOS =~ 'ppc-apple-rhapsody';
472     if ( $GUESSOS =~ 'ppc-apple-darwin' ) {
473         my $ISA64 = `sysctl -n hw.optional.64bitops 2>/dev/null`;
474         if ( $ISA64 == 1 && $KERNEL_BITS eq '' ) {
475             print <<EOF;
476 WARNING! To build 64-bit package, do this:
477          $WHERE/Configure darwin64-ppc-cc
478 EOF
479             maybe_abort();
480         }
481         return "darwin64-ppc-cc" if $ISA64 == 1 && $KERNEL_BITS eq '64';
482         return "darwin-ppc-cc";
483     }
484     if ( $GUESSOS =~ 'i.86-apple-darwin' ) {
485         my $ISA64 = `sysctl -n hw.optional.x86_64 2>/dev/null`;
486         if ( $ISA64 == 1 && $KERNEL_BITS eq '' ) {
487             print <<EOF;
488 WARNING! To build 64-bit package, do this:
489          KERNEL_BITS=64 $WHERE/config $options
490 EOF
491             maybe_abort();
492         }
493         return "darwin64-x86_64-cc" if $ISA64 == 1 && $KERNEL_BITS eq '64';
494         return "darwin-i386-cc";
495     }
496     if ( $GUESSOS =~ 'x86_64-apple-darwin' ) {
497         return "darwin-i386-cc" if $KERNEL_BITS eq '32';
498
499         print <<EOF;
500 WARNING! To build 32-bit package, do this:
501          KERNEL_BITS=32 $WHERE/config $options
502 EOF
503         maybe_abort();
504         return "darwin64-x86_64-cc"
505     }
506     if ( $GUESSOS =~ 'armv6+7-.*-iphoneos' ) {
507         $__CNF_CFLAGS .= " -arch armv6 -arch armv7";
508         $__CNF_CXXFLAGS .= " -arch armv6 -arch armv7";
509         return "iphoneos-cross";
510     }
511     if ( $GUESSOS =~ '.*-.*-iphoneos' ) {
512         $__CNF_CFLAGS .= " -arch ${MACHINE}";
513         $__CNF_CXXFLAGS .= " -arch ${MACHINE}";
514         return "iphoneos-cross";
515     }
516     return "ios64-cross" if $GUESSOS =~ 'arm64-.*-iphoneos|.*-.*-ios64';
517     if ( $GUESSOS =~ 'alpha-.*-linux2' ) {
518         my $ISA = `awk '/cpu model/{print \$4;exit(0);}' /proc/cpuinfo`;
519         $ISA //= 'generic';
520         if ( $CCVENDOR eq "gnu" ) {
521             if ( $ISA =~ 'EV5|EV45' ) {
522                 $__CNF_CFLAGS .= " -mcpu=ev5";
523                 $__CNF_CFLAGS .= " -mcpu=ev5";
524             } elsif ( $ISA =~ 'EV56|PCA56' ) {
525                 $__CNF_CFLAGS .= " -mcpu=ev56";
526                 $__CNF_CXXFLAGS .= " -mcpu=ev56";
527             } else {
528                 $__CNF_CFLAGS .= "-mcpu=ev6";
529                 $__CNF_CXXFLAGS .= "-mcpu=ev6";
530             }
531         }
532         return "linux-alpha-$CC";
533     }
534     if ( $GUESSOS =~ 'ppc64-.*-linux2' ) {
535         if ( $KERNEL_BITS eq '' ) {
536             print <<EOF;
537 WARNING! To build 64-bit package, do this:
538          $WHERE/Configure linux-ppc64
539 EOF
540             maybe_abort();
541         }
542         return "linux-ppc64" if $KERNEL_BITS eq '64';
543         if (!okrun('echo __LP64__',
544                 'gcc -E -x c - 2>/dev/null',
545                 'grep "^__LP64__" 2>&1 >/dev/null') ) {
546             $__CNF_CFLAGS .= " -m32";
547             $__CNF_CXXFLAGS .= " -m32";
548         }
549         return "linux-ppc";
550     }
551     return "linux-ppc64le" if $GUESSOS =~ 'ppc64le-.*-linux2';
552     return "linux-ppc" if $GUESSOS =~ 'ppc-.*-linux2';
553     if ( $GUESSOS =~ 'mips64.*-*-linux2' ) {
554         print <<EOF;
555 WARNING! To build 64-bit package, do this:
556          $WHERE/Configure linux64-mips64
557 EOF
558         maybe_abort();
559         return "linux-mips64";
560     }
561     return "linux-mips32" if $GUESSOS =~ 'mips.*-.*-linux2';
562     return "vxworks-ppc60x" if $GUESSOS =~ 'ppc60x-.*-vxworks*';
563     return "vxworks-ppcgen" if $GUESSOS =~ 'ppcgen-.*-vxworks*';
564     return "vxworks-pentium" if $GUESSOS =~ 'pentium-.*-vxworks*';
565     return "vxworks-simlinux" if $GUESSOS =~ 'simlinux-.*-vxworks*';
566     return "vxworks-mips" if $GUESSOS =~ 'mips-.*-vxworks*';
567     return "linux-generic64 -DL_ENDIAN" if $GUESSOS =~ 'e2k-.*-linux*';
568     return "linux-ia64" if $GUESSOS =~ 'ia64-.*-linux.';
569     if ( $GUESSOS =~ 'sparc64-.*-linux2' ) {
570         print <<EOF;
571 WARNING! If you *know* that your GNU C supports 64-bit/V9 ABI and you
572          want to build 64-bit library, do this:
573          $WHERE/Configure linux64-sparcv9
574 EOF
575         maybe_abort();
576         return "linux-sparcv9";
577     }
578     if ( $GUESSOS =~ 'sparc-.*-linux2' ) {
579         my $KARCH = `awk '/^type/{print \$3;exit(0);}' /proc/cpuinfo`;
580         $KARCH //= "sun4";
581         return "linux-sparcv9" if $KARCH =~ 'sun4u*';
582         return "linux-sparcv8" if $KARCH =~ 'sun4[md]';
583         $__CNF_CPPFLAGS .= " -DB_ENDIAN";
584         return "linux-generic32";
585     }
586     if ( $GUESSOS =~ 'parisc.*-.*-linux2' ) {
587         # 64-bit builds under parisc64 linux are not supported and
588         # compiler is expected to generate 32-bit objects...
589         my $CPUARCH =
590         `awk '/cpu family/{print substr(\$5,1,3); exit(0);}' /proc/cpuinfo`;
591         my $CPUSCHEDULE =
592         `awk '/^cpu.[   ]*: PA/{print substr(\$3,3); exit(0);}' /proc/cpuinfo`;
593         # TODO XXX  Model transformations
594         # 0. CPU Architecture for the 1.1 processor has letter suffixes. We
595         #    strip that off assuming no further arch. identification will ever
596         #    be used by GCC.
597         # 1. I'm most concerned about whether is a 7300LC is closer to a 7100
598         #    versus a 7100LC.
599         # 2. The variant 64-bit processors cause concern should GCC support
600         #    explicit schedulers for these chips in the future.
601         #         PA7300LC -> 7100LC (1.1)
602         #         PA8200   -> 8000   (2.0)
603         #         PA8500   -> 8000   (2.0)
604         #         PA8600   -> 8000   (2.0)
605         $CPUSCHEDULE =~ s/7300LC/7100LC/;
606         $CPUSCHEDULE =~ s/8.00/8000/;
607         # Finish Model transformations
608         $__CNF_CPPFLAGS .= " -DB_ENDIAN";
609         $__CNF_CFLAGS .= " -mschedule=$CPUSCHEDULE -march=$CPUARCH";
610         $__CNF_CXXFLAGS .= " -mschedule=$CPUSCHEDULE -march=$CPUARCH";
611         return "linux-generic32";
612     }
613     return "linux-generic32" if $GUESSOS =~ 'armv[1-3].*-.*-linux2';
614     if ( $GUESSOS =~ 'armv[7-9].*-.*-linux2' ) {
615         $__CNF_CFLAGS .= " -march=armv7-a";
616         $__CNF_CXXFLAGS .= " -march=armv7-a";
617         return "linux-armv4";
618     }
619     return "linux-armv4" if $GUESSOS =~ 'arm.*-.*-linux2';
620     return "linux-aarch64" if $GUESSOS =~ 'aarch64-.*-linux2';
621     if ( $GUESSOS =~ 'sh.*b-.*-linux2' ) {
622         $__CNF_CPPFLAGS .= " -DB_ENDIAN";
623         return "linux-generic32";
624     }
625     if ( $GUESSOS =~ 'sh.*-.*-linux2' ) {
626         $__CNF_CPPFLAGS .= " -DL_ENDIAN";
627         return "linux-generic32";
628     }
629     if ( $GUESSOS =~ 'm68k.*-.*-linux2' || $GUESSOS =~ 's390-.*-linux2' ) {
630         $__CNF_CPPFLAGS .= " -DB_ENDIAN";
631         return "linux-generic32";
632     }
633     if ( $GUESSOS =~ 's390x-.*-linux2' ) {
634         # Disabled until a glibc bug is fixed; see Configure.
635         if (0 || okrun(
636                 'egrep -e \'^features.* highgprs\' /proc/cpuinfo >/dev/null') )
637         {
638             print <<EOF;
639 WARNING! To build "highgprs" 32-bit package, do this:
640          $WHERE/Configure linux32-s390x
641 EOF
642             maybe_abort();
643         }
644         return "linux64-s390x";
645     }
646     if ( $GUESSOS =~ 'x86_64-.*-linux.' ) {
647         return "linux-x32"
648             if okrun("$CC -dM -E -x c /dev/null 2>&1",
649                 'grep -q ILP32 >/dev/null');
650         return "linux-x86_64";
651     }
652     if ( $GUESSOS =~ '.*86-.*-linux2' ) {
653         # On machines where the compiler understands -m32, prefer a
654         # config target that uses it
655         return "linux-x86"
656             if okrun("$CC -m32 -E -x c /dev/null >/dev/null 2>&1");
657         return "linux-elf"
658     }
659     return "linux-aout" if $GUESSOS =~ '.*86-.*-linux1';
660     return "linux-generic32" if $GUESSOS =~ '.*-.*-linux.';
661     if ( $GUESSOS =~ 'sun4[uv].*-.*-solaris2' ) {
662         my $ISA64 = `isainfo 2>/dev/null | grep sparcv9`;
663         if ( $ISA64 ne "" && $KERNEL_BITS eq '' ) {
664             if ( $CCVENDOR eq "sun" && $CCVER >= 500 ) {
665                 print <<EOF;
666 WARNING! To build 64-bit package, do this:
667          $WHERE/Configure solaris64-sparcv9-cc
668 EOF
669                 maybe_abort();
670             } elsif ( $CCVENDOR eq "gnu" && $GCC_ARCH eq "-m64" ) {
671                 # $GCC_ARCH denotes default ABI chosen by compiler driver
672                 # (first one found on the $PATH). I assume that user
673                 # expects certain consistency with the rest of his builds
674                 # and therefore switch over to 64-bit. <appro>
675                 print <<EOF;
676 WARNING! To build 32-bit package, do this:
677          $WHERE/Configure solaris-sparcv9-gcc
678 EOF
679                 maybe_abort();
680                 return "solaris64-sparcv9-gcc";
681             } elsif ( $GCC_ARCH eq "-m32" ) {
682                 print <<EOF;
683 NOTICE! If you *know* that your GNU C supports 64-bit/V9 ABI and you wish
684         to build 64-bit library, do this:
685         $WHERE/Configure solaris64-sparcv9-gcc
686 EOF
687                 maybe_abort();
688             }
689         }
690         return "solaris64-sparcv9-$CC" if $ISA64 ne "" && $KERNEL_BITS eq '64';
691         return "solaris-sparcv9-$CC";
692     }
693     return "solaris-sparcv8-$CC" if $GUESSOS =~ 'sun4m-.*-solaris2';
694     return "solaris-sparcv8-$CC" if $GUESSOS =~ 'sun4d-.*-solaris2';
695     return "solaris-sparcv7-$CC" if $GUESSOS =~ 'sun4.*-.*-solaris2';
696     if ( $GUESSOS =~ '.*86.*-.*-solaris2' ) {
697         my $ISA64 = `isainfo 2>/dev/null | grep amd64`;
698         my $KB = $KERNEL_BITS // '64';
699         return "solaris64-x86_64-$CC" if $ISA64 ne "" && $KB eq '64';
700         my $REL = uname('-r');
701         $REL =~ s/5\.//;
702         $options .= " no-sse2" if int($REL) < 10;
703         return "solaris-x86-$CC";
704     }
705     return "sunos-$CC" if $GUESSOS =~ '.*-.*-sunos4';
706     if ( $GUESSOS =~ '.*86.*-.*-bsdi4' ) {
707         $options .= " no-sse2";
708         $__CNF_LDFLAGS .= " -ldl";
709         return "BSD-x86-elf";
710     }
711     if ( $GUESSOS =~ 'alpha.*-.*-.*bsd.*' ) {
712         $__CNF_CPPFLAGS .= " -DL_ENDIAN";
713         return "BSD-generic64";
714     }
715     if ( $GUESSOS =~ 'powerpc64-.*-.*bsd.*' ) {
716         $__CNF_CPPFLAGS .= " -DB_ENDIAN";
717         return "BSD-generic64";
718     }
719     return "BSD-sparc64" if $GUESSOS =~ 'sparc64-.*-.*bsd.*';
720     return "BSD-ia64" if $GUESSOS =~ 'ia64-.*-.*bsd.*';
721     return "BSD-x86_64" if $GUESSOS =~ 'x86_64-.*-dragonfly.*';
722     return "BSD-x86_64" if $GUESSOS =~ 'amd64-.*-.*bsd.*';
723     if ( $GUESSOS =~ '.*86.*-.*-.*bsd.*' ) {
724         # mimic ld behaviour when it's looking for libc...
725         my $libc;
726         if ( -l "/usr/lib/libc.so" ) {
727             $libc = "/usr/lib/libc.so";
728         } else {
729             # ld searches for highest libc.so.* and so do we
730             $libc = 
731             `(ls /usr/lib/libc.so.* /lib/libc.so.* | tail -1) 2>/dev/null`;
732         }
733         my $what = `file -L $libc 2>/dev/null`;
734         return "BSD-x86-elf" if $what =~ /ELF/;
735         $options .= " no-sse2";
736         return "BSD-x86";
737     }
738     return "BSD-generic32" if $GUESSOS =~ '.*-.*-.*bsd.*';
739     return "haiku-x86_64" if $GUESSOS =~ 'x86_64-.*-haiku';
740     return "haiku-x86" if $GUESSOS =~ '.*-.*-haiku';
741     return "osf1-alpha-cc" if $GUESSOS =~ '.*-.*-osf';
742     return "tru64-alpha-cc" if $GUESSOS =~ '.*-.*-tru64';
743     if ( $GUESSOS =~ '.*-.*-[Uu]nix[Ww]are7' ) {
744         $options .= "no-sse2";
745         return "unixware-7-gcc" if $CCVENDOR eq "gnu";
746         $__CNF_CPPFLAGS .= " -D__i386__";
747         return "unixware-7";
748     }
749     if ( $GUESSOS =~ '.*-.*-[Uu]nix[Ww]are20*' ) {
750         $options .= " no-sse2 no-sha512";
751         return "unixware-2.0";
752     }
753     if ( $GUESSOS =~ '.*-.*-[Uu]nix[Ww]are21*' ) {
754         $options .= " no-sse2 no-sha512";
755         return "unixware-2.1";
756     }
757     if ( $GUESSOS =~ '.*-.*-vos' ) {
758         $options .= " no-threads no-shared no-asm no-dso";
759         return "vos-$CC";
760     }
761     return "BS2000-OSD" if $GUESSOS =~ 'BS2000-siemens-sysv4';
762     return "Cygwin-x86" if $GUESSOS =~ 'i[3456]86-.*-cygwin';
763     return "Cygwin-${MACHINE}" if $GUESSOS =~ '.*-.*-cygwin';
764     return "android-x86" if $GUESSOS =~ 'x86-.*-android|i.86-.*-android';
765     if ( $GUESSOS =~ 'armv[7-9].*-.*-android' ) {
766         $__CNF_CFLAGS .= " -march=armv7-a";
767         $__CNF_CXXFLAGS .= " -march=armv7-a";
768         return "android-armeabi";
769     }
770     return "android-armeabi" if $GUESSOS =~ 'arm.*-.*-android';
771     if ( $GUESSOS =~ '.*-hpux1.*' ) {
772         $OUT = "hpux64-parisc2-gcc" if $CCVENDOR eq "gnu" && $GCC_BITS eq '64';
773         $KERNEL_BITS //= `getconf KERNEL_BITS 2>/dev/null` // '32';
774         # See <sys/unistd.h> for further info on CPU_VERSION.
775         my $CPU_VERSION = `getconf CPU_VERSION 2>/dev/null` // 0;
776         $__CNF_CPPFLAGS .= " -D_REENTRANT";
777         if ( $CPU_VERSION >= 768 ) {
778             # IA-64 CPU
779             return "hpux64-ia64-cc" if $KERNEL_BITS eq '64' && ! $CCVENDOR;
780             return "hpux-ia64-cc"
781         }
782         if ( $CPU_VERSION >= 532 ) {
783             # PA-RISC 2.x CPU
784             # PA-RISC 2.0 is no longer supported as separate 32-bit
785             # target. This is compensated for by run-time detection
786             # in most critical assembly modules and taking advantage
787             # of 2.0 architecture in PA-RISC 1.1 build.
788             $OUT //= "hpux-parisc1_1-${CC}";
789             if ( $KERNEL_BITS eq '64' && ! $CCVENDOR ) {
790                 print <<EOF;
791 WARNING! To build 64-bit package, do this:
792          $WHERE/Configure hpux64-parisc2-cc
793 EOF
794                 maybe_abort();
795             }
796             return $OUT;
797         }
798         # PA-RISC 1.1+ CPU?
799         return "hpux-parisc1_1-${CC}" if $CPU_VERSION >= 528;
800         # PA-RISC 1.0 CPU
801         return "hpux-parisc-${CC}" if $CPU_VERSION >= 523;
802         # Motorola(?) CPU
803         return "hpux-$CC";
804         return $OUT;
805     }
806     return "hpux-parisc-$CC" if $GUESSOS =~ '.*-hpux';
807     if ( $GUESSOS =~ '.*-aix' ) {
808         $KERNEL_BITS //= `getconf KERNEL_BITMODE 2>/dev/null`;
809         $KERNEL_BITS //= '32';
810         my $OBJECT_MODE //= 32;
811         if ( $CCVENDOR eq "gcc" ) {
812             $OUT = "aix-gcc";
813             if ( $OBJECT_MODE == 64 ) {
814                 print 'Your $OBJECT_MODE was found to be set to 64';
815                 $OUT = "aix64-gcc"
816             }
817         } elsif ( $OBJECT_MODE == 64 ) {
818             print 'Your $OBJECT_MODE was found to be set to 64';
819             $OUT = "aix64-cc";
820         } else {
821             $OUT = "aix-cc";
822             if ( $KERNEL_BITS eq '64' ) {
823                 print <<EOF;
824 WARNING! To build 64-bit package, do this:
825          $WHERE/Configure aix64-cc
826 EOF
827                 maybe_abort();
828             }
829         }
830         if ( okrun(
831                 "lsattr -E -O -l `lsdev -c processor|awk '{print \$1;exit}'`",
832                 'grep -i powerpc) >/dev/null 2>&1') ) {
833             # this applies even to Power3 and later, as they return
834             # PowerPC_POWER[345]
835         } else {
836             $config{disable} = [ 'asm' ];
837         }
838         return %config;
839     }
840
841     # Last case, return "z" from x-y-z
842     my @fields = split(/-/, $GUESSOS);
843     return ( target => $fields[2] );
844 }
845
846 # gcc < 2.8 does not support -march=ultrasparc
847 sub check_solaris_sparc8 {
848     my $OUT = shift;
849     if ( $CCVENDOR eq 'gnu' && $CCVER < 208 ) {
850         if ( $OUT eq 'solaris-sparcv9-gcc' ) {
851             print <<EOF;
852 WARNING! Downgrading to solaris-sparcv8-gcc
853          Upgrade to gcc-2.8 or later.
854 EOF
855             maybe_abort();
856             return 'solaris-sparcv8-gcc';
857         }
858         if ( $OUT eq "linux-sparcv9" ) {
859             print <<EOF;
860 WARNING! Downgrading to linux-sparcv8
861          Upgrade to gcc-2.8 or later.
862 EOF
863             maybe_abort();
864             return 'linux-sparcv8';
865         }
866     }
867     return $OUT;
868 }
869
870 # Append $CC to the target if that's in the Config list.
871 sub check_target_exists {
872     my $OUT = shift;
873     my %table;
874
875     open T, "$PERL $WHERE/Configure LIST|" or die "Can't get LIST, $!";
876     while ( <T> ) {
877         chop;
878         $table{$_} = 1;
879     }
880     close T;
881     return "$OUT-$CC" if defined $table{"$OUT-$CC"};
882     return "$OUT" if defined $table{$OUT};
883     print "This system ($OUT) is not supported. See INSTALL for details.\n";
884     exit 1;
885 }
886
887
888 ###
889 ###   MAIN PROCESSING
890 ###
891
892 # Common part, does all the real work.
893 sub common {
894     my $showguess = shift;
895
896     get_machine_etc();
897     my $GUESSOS = guess_system();
898     print "Operating system: $GUESSOS\n" if $VERBOSE || $showguess;
899     $options .= " 386" if $GUESSOS =~ /i386-/;
900     remove_removed_crypto_directories();
901     determine_compiler_settings();
902     my $TARGET = map_guess($GUESSOS) // $CC;
903     $TARGET = check_solaris_sparc8($TARGET);
904     $TARGET = check_target_exists($TARGET);
905     $options .= " $CONFIG_OPTIONS" if $CONFIG_OPTIONS ne '';
906     return $TARGET;
907 }
908
909 ##  If called from Configure
910 sub get_platform {
911     my $ref = shift;
912     my %options = %{$ref};
913     $VERBOSE = 1 if defined $options{verbose};
914     $options .= " --debug" if defined $options{debug};
915     $WAIT = 0 if defined $options{nowait};
916
917     my $TARGET = common(0);
918
919     # Populate the environment settings.
920     my %env;
921     $env{__CNF_CPPDEFINES} = $__CNF_CPPDEFINES;
922     $env{__CNF_CPPINCLUDES} = $__CNF_CPPINCLUDES;
923     $env{__CNF_CPPFLAGS} = $__CNF_CPPFLAGS;
924     $env{__CNF_CFLAGS} = $__CNF_CFLAGS;
925     $env{__CNF_CXXFLAGS} = $__CNF_CXXFLAGS;
926
927     # Prepare results and return them
928     my %ret = {
929         'target' => $TARGET,
930         'options' => $options,
931         'envvars' => %env,
932     };
933     return %ret;
934 }
935
936 }
937
938 1;