Configure: Read in extra information to help create shared libraries
[openssl.git] / Configure
index 4d74b432eb16c9863ba550c50f54cad50cb0c582..a5d5c84e024451c91a5033550862fc48a982b711 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -141,7 +141,6 @@ 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"
         . " -Wswitch-default"
         . " -Wno-parentheses-equality"
         . " -Wno-language-extension-token"
@@ -149,6 +148,7 @@ my $clang_devteam_warn = ""
         . " -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
@@ -211,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) {
@@ -223,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";
     }
@@ -280,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)) {
@@ -307,8 +296,8 @@ $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "
 # crypto/ subdirectories to build
 $config{sdirs} = [
     "objects",
-    "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",
-    "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "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",
@@ -394,6 +383,8 @@ my @disablables = (
     "seed",
     "shared",
     "siphash",
+    "sm3",
+    "sm4",
     "sock",
     "srp",
     "srtp",
@@ -476,31 +467,10 @@ my @disable_cascades = (
     sub { 0 == scalar grep { !$disabled{$_} } @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" ],
-
     "tls"              => [ @tls ],
     sub { 0 == scalar grep { !$disabled{$_} } @tls }
                        => [ "tls" ],
 
-    # SRP and HEARTBEATS require TLSEXT
-    "tlsext"           => [ "srp", "heartbeats" ],
-
     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
 
     # Without DSO, we can't load dynamic engines, so don't build them dynamic
@@ -570,6 +540,14 @@ 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.
@@ -793,7 +771,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.)
@@ -901,9 +879,48 @@ 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 ];
-%target = ( %{$table{DEFAULTS}}, %target );
 
 foreach my $feature (@{$target{disable}}) {
     if (exists $deprecated_disablables{$feature}) {
@@ -1001,7 +1018,7 @@ $target{dso_extension}=$target{shared_extension_simple};
     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
@@ -1009,19 +1026,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};
@@ -1185,8 +1202,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
        {
@@ -1257,33 +1277,20 @@ unless ($disabled{asm}) {
     }
 }
 
-my %predefined;
+my %predefined = compiler_predefined($target{cc});
 
-if ($^O ne "VMS") {
-    my $cc = "$config{cross_compile_prefix}$target{cc}";
-
-    # collect compiler pre-defines from gcc or gcc-alike...
-    open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
-    while (<PIPE>) {
-       m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
-       $predefined{$1} = $2 // "";
-    }
-    close(PIPE);
-
-    if (!$disabled{makedepend}) {
-       # We know that GNU C version 3 and up as well as all clang
-       # versions support dependency generation
-       if ($predefined{__GNUC__} >= 3) {
-           $config{makedepprog} = $cc;
-       } else {
-           $config{makedepprog} = which('makedepend');
-           $disabled{makedepend} = "unavailable" unless $config{makedepprog};
-       }
+if (!$disabled{makedepend}) {
+    # We know that GNU C version 3 and up as well as all clang
+    # versions support dependency generation
+    if ($predefined{__GNUC__} >= 3) {
+        $config{makedepprog} = "\$(CROSS_COMPILE)$target{cc}";
+    } else {
+        $config{makedepprog} = which('makedepend');
+        $disabled{makedepend} = "unavailable" unless $config{makedepprog};
     }
 }
 
 
-
 # Deal with bn_ops ###################################################
 
 $config{bn_ll}                 =0;
@@ -1321,11 +1328,18 @@ 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 gcc-alike"
-            unless defined($predefined{__GNUC__});
+       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|$)/)
@@ -1430,7 +1444,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') {
@@ -1438,7 +1452,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;
@@ -1779,7 +1793,7 @@ EOF
 
             # Additionally, we set up sharednames for libraries that don't
             # have any, as themselves.  Only for libraries that aren't
-            # explicitely static.
+            # explicitly static.
             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
                 if (!defined $unified_info{sharednames}->{$_}) {
                     $unified_info{sharednames}->{$_} = $_
@@ -1787,13 +1801,13 @@ EOF
             }
 
             # Check that we haven't defined any library as both shared and
-            # explicitely static.  That is forbidden.
+            # 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 explicitely static and shared:\n  ",
+            die "these libraries are both explicitly static and shared:\n  ",
                 join(" ", @doubles), "\n"
                 if @doubles;
         }
@@ -2021,6 +2035,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"
     }
@@ -2304,25 +2334,38 @@ 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);
     }
 
     # For each target, check that it's configured with a hash table.
@@ -2513,6 +2556,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)=@_;
@@ -2534,6 +2603,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