Make the s_server command listen on IPv6 only when requested
[openssl.git] / Configure
index ef532dad78d1530cb520b5db45ad95735874da08..ea00e8d96d1dfaffe95e8958f114ea53a2287c36 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -1,6 +1,6 @@
 #! /usr/bin/env perl
 # -*- mode: perl; -*-
-# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -9,13 +9,15 @@
 
 ##  Configure -- OpenSSL source tree configuration script
 
-require 5.10.0;
+use 5.10.0;
 use strict;
 use Config;
+use FindBin;
+use lib "$FindBin::Bin/util/perl";
 use File::Basename;
 use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
 use File::Path qw/mkpath/;
-use if $^O ne "VMS", 'File::Glob' => qw/glob/;
+use OpenSSL::Glob;
 
 # see INSTALL for instructions.
 
@@ -61,8 +63,7 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
 #              library and will be loaded in run-time by the OpenSSL library.
 # sctp          include SCTP support
 # enable-weak-ssl-ciphers
-#               Enable weak ciphers that are disabled by default. This currently
-#               only includes RC4 based ciphers.
+#               Enable weak ciphers that are disabled by default.
 # 386           generate 80386 code in assembly modules
 # no-sse2       disables IA-32 SSE2 code in assembly modules, the above
 #               mentioned '386' option implies this one
@@ -116,15 +117,18 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
 # but 'long long' type.
 
 my $gcc_devteam_warn = "-DDEBUG_UNUSED"
-        . " -Wswitch"
         . " -DPEDANTIC -pedantic -Wno-long-long"
         . " -Wall"
+        . " -Wextra"
+        . " -Wno-unused-parameter"
+        . " -Wno-missing-field-initializers"
+        . " -Wswitch"
         . " -Wsign-compare"
         . " -Wmissing-prototypes"
         . " -Wshadow"
         . " -Wformat"
         . " -Wtype-limits"
-        . " -Wno-parentheses-equality"
+        . " -Wundef"
         . " -Werror"
         ;
 
@@ -137,17 +141,14 @@ my $gcc_devteam_warn = "-DDEBUG_UNUSED"
 #       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
 #       -Wextended-offsetof -- no, needed in CMS ASN1 code
 my $clang_devteam_warn = ""
-        . " -Qunused-arguments"
-        . " -Wextra"
-        . " -Wswitch -Wswitch-default"
-        . " -Wno-unused-parameter"
+        . " -Wswitch-default"
         . " -Wno-parentheses-equality"
-        . " -Wno-missing-field-initializers"
         . " -Wno-language-extension-token"
         . " -Wno-extended-offsetof"
         . " -Wconditional-uninitialized"
         . " -Wincompatible-pointer-types-discards-qualifiers"
         . " -Wmissing-variable-declarations"
+        . " -Wno-unknown-warning-option"
         ;
 
 # This adds backtrace information to the memory leak info.  Is only used
@@ -210,6 +211,8 @@ $config{builddir} = abs2rel($blddir);
 my @argvcopy=@ARGV;
 
 if (grep /^reconf(igure)?$/, @argvcopy) {
+    die "reconfiguring with other arguments present isn't supported"
+        if scalar @argvcopy > 1;
     if (-f "./configdata.pm") {
        my $file = "./configdata.pm";
        unless (my $return = do $file) {
@@ -222,25 +225,12 @@ if (grep /^reconf(igure)?$/, @argvcopy) {
            @{$configdata::config{perlargv}} : ();
        die "Incorrect data to reconfigure, please do a normal configuration\n"
            if (grep(/^reconf/,@argvcopy));
-       $ENV{CROSS_COMPILE} = $configdata::config{cross_compile_prefix}
-           if defined($configdata::config{cross_compile_prefix});
-       $ENV{CC} = $configdata::config{cc}
-           if defined($configdata::config{cc});
-       $ENV{CXX} = $configdata::config{cxx}
-           if defined($configdata::config{cxx});
-       $ENV{BUILDFILE} = $configdata::config{build_file}
-           if defined($configdata::config{build_file});
-       $ENV{$local_config_envname} = $configdata::config{local_config_dir}
-           if defined($configdata::config{local_config_dir});
+       $config{perlenv} = $configdata::config{perlenv} // {};
 
        print "Reconfiguring with: ", join(" ",@argvcopy), "\n";
-       print "    CROSS_COMPILE = ",$ENV{CROSS_COMPILE},"\n"
-           if $ENV{CROSS_COMPILE};
-       print "    CC = ",$ENV{CC},"\n" if $ENV{CC};
-       print "    CXX = ",$ENV{CXX},"\n" if $ENV{CXX};
-       print "    BUILDFILE = ",$ENV{BUILDFILE},"\n" if $ENV{BUILDFILE};
-       print "    $local_config_envname = ",$ENV{$local_config_envname},"\n"
-           if $ENV{$local_config_envname};
+       foreach (sort keys %{$config{perlenv}}) {
+           print "    $_ = $config{perlenv}->{$_}\n";
+       }
     } else {
        die "Insufficient data to reconfigure, please do a normal configuration\n";
     }
@@ -279,13 +269,13 @@ foreach (sort glob($pattern)) {
     &read_config($_);
 }
 
-if (defined $ENV{$local_config_envname}) {
+if (defined env($local_config_envname)) {
     if ($^O eq 'VMS') {
         # VMS environment variables are logical names,
         # which can be used as is
         $pattern = $local_config_envname . ':' . '*.conf';
     } else {
-        $pattern = catfile($ENV{$local_config_envname}, '*.conf');
+        $pattern = catfile(env($local_config_envname), '*.conf');
     }
 
     foreach (sort glob($pattern)) {
@@ -293,32 +283,25 @@ if (defined $ENV{$local_config_envname}) {
     }
 }
 
-
-print "Configuring OpenSSL version $config{version} ($config{version_num})\n";
-
 $config{prefix}="";
 $config{openssldir}="";
 $config{processor}="";
 $config{libdir}="";
 $config{cross_compile_prefix}="";
-$config{fipslibdir}="/usr/local/ssl/fips-2.0/lib/";
-my $nofipscanistercheck=0;
-$config{baseaddr}="0xFB00000";
 my $auto_threads=1;    # enable threads automatically? true by default
 my $default_ranlib;
-$config{fips}=0;
 
 # Top level directories to build
 $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
 # crypto/ subdirectories to build
 $config{sdirs} = [
     "objects",
-    "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2",
-    "des", "aes", "rc2", "rc4", "rc5", "idea", "bf", "cast", "camellia", "seed", "chacha", "modes",
+    "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
+    "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
     "bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
     "buffer", "bio", "stack", "lhash", "rand", "err",
     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
-    "cms", "ts", "srp", "cmac", "ct", "async", "kdf"
+    "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
     ];
 # test/ subdirectories to build
 $config{tdirs} = [ "ossl_shim" ];
@@ -333,6 +316,7 @@ my @dtls = qw(dtls1 dtls1_2);
 
 my @disablables = (
     "afalgeng",
+    "aria",
     "asan",
     "asm",
     "async",
@@ -352,6 +336,7 @@ my @disablables = (
     "ct",
     "deprecated",
     "des",
+    "devcryptoeng",
     "dgram",
     "dh",
     "dsa",
@@ -397,6 +382,9 @@ my @disablables = (
     "sctp",
     "seed",
     "shared",
+    "siphash",
+    "sm3",
+    "sm4",
     "sock",
     "srp",
     "srtp",
@@ -408,9 +396,10 @@ my @disablables = (
     "tests",
     "threads",
     "tls",
+    "tls13downgrade",
     "ts",
     "ubsan",
-    "ui",
+    "ui-console",
     "unit-test",
     "whirlpool",
     "weak-ssl-ciphers",
@@ -420,13 +409,14 @@ my @disablables = (
 foreach my $proto ((@tls, @dtls))
        {
        push(@disablables, $proto);
-       push(@disablables, "$proto-method");
+       push(@disablables, "$proto-method") unless $proto eq "tls1_3";
        }
 
 my %deprecated_disablables = (
     "ssl2" => undef,
     "buf-freelists" => undef,
-    "ripemd" => "rmd160"
+    "ripemd" => "rmd160",
+    "ui" => "ui-console",
     );
 
 # All of the following is disabled by default (RC5 was enabled before 0.9.8):
@@ -435,6 +425,7 @@ our %disabled = ( # "what"         => "comment"
                   "asan"               => "default",
                  "crypto-mdebug"       => "default",
                  "crypto-mdebug-backtrace" => "default",
+                 "devcryptoeng"        => "default",
                  "ec_nistp_64_gcc_128" => "default",
                  "egd"                 => "default",
                  "external-tests"      => "default",
@@ -451,6 +442,7 @@ our %disabled = ( # "what"         => "comment"
                   "ubsan"              => "default",
           #TODO(TLS1.3): Temporarily disabled while this is a WIP
                  "tls1_3"              => "default",
+                 "tls13downgrade"      => "default",
                  "unit-test"           => "default",
                  "weak-ssl-ciphers"    => "default",
                  "zlib"                => "default",
@@ -471,29 +463,12 @@ my @disable_cascades = (
     "dgram"            => [ "dtls", "sctp" ],
     "sock"             => [ "dgram" ],
     "dtls"             => [ @dtls ],
-
-    # SSL 3.0, (D)TLS 1.0 and TLS 1.1 require MD5 and SHA
-    "md5"              => [ "ssl", "tls1", "tls1_1", "dtls1" ],
-    "sha"              => [ "ssl", "tls1", "tls1_1", "dtls1" ],
-
-    # Additionally, SSL 3.0 requires either RSA or DSA+DH
-    sub { $disabled{rsa}
-         && ($disabled{dsa} || $disabled{dh}); }
-                       => [ "ssl" ],
-
-    # (D)TLS 1.0 and TLS 1.1 also require either RSA or DSA+DH
-    # or ECDSA + ECDH.  (D)TLS 1.2 has this requirement as well.
-    # (XXX: We don't support PSK-only builds).
-    sub { $disabled{rsa}
-         && ($disabled{dsa} || $disabled{dh})
-         && ($disabled{ecdsa} || $disabled{ecdh}); }
-                       => [ "tls1", "tls1_1", "tls1_2", "tls1_3",
-                            "dtls1", "dtls1_2" ],
+    sub { 0 == scalar grep { !$disabled{$_} } @dtls }
+                       => [ "dtls" ],
 
     "tls"              => [ @tls ],
-
-    # SRP and HEARTBEATS require TLSEXT
-    "tlsext"           => [ "srp", "heartbeats" ],
+    sub { 0 == scalar grep { !$disabled{$_} } @tls }
+                       => [ "tls" ],
 
     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
 
@@ -503,13 +478,14 @@ my @disable_cascades = (
     # Without position independent code, there can be no shared libraries or DSOs
     "pic"               => [ "shared" ],
     "shared"            => [ "dynamic-engine" ],
-    "engine"            => [ "afalgeng" ],
+    "engine"            => [ "afalgeng", "devcryptoeng" ],
 
     # no-autoalginit is only useful when building non-shared
     "autoalginit"       => [ "shared", "apps" ],
 
-    "stdio"             => [ "apps", "capieng" ],
+    "stdio"             => [ "apps", "capieng", "egd" ],
     "apps"              => [ "tests" ],
+    "tests"             => [ "external-tests" ],
     "comp"              => [ "zlib" ],
     "ec"                => [ "tls1_3" ],
     sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
@@ -550,6 +526,7 @@ $config{openssl_algorithm_defines}=[];
 $config{openssl_thread_defines}=[];
 $config{openssl_sys_defines}=[];
 $config{openssl_other_defines}=[];
+my $ldflags="";
 my $libs="";
 my $target="";
 $config{options}="";
@@ -557,9 +534,20 @@ $config{build_type} = "release";
 
 my %unsupported_options = ();
 my %deprecated_options = ();
+# If you change this, update apps/version.c
+my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
+my @seed_sources = ();
 while (@argvcopy)
        {
        $_ = shift @argvcopy;
+
+       # Support env variable assignments among the options
+       if (m|^(\w+)=(.+)?$|)
+               {
+               $config{perlenv}->{$1} = $2;
+               next;
+               }
+
        # VMS is a case insensitive environment, and depending on settings
        # out of our control, we may receive options uppercased.  Let's
        # downcase at least the part before any equal sign.
@@ -677,7 +665,7 @@ while (@argvcopy)
                { $config{processor}=386; }
        elsif (/^fips$/)
                {
-               $config{fips}=1;
+               die "FIPS mode not supported\n";
                }
        elsif (/^rsaref$/)
                {
@@ -687,8 +675,7 @@ while (@argvcopy)
                }
        elsif (/^nofipscanistercheck$/)
                {
-               $config{fips} = 1;
-               $nofipscanistercheck = 1;
+               die "FIPS mode not supported\n";
                }
        elsif (/^[-+]/)
                {
@@ -726,14 +713,15 @@ while (@argvcopy)
                        {
                        $withargs{fuzzer_include}=$1;
                        }
-               elsif (/^--with-fipslibdir=(.*)$/)
+               elsif (/^--with-rand-seed=(.*)$/)
                        {
-                       $config{fipslibdir}="$1/";
-                       }
-               elsif (/^--with-baseaddr=(.*)$/)
-                       {
-                       $config{baseaddr}="$1";
-                       }
+                       foreach my $x (split(m|,|, $1))
+                           {
+                           die "Unknown --with-rand-seed choice $x\n"
+                               if ! grep { $x eq $_ } @known_seed_sources;
+                           push @seed_sources, $x;
+                           }
+                        }
                elsif (/^--cross-compile-prefix=(.*)$/)
                        {
                        $config{cross_compile_prefix}=$1;
@@ -742,10 +730,18 @@ while (@argvcopy)
                        {
                        read_config $1;
                        }
-               elsif (/^-[lL](.*)$/ or /^-Wl,/)
+               elsif (/^-L(.*)$/)
+                       {
+                       $ldflags.=$_." ";
+                       }
+               elsif (/^-l(.*)$/ or /^-Wl,/)
                        {
                        $libs.=$_." ";
                        }
+               elsif (/^-framework$/)
+                       {
+                       $libs.=$_." ".shift(@argvcopy)." ";
+                       }
                elsif (/^-rpath$/ or /^-R$/)
                        # -rpath is the OSF1 rpath flag
                        # -R is the old Solaris rpath flag
@@ -779,7 +775,7 @@ while (@argvcopy)
                }
        unless ($_ eq $target || /^no-/ || /^disable-/)
                {
-               # "no-..." follows later after implied disactivations
+               # "no-..." follows later after implied deactivations
                # have been derived.  (Don't take this too seriously,
                # we really only write OPTIONS to the Makefile out of
                # nostalgia.)
@@ -813,14 +809,16 @@ if ($libs =~ /(^|\s)-Wl,-rpath,/
        "***** any of asan, msan or ubsan\n";
 }
 
-if ($config{fips})
-       {
-       delete $disabled{"shared"} if ($disabled{"shared"} =~ /^default/);
-       }
-else
-       {
-       @{$config{dirs}} = grep !/^fips$/, @{$config{dirs}};
-       }
+if (scalar(@seed_sources) == 0) {
+    print "Using implicit seed configuration\n";
+    push @seed_sources, 'os';
+}
+die "Cannot seed with none and anything else"
+    if scalar(grep { $_ eq 'none' } @seed_sources) > 0
+        && scalar(@seed_sources) > 1;
+push @{$config{openssl_other_defines}},
+     map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
+       @seed_sources;
 
 my @tocheckfor = (keys %disabled);
 while (@tocheckfor) {
@@ -862,11 +860,91 @@ if ($target eq "HASH") {
     exit 0;
 }
 
+print "Configuring OpenSSL version $config{version} ($config{version_num})\n";
+print "for $target\n";
+
 # Backward compatibility?
 if ($target =~ m/^CygWin32(-.*)$/) {
     $target = "Cygwin".$1;
 }
 
+# Support for legacy targets having a name starting with 'debug-'
+my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
+if ($d) {
+    $config{build_type} = "debug";
+
+    # If we do not find debug-foo in the table, the target is set to foo.
+    if (!$table{$target}) {
+       $target = $t;
+    }
+}
+$config{target} = $target;
+my %target = resolve_config($target);
+
+&usage if (!%target || $target{template});
+
+%target = ( %{$table{DEFAULTS}}, %target );
+
+# Make the flags to build DSOs the same as for shared libraries unless they
+# are already defined
+$target{dso_cflags} = $target{shared_cflag} unless defined $target{dso_cflags};
+$target{dso_cxxflags} = $target{shared_cxxflag} unless defined $target{dso_cxxflags};
+$target{dso_lflags} = $target{shared_ldflag} unless defined $target{dso_lflags};
+{
+    my $shared_info_pl =
+        catfile(dirname($0), "Configurations", "shared-info.pl");
+    my %shared_info = read_eval_file($shared_info_pl);
+    push @{$target{_conf_fname_int}}, $shared_info_pl;
+    my $si = $target{shared_target};
+    while (ref $si ne "HASH") {
+        last if ! defined $si;
+        if (ref $si eq "CODE") {
+            $si = $si->();
+        } else {
+            $si = $shared_info{$si};
+        }
+    }
+
+    # Some of the 'shared_target' values don't have any entried in
+    # %shared_info.  That's perfectly fine, AS LONG AS the build file
+    # template knows how to handle this.  That is currently the case for
+    # Windows and VMS.
+    if (defined $si) {
+        # Just as above, copy certain shared_* attributes to the corresponding
+        # dso_ attribute unless the latter is already defined
+        $si->{dso_cflags} = $si->{shared_cflag} unless defined $si->{dso_cflags};
+        $si->{dso_cxxflags} = $si->{shared_cxxflag} unless defined $si->{dso_cxxflags};
+        $si->{dso_lflags} = $si->{shared_ldflag} unless defined $si->{dso_lflags};
+        foreach (sort keys %$si) {
+            $target{$_} = defined $target{$_}
+                ? add($si->{$_})->($target{$_})
+                : $si->{$_};
+        }
+    }
+}
+
+my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
+$config{conf_files} = [ sort keys %conf_files ];
+
+foreach my $feature (@{$target{disable}}) {
+    if (exists $deprecated_disablables{$feature}) {
+        warn "***** config $target disables deprecated feature $feature\n";
+    } elsif (!grep { $feature eq $_ } @disablables) {
+        die "***** config $target disables unknown feature $feature\n";
+    }
+    $disabled{$feature} = 'config';
+}
+foreach my $feature (@{$target{enable}}) {
+    if ("default" eq ($disabled{$_} // "")) {
+        if (exists $deprecated_disablables{$feature}) {
+            warn "***** config $target enables deprecated feature $feature\n";
+        } elsif (!grep { $feature eq $_ } @disablables) {
+            die "***** config $target enables unknown feature $feature\n";
+        }
+        delete $disabled{$_};
+    }
+}
+
 foreach (sort (keys %disabled))
        {
        $config{options} .= " no-$_";
@@ -931,26 +1009,6 @@ foreach (sort (keys %disabled))
        print "\n";
        }
 
-print "Configuring for $target\n";
-# Support for legacy targets having a name starting with 'debug-'
-my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
-if ($d) {
-    $config{build_type} = "debug";
-
-    # If we do not find debug-foo in the table, the target is set to foo.
-    if (!$table{$target}) {
-       $target = $t;
-    }
-}
-$config{target} = $target;
-my %target = resolve_config($target);
-
-&usage if (!%target || $target{template});
-
-my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
-$config{conf_files} = [ sort keys %conf_files ];
-%target = ( %{$table{DEFAULTS}}, %target );
-
 $target{cxxflags}=$target{cflags} unless defined $target{cxxflags};
 $target{exe_extension}="";
 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
@@ -958,13 +1016,13 @@ $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
 
 ($target{shared_extension_simple}=$target{shared_extension})
-    =~ s|\.\$\(SHLIB_MAJOR\)\.\$\(SHLIB_MINOR\)||;
+    =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||;
 $target{dso_extension}=$target{shared_extension_simple};
 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
     if ($config{target} =~ /^(?:Cygwin|mingw)/);
 
 
-$config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'}
+$config{cross_compile_prefix} = env('CROSS_COMPILE')
     if $config{cross_compile_prefix} eq "";
 
 # Allow overriding the names of some tools.  USE WITH CARE
@@ -972,19 +1030,19 @@ $config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'}
 # the default string.
 $config{perl} =    ($^O ne "VMS" ? $^X : "perl");
 $config{hashbangperl} =
-    $ENV{'HASHBANGPERL'}           || $ENV{'PERL'}     || "/usr/bin/env perl";
-$target{cc} =      $ENV{'CC'}      || $target{cc}      || "cc";
-$target{cxx} =     $ENV{'CXX'}     || $target{cxx}     || "c++";
-$target{ranlib} =  $ENV{'RANLIB'}  || $target{ranlib}  ||
+    env('HASHBANGPERL')           || env('PERL')      || "/usr/bin/env perl";
+$target{cc} =      env('CC')      || $target{cc}      || "cc";
+$target{cxx} =     env('CXX')     || $target{cxx}     || "c++";
+$target{ranlib} =  env('RANLIB')  || $target{ranlib}  ||
                    (which("$config{cross_compile_prefix}ranlib") ?
                           "\$(CROSS_COMPILE)ranlib" : "true");
-$target{ar} =      $ENV{'AR'}      || $target{ar}      || "ar";
-$target{nm} =      $ENV{'NM'}      || $target{nm}      || "nm";
+$target{ar} =      env('AR')      || $target{ar}      || "ar";
+$target{nm} =      env('NM')      || $target{nm}      || "nm";
 $target{rc} =
-    $ENV{'RC'}  || $ENV{'WINDRES'} || $target{rc}      || "windres";
+    env('RC')  || env('WINDRES')  || $target{rc}      || "windres";
 
 # Allow overriding the build file name
-$target{build_file} = $ENV{BUILDFILE} || $target{build_file} || "Makefile";
+$target{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
 
 # Cache information necessary for reconfiguration
 $config{cc} = $target{cc};
@@ -997,6 +1055,7 @@ $config{build_file} = $target{build_file};
 $config{defines} = [];
 $config{cflags} = "";
 $config{cxxflags} = "";
+$config{lflags} = "";
 $config{ex_libs} = "";
 $config{shared_ldflag} = "";
 
@@ -1007,6 +1066,25 @@ $target{build_scheme} = [ $target{build_scheme} ]
 my ($builder, $builder_platform, @builder_opts) =
     @{$target{build_scheme}};
 
+foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
+                      $builder_platform."-checker.pm")) {
+    my $checker_path = catfile($srcdir, "Configurations", $checker);
+    if (-f $checker_path) {
+        my $fn = $ENV{CONFIGURE_CHECKER_WARN}
+            ? sub { warn $@; } : sub { die $@; };
+        if (! do $checker_path) {
+            if ($@) {
+                $fn->($@);
+            } elsif ($!) {
+                $fn->($!);
+            } else {
+                $fn->("The detected tools didn't match the platform\n");
+            }
+        }
+        last;
+    }
+}
+
 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
 
 if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` =~ m/-mno-cygwin/m)
@@ -1049,15 +1127,7 @@ if (!$disabled{dso} && $target{dso_scheme} ne "")
        }
 
 $config{ex_libs}="$libs$config{ex_libs}" if ($libs ne "");
-
-if ($disabled{asm})
-       {
-       if ($config{fips})
-               {
-               @{$config{defines}} = grep !/^[BL]_ENDIAN$/, @{$config{defines}};
-               @{$target{defines}} = grep !/^[BL]_ENDIAN$/, @{$target{defines}};
-               }
-       }
+$config{lflags}="$config{lflags}$ldflags" if ($ldflags ne "");
 
 # If threads aren't disabled, check how possible they are
 unless ($disabled{threads}) {
@@ -1099,8 +1169,7 @@ if (defined($disabled{"deprecated"})) {
 if ($target{shared_target} eq "")
        {
        $no_shared_warn = 1
-           if ((!$disabled{shared} || !$disabled{"dynamic-engine"})
-               && !$config{fips});
+           if (!$disabled{shared} || !$disabled{"dynamic-engine"});
        $disabled{shared} = "no-shared-target";
        $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
            "no-shared-target";
@@ -1139,8 +1208,11 @@ unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
 # This saves the build files from having to check
 if ($disabled{pic})
        {
-       $target{shared_cflag} = $target{shared_ldflag} =
-               $target{shared_rcflag} = "";
+       foreach (qw(shared_cflag shared_cxxflag shared_ldflag
+                   dso_cflags dso_cxxflags dso_lflags))
+               {
+               $target{$_} = "";
+               }
        }
 else
        {
@@ -1164,10 +1236,6 @@ unless ($disabled{asm}) {
     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
     push @{$config{defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
 
-    if ($config{fips}) {
-       push @{$config{openssl_other_defines}}, "OPENSSL_FIPS";
-    }
-
     if ($target{sha1_asm_src}) {
        push @{$config{defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
        push @{$config{defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
@@ -1215,33 +1283,27 @@ unless ($disabled{asm}) {
     }
 }
 
-my $ecc = $target{cc};
-if ($^O ne "VMS" && !$disabled{makedepend}) {
-    # Is the compiler gcc or clang?  $ecc is used below to see if
-    # error-checking can be turned on.
-    my $ccpcc = "$config{cross_compile_prefix}$target{cc}";
-    open(PIPE, "$ccpcc --version 2>&1 |");
-    my $lines = 2;
-    while ( <PIPE> ) {
-        # Find the version number and save the major.
-        m|(?:.*)\b(\d+)\.\d+\.\d+\b(?:.*)|;
-        my $compiler_major = $1;
+my %predefined = compiler_predefined($target{cc});
+
+# Check for makedepend capabilities.
+if (!$disabled{makedepend}) {
+    if ($config{target} =~ /^(VC|vms)-/) {
+        # For VC- and vms- targets, there's nothing more to do here.  The
+        # functionality is hard coded in the corresponding build files for
+        # cl (Windows) and CC/DECC (VMS).
+    } elsif ($predefined{__GNUC__} >= 3) {
         # We know that GNU C version 3 and up as well as all clang
         # versions support dependency generation
-        $config{makedepprog} = $ccpcc
-            if (/clang/ || (/gcc/ && $compiler_major >= 3));
-        $ecc = "clang" if /clang/;
-        $ecc = "gcc" if /gcc/;
-        last if ($config{makedepprog} || !$lines--);
+        $config{makedepprog} = "\$(CROSS_COMPILE)$target{cc}";
+    } else {
+        # In all other cases, we look for 'makedepend', and disable the
+        # capability if not found.
+        $config{makedepprog} = which('makedepend');
+        $disabled{makedepend} = "unavailable" unless $config{makedepprog};
     }
-    close(PIPE);
-
-    $config{makedepprog} = which('makedepend') unless $config{makedepprog};
-    $disabled{makedepend} = "unavailable" unless $config{makedepprog};
 }
 
 
-
 # Deal with bn_ops ###################################################
 
 $config{bn_ll}                 =0;
@@ -1279,16 +1341,23 @@ if (defined($config{api})) {
     push @{$config{defines}}, $apiflag;
 }
 
+if (defined($predefined{__clang__}) && !$disabled{asm}) {
+    $config{cflags} .= " -Qunused-arguments";
+}
+
 if ($strict_warnings)
        {
        my $wopt;
-       die "ERROR --strict-warnings requires gcc or clang"
-            unless $ecc eq 'gcc' || $ecc eq 'clang';
+       my $gccver = $predefined{__GNUC__} // -1;
+
+       die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike"
+            unless $gccver >= 4;
+       $gcc_devteam_warn .= " -Wmisleading-indentation" if $gccver >= 6;
        foreach $wopt (split /\s+/, $gcc_devteam_warn)
                {
                $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
                }
-       if ($ecc eq "clang")
+       if (defined($predefined{__clang__}))
                {
                foreach $wopt (split /\s+/, $clang_devteam_warn)
                        {
@@ -1345,7 +1414,6 @@ my %unified_info = ();
 
 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
 if ($builder eq "unified") {
-    use lib catdir(dirname(__FILE__),"util");
     use with_fallback qw(Text::Template);
 
     sub cleandir {
@@ -1389,7 +1457,7 @@ if ($builder eq "unified") {
     my @build_file_templates = ();
 
     # First, look in the user provided directory, if given
-    if (defined $ENV{$local_config_envname}) {
+    if (defined env($local_config_envname)) {
        @build_file_templates =
            map {
                if ($^O eq 'VMS') {
@@ -1397,7 +1465,7 @@ if ($builder eq "unified") {
                    # which can be used as is
                    $local_config_envname . ':' . $_;
                } else {
-                   catfile($ENV{$local_config_envname}, $_);
+                   catfile(env($local_config_envname), $_);
                }
            }
            @build_file_template_names;
@@ -1442,6 +1510,7 @@ if ($builder eq "unified") {
 
     $config{build_infos} = [ ];
 
+    my %ordinals = ();
     foreach (@build_infos) {
         my $sourced = catdir($srcdir, $_->[0]);
         my $buildd = catdir($blddir, $_->[0]);
@@ -1463,7 +1532,6 @@ if ($builder eq "unified") {
         my @intermediates = ();
         my @rawlines = ();
 
-        my %ordinals = ();
         my %sources = ();
         my %shared_sources = ();
         my %includes = ();
@@ -1473,8 +1541,10 @@ if ($builder eq "unified") {
         my %generate = ();
 
         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
-        my $template = Text::Template->new(TYPE => 'FILE',
-                                           SOURCE => catfile($sourced, $f));
+        my $template =
+            Text::Template->new(TYPE => 'FILE',
+                                SOURCE => catfile($sourced, $f),
+                                PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
         die "Something went wrong with $sourced/$f: $!\n" unless $template;
         my @text =
             split /^/m,
@@ -1735,33 +1805,24 @@ EOF
             }
 
             # Additionally, we set up sharednames for libraries that don't
-            # have any, as themselves.
-            foreach (keys %{$unified_info{libraries}}) {
+            # have any, as themselves.  Only for libraries that aren't
+            # explicitly static.
+            foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
                 if (!defined $unified_info{sharednames}->{$_}) {
                     $unified_info{sharednames}->{$_} = $_
                 }
             }
-        }
 
-        foreach (keys %ordinals) {
-            my $dest = $_;
-            my $ddest = cleanfile($buildd, $_, $blddir);
-            if ($unified_info{rename}->{$ddest}) {
-                $ddest = $unified_info{rename}->{$ddest};
-            }
-            foreach (@{$ordinals{$dest}}) {
-                my %known_ordinals =
-                    (
-                     crypto =>
-                     cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
-                     ssl =>
-                     cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
-                    );
-                my $o = $known_ordinals{$_};
-                die "Ordinals for $ddest defined more than once\n"
-                    if $unified_info{ordinals}->{$ddest};
-                $unified_info{ordinals}->{$ddest} = [ $_, $o ];
+            # Check that we haven't defined any library as both shared and
+            # explicitly static.  That is forbidden.
+            my @doubles = ();
+            foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
+                (my $l = $_) =~ s/\.a$//;
+                push @doubles, $l if defined $unified_info{sharednames}->{$l};
             }
+            die "these libraries are both explicitly static and shared:\n  ",
+                join(" ", @doubles), "\n"
+                if @doubles;
         }
 
         foreach (keys %sources) {
@@ -1806,14 +1867,27 @@ EOF
                 if (! -f $s) {
                     $s = cleanfile($buildd, $_, $blddir);
                 }
-                # We recognise C++, C and asm files
+
                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
+                    # We recognise C++, C and asm files
                     my $o = $_;
                     $o =~ s/\.[csS]$/.o/; # C and assembler
                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
                     $o = cleanfile($buildd, $o, $blddir);
                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
                     $unified_info{sources}->{$o}->{$s} = 1;
+                } elsif ($s =~ /\.rc$/) {
+                    # We also recognise resource files
+                    my $o = $_;
+                    $o =~ s/\.rc$/.res/; # Resource configuration
+                    my $o = cleanfile($buildd, $o, $blddir);
+                    $unified_info{shared_sources}->{$ddest}->{$o} = 1;
+                    $unified_info{sources}->{$o}->{$s} = 1;
+                } elsif ($s =~ /\.(def|map|opt)$/) {
+                    # We also recognise .def / .map / .opt files
+                    # We know they are generated files
+                    my $def = cleanfile($buildd, $s, $blddir);
+                    $unified_info{shared_sources}->{$ddest}->{$def} = 1;
                 } else {
                     die "unrecognised source file type for shared library: $s\n";
                 }
@@ -1872,13 +1946,6 @@ EOF
                 }
                 $d .= $e;
                 $unified_info{depends}->{$ddest}->{$d} = 1;
-                # If we depend on a header file or a perl module, let's make
-                # sure it can get included
-                if ($dest ne "" && $d =~ /\.(h|pm)$/) {
-                    my $i = dirname($d);
-                    push @{$unified_info{includes}->{$ddest}->{source}}, $i
-                        unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}->{source}};
-                }
             }
         }
 
@@ -1905,6 +1972,55 @@ EOF
         }
     }
 
+    my $ordinals_text = join(', ', sort keys %ordinals);
+    warn <<"EOF" if $ordinals_text;
+
+WARNING: ORDINALS were specified for $ordinals_text
+They are ignored and should be replaced with a combination of GENERATE,
+DEPEND and SHARED_SOURCE.
+EOF
+
+    # Massage the result
+
+    # If we depend on a header file or a perl module, add an inclusion of
+    # its directory to allow smoothe inclusion
+    foreach my $dest (keys %{$unified_info{depends}}) {
+        next if $dest eq "";
+        foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
+            next unless $d =~ /\.(h|pm)$/;
+            if ($d eq "configdata.pm"
+                    || defined($unified_info{generate}->{$d})) {
+                my $i = cleandir($blddir, dirname($d));
+                push @{$unified_info{includes}->{$dest}->{build}}, $i
+                    unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{build}};
+            } else {
+                my $i = cleandir($srcdir, dirname($d));
+                push @{$unified_info{includes}->{$dest}->{source}}, $i
+                    unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{source}};
+            }
+        }
+    }
+
+    # Trickle down includes placed on libraries, engines and programs to
+    # their sources (i.e. object files)
+    foreach my $dest (keys %{$unified_info{engines}},
+                      keys %{$unified_info{libraries}},
+                      keys %{$unified_info{programs}}) {
+        foreach my $k (("source", "build")) {
+            next unless defined($unified_info{includes}->{$dest}->{$k});
+            my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
+            foreach my $obj (grep /\.o$/,
+                             (keys %{$unified_info{sources}->{$dest}},
+                              keys %{$unified_info{shared_sources}->{$dest}})) {
+                foreach my $inc (@incs) {
+                    unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
+                        unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
+                }
+            }
+        }
+        delete $unified_info{includes}->{$dest};
+    }
+
     ### Make unified_info a bit more efficient
     # One level structures
     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
@@ -1920,8 +2036,9 @@ EOF
     # Includes
     foreach my $dest (sort keys %{$unified_info{includes}}) {
         if (defined($unified_info{includes}->{$dest}->{build})) {
-            my @source_includes =
-                ( @{$unified_info{includes}->{$dest}->{source}} );
+            my @source_includes = ();
+            @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
+                if defined($unified_info{includes}->{$dest}->{source});
             $unified_info{includes}->{$dest} =
                 [ @{$unified_info{includes}->{$dest}->{build}} ];
             foreach my $inc (@source_includes) {
@@ -1966,6 +2083,22 @@ foreach (sort keys %config) {
        print OUT "  ", $_, " => [ ", join(", ",
                                           map { quotify("perl", $_) }
                                           @{$config{$_}}), " ],\n";
+    } elsif (ref($config{$_}) eq "HASH") {
+       print OUT "  ", $_, " => {";
+        if (scalar keys %{$config{$_}} > 0) {
+            print OUT "\n";
+            foreach my $key (sort keys %{$config{$_}}) {
+                print OUT "      ",
+                    join(" => ",
+                         quotify("perl", $key),
+                         defined $config{$_}->{$key}
+                             ? quotify("perl", $config{$_}->{$key})
+                             : "undef");
+                print OUT ",\n";
+            }
+            print OUT "  ";
+        }
+        print OUT "},\n";
     } else {
        print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
     }
@@ -2085,6 +2218,7 @@ print "DEFINES       =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n"
 #print "RANLIB        =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
 #                             "$config{cross_compile_prefix}ranlib" :
 #                             "$target{ranlib}", "\n";
+print "LDFLAGS       =$config{lflags} $target{lflags}\n";
 print "EX_LIBS       =$target{ex_libs} $config{ex_libs}\n";
 
 my %builders = (
@@ -2249,26 +2383,50 @@ sub add {
     sub { _add($separator, @_, @x) };
 }
 
+sub read_eval_file {
+    my $fname = shift;
+    my $content;
+    my @result;
+
+    open F, "< $fname" or die "Can't open '$fname': $!\n";
+    {
+        undef local $/;
+        $content = <F>;
+    }
+    close F;
+    {
+        local $@;
+
+        @result = ( eval $content );
+        warn $@ if $@;
+    }
+    return wantarray ? @result : $result[0];
+}
+
 # configuration reader, evaluates the input file as a perl script and expects
 # it to fill %targets with target configurations.  Those are then added to
 # %table.
 sub read_config {
     my $fname = shift;
-    open(CONFFILE, "< $fname")
-       or die "Can't open configuration file '$fname'!\n";
-    my $x = $/;
-    undef $/;
-    my $content = <CONFFILE>;
-    $/ = $x;
-    close(CONFFILE);
-    my %targets = ();
+    my %targets;
+
     {
        # Protect certain tables from tampering
-       local %table = %::table;
+       local %table = ();
 
-       eval $content;
-       warn $@ if $@;
+       %targets = read_eval_file($fname);
     }
+    my %preexisting = ();
+    foreach (sort keys %targets) {
+        $preexisting{$_} = 1 if $table{$_};
+    }
+    die <<"EOF",
+The following config targets from $fname
+shadow pre-existing config targets with the same name:
+EOF
+        map { "  $_\n" } sort keys %preexisting
+        if %preexisting;
+
 
     # For each target, check that it's configured with a hash table.
     foreach (keys %targets) {
@@ -2458,6 +2616,32 @@ sub run_dofile
     rename("$out.new", $out) || die "Can't rename $out.new, $!";
 }
 
+sub compiler_predefined {
+    state %predefined;
+    my $default_compiler = shift;
+
+    return () if $^O eq 'VMS';
+
+    die 'compiler_predefines called without a default compiler'
+        unless $default_compiler;
+
+    if (! $predefined{$default_compiler}) {
+        my $cc = "$config{cross_compile_prefix}$default_compiler";
+
+        $predefined{$default_compiler} = {};
+
+        # collect compiler pre-defines from gcc or gcc-alike...
+        open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
+        while (my $l = <PIPE>) {
+            $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
+            $predefined{$default_compiler}->{$1} = $2 // '';
+        }
+        close(PIPE);
+    }
+
+    return %{$predefined{$default_compiler}};
+}
+
 sub which
 {
     my ($name)=@_;
@@ -2479,6 +2663,19 @@ sub which
     }
 }
 
+sub env
+{
+    my $name = shift;
+
+    # Note that if $ENV{$name} doesn't exist or is undefined,
+    # $config{perlenv}->{$name} will be created with the value
+    # undef.  This is intentional.
+
+    $config{perlenv}->{$name} = $ENV{$name}
+        if ! exists $config{perlenv}->{$name};
+    return $config{perlenv}->{$name};
+}
+
 # Configuration printer ##############################################
 
 sub print_table_entry
@@ -2587,7 +2784,7 @@ sub isabsolute {
     # On non-platforms, we just use file_name_is_absolute().
     return file_name_is_absolute($file) unless $^O eq "VMS";
 
-    # If the file spec includes a device or a directpry spec,
+    # If the file spec includes a device or a directory spec,
     # file_name_is_absolute() is perfectly safe.
     return file_name_is_absolute($file) if $file =~ m|[:\[]|;