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