X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=Configure;h=3c40a0e25e16de41d7424a93fe3fb1597de91319;hp=1510818bcc495a1e79d16d23298e27147cd7d774;hb=604e591ed75eff9296c21ee5fe93f3e9ec246094;hpb=d42d0a4dc7925e3ea398821028a254c94665d733 diff --git a/Configure b/Configure index 1510818bcc..3c40a0e25e 100755 --- a/Configure +++ b/Configure @@ -1,6 +1,6 @@ #! /usr/bin/env perl # -*- mode: perl; -*- -# Copyright 2016-2017 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- ...] [enable- ...] [-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- ...] [enable- ...] [-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,7 @@ 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}); - - 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}; + $config{perlenv} = $configdata::config{perlenv} // {}; } else { die "Insufficient data to reconfigure, please do a normal configuration\n"; } @@ -279,13 +264,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 +278,29 @@ if (defined $ENV{$local_config_envname}) { } } - -print "Configuring OpenSSL version $config{version} ($config{version_num})\n"; +# Save away perl command information +$config{perl_cmd} = $^X; +$config{perl_version} = $Config{version}; +$config{perl_archname} = $Config{archname}; $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", "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", - "cms", "ts", "srp", "cmac", "ct", "async", "kdf" + "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store" ]; # test/ subdirectories to build $config{tdirs} = [ "ossl_shim" ]; @@ -353,6 +335,7 @@ my @disablables = ( "ct", "deprecated", "des", + "devcryptoeng", "dgram", "dh", "dsa", @@ -399,6 +382,8 @@ my @disablables = ( "seed", "shared", "siphash", + "sm3", + "sm4", "sock", "srp", "srtp", @@ -410,9 +395,10 @@ my @disablables = ( "tests", "threads", "tls", + "tls13downgrade", "ts", "ubsan", - "ui", + "ui-console", "unit-test", "whirlpool", "weak-ssl-ciphers", @@ -422,22 +408,23 @@ 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): our %disabled = ( # "what" => "comment" - "aria" => "default", "asan" => "default", "crypto-mdebug" => "default", "crypto-mdebug-backtrace" => "default", + "devcryptoeng" => "default", "ec_nistp_64_gcc_128" => "default", "egd" => "default", "external-tests" => "default", @@ -452,8 +439,7 @@ our %disabled = ( # "what" => "comment" "ssl3" => "default", "ssl3-method" => "default", "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", @@ -477,31 +463,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 @@ -510,13 +475,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" ], @@ -546,27 +512,106 @@ while ((my $first, my $second) = (shift @list, shift @list)) { # To remove something from %disabled, use "enable-foo". # For symmetry, "disable-foo" is a synonym for "no-foo". -my $no_sse2=0; - &usage if ($#ARGV < 0); -my $user_cflags=""; -my @user_defines=(); +# For the "make variables" CINCLUDES and CDEFINES, we support lists with +# platform specific list separators. Users from those platforms should +# recognise those separators from how you set up the PATH to find executables. +# The default is the Unix like separator, :, but as an exception, we also +# support the space as separator. +my $list_separator_re = + { VMS => qr/(? qr/(? {$^O} // qr/(? undef, + ARFLAGS => [], + AS => undef, + ASFLAGS => [], + CC => undef, + CFLAGS => [], + CXX => undef, + CXXFLAGS => [], + CPP => undef, + CPPFLAGS => [], # -D, -I, -Wp, + CPPDEFINES => [], # Alternative for -D + CPPINCLUDES => [], # Alternative for -I + CROSS_COMPILE => undef, + HASHBANGPERL=> undef, + LD => undef, + LDFLAGS => [], # -L, -Wl, + LDLIBS => [], # -l + MT => undef, + MTFLAGS => [], + RANLIB => undef, + RC => undef, + RCFLAGS => [], + RM => undef, + ); +# Info about what "make variables" may be prefixed with the cross compiler +# prefix. This should NEVER mention any such variable with a list for value. +my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC ); +# The same but for flags given as Configure options. These are *additional* +# input, as opposed to the VAR=string option that override the corresponding +# config target attributes +my %useradd = ( + CPPDEFINES => [], + CPPINCLUDES => [], + CPPFLAGS => [], + CFLAGS => [], + CXXFLAGS => [], + LDFLAGS => [], + LDLIBS => [], + ); + +my %user_synonyms = ( + HASHBANGPERL=> 'PERL', + RC => 'WINDRES', + ); +my %user_to_target = ( + # If not given here, the value is the lc of the key + CPPDEFINES => 'defines', + CPPINCLUDES => 'includes', + CROSS_COMPILE => 'cross_compile_prefix', + LDFLAGS => 'lflags', + LDLIBS => 'ex_libs', + ); + $config{openssl_api_defines}=[]; $config{openssl_algorithm_defines}=[]; $config{openssl_thread_defines}=[]; $config{openssl_sys_defines}=[]; $config{openssl_other_defines}=[]; -my $libs=""; -my $target=""; $config{options}=""; $config{build_type} = "release"; +my $target=""; 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; + # Every time a variable is given as a configuration argument, + # it acts as a reset if the variable. + if (exists $user{$1}) + { + $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef; + } + if (exists $useradd{$1}) + { + $useradd{$1} = []; + } + 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. @@ -684,7 +729,7 @@ while (@argvcopy) { $config{processor}=386; } elsif (/^fips$/) { - $config{fips}=1; + die "FIPS mode not supported\n"; } elsif (/^rsaref$/) { @@ -694,8 +739,7 @@ while (@argvcopy) } elsif (/^nofipscanistercheck$/) { - $config{fips} = 1; - $nofipscanistercheck = 1; + die "FIPS mode not supported\n"; } elsif (/^[-+]/) { @@ -733,25 +777,34 @@ while (@argvcopy) { $withargs{fuzzer_include}=$1; } - elsif (/^--with-fipslibdir=(.*)$/) - { - $config{fipslibdir}="$1/"; - } - elsif (/^--with-baseaddr=(.*)$/) + elsif (/^--with-rand-seed=(.*)$/) { - $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; + $user{CROSS_COMPILE}=$1; } elsif (/^--config=(.*)$/) { read_config $1; } - elsif (/^-[lL](.*)$/ or /^-Wl,/) + elsif (/^-L(.*)$/) + { + push @{$useradd{LDFLAGS}}, $_; + } + elsif (/^-l(.*)$/ or /^-Wl,/) { - $libs.=$_." "; + push @{$useradd{LDLIBS}}, $_; + } + elsif (/^-framework$/) + { + push @{$useradd{LDLIBS}}, $_, shift(@argvcopy); } elsif (/^-rpath$/ or /^-R$/) # -rpath is the OSF1 rpath flag @@ -759,11 +812,11 @@ while (@argvcopy) { my $rpath = shift(@argvcopy) || ""; $rpath .= " " if $rpath ne ""; - $libs.=$_." ".$rpath; + push @{$useradd{LDFLAGS}}, $_, $rpath; } elsif (/^-static$/) { - $libs.=$_." "; + push @{$useradd{LDFLAGS}}, $_; $disabled{"dso"} = "forced"; $disabled{"pic"} = "forced"; $disabled{"shared"} = "forced"; @@ -771,12 +824,21 @@ while (@argvcopy) } elsif (/^-D(.*)$/) { - push @user_defines, $1; + push @{$useradd{CPPDEFINES}}, $1; + } + elsif (/^-I(.*)$/) + { + push @{$useradd{CPPINCLUDES}}, $1; + } + elsif (/^-Wp,$/) + { + push @{$useradd{CPPFLAGS}}, $1; } else # common if (/^[-+]/), just pass down... { $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei; - $user_cflags.=" ".$_; + push @{$useradd{CFLAGS}}, $_; + push @{$useradd{CXXFLAGS}}, $_; } } else @@ -786,7 +848,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,22 +875,26 @@ while (@argvcopy) } } -if ($libs =~ /(^|\s)-Wl,-rpath,/ +foreach (keys %user) { + my $value = env($_); + $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef; + + if (defined $value) { + if (ref $user{$_} eq 'ARRAY') { + $user{$_} = [ split /$list_separator_re/, $value ]; + } elsif (!defined $user{$_}) { + $user{$_} = $value; + } + } +} + +if (grep { $_ =~ /(^|\s)-Wl,-rpath,/ } ($user{LDLIBS} ? @{$user{LDLIBS}} : ()) && !$disabled{shared} && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) { die "***** Cannot simultaneously use -rpath, shared libraries, and\n", "***** any of asan, msan or ubsan\n"; } -if ($config{fips}) - { - delete $disabled{"shared"} if ($disabled{"shared"} =~ /^default/); - } -else - { - @{$config{dirs}} = grep !/^fips$/, @{$config{dirs}}; - } - my @tocheckfor = (keys %disabled); while (@tocheckfor) { my %new_tocheckfor = (); @@ -869,76 +935,25 @@ if ($target eq "HASH") { exit 0; } +print "Configuring OpenSSL version $config{version} ($config{version_num}) "; +print "for $target\n"; + +if (scalar(@seed_sources) == 0) { + print "Using os-specific 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; + # Backward compatibility? if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; } -foreach (sort (keys %disabled)) - { - $config{options} .= " no-$_"; - - printf " no-%-12s %-10s", $_, "[$disabled{$_}]"; - - if (/^dso$/) - { } - elsif (/^threads$/) - { } - elsif (/^shared$/) - { } - elsif (/^pic$/) - { } - elsif (/^zlib$/) - { } - elsif (/^dynamic-engine$/) - { } - elsif (/^makedepend$/) - { } - elsif (/^zlib-dynamic$/) - { } - elsif (/^sse2$/) - { $no_sse2 = 1; } - elsif (/^engine$/) - { - @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}}; - @{$config{sdirs}} = grep !/^engine$/, @{$config{sdirs}}; - push @{$config{openssl_other_defines}}, "OPENSSL_NO_ENGINE"; - print " OPENSSL_NO_ENGINE (skip engines)"; - } - else - { - my ($WHAT, $what); - - ($WHAT = $what = $_) =~ tr/[\-a-z]/[_A-Z]/; - - # Fix up C macro end names - $WHAT = "RMD160" if $what eq "ripemd"; - - # fix-up crypto/directory name(s) - $what = "ripemd" if $what eq "rmd160"; - $what = "whrlpool" if $what eq "whirlpool"; - - if ($what ne "async" && $what ne "err" - && grep { $_ eq $what } @{$config{sdirs}}) - { - push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$WHAT"; - @{$config{sdirs}} = grep { $_ ne $what} @{$config{sdirs}}; - - print " OPENSSL_NO_$WHAT (skip dir)"; - } - else - { - push @{$config{openssl_other_defines}}, "OPENSSL_NO_$WHAT"; - print " OPENSSL_NO_$WHAT"; - - if (/^err$/) { push @user_defines, "OPENSSL_NO_ERR"; } - } - } - - 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) { @@ -954,58 +969,157 @@ 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 ); -$target{cxxflags}=$target{cflags} unless defined $target{cxxflags}; +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{$_}; + } +} + +$target{cxxflags}//=$target{cflags} if $target{cxx}; $target{exe_extension}=""; $target{exe_extension}=".exe" if ($config{target} eq "DJGPP" || $config{target} =~ /^(?:Cygwin|mingw)/); $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'} - if $config{cross_compile_prefix} eq ""; - # Allow overriding the names of some tools. USE WITH CARE # Note: only Unix cares about HASHBANGPERL... that explains # 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} || - (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{rc} = - $ENV{'RC'} || $ENV{'WINDRES'} || $target{rc} || "windres"; +foreach (keys %user) { + my $target_key = $user_to_target{$_} // lc $_; + my $ref_type = ref $user{$_}; + + # Temporary function. Takes an intended ref type (empty string or "ARRAY") + # and a value that's to be coerced into that type. + my $mkvalue = sub { + my $type = shift; + my $value = shift; + my $undef_p = shift; + + die "Too many arguments for \$mkvalue" if @_; + + while (ref $value eq 'CODE') { + $value = $value->(); + } + + if ($type eq 'ARRAY') { + return undef unless defined $value; + return undef if ref $value ne 'ARRAY' && !$value; + return undef if ref $value eq 'ARRAY' && !@$value; + return [ $value ] unless ref $value eq 'ARRAY'; + } + return undef unless $value; + return $value; + }; + + $config{$target_key} = + $mkvalue->($ref_type, $user{$_}) + || $mkvalue->($ref_type, $target{$target_key}); + delete $config{$target_key} unless defined $config{$target_key}; +} +$config{plib_lflags} = [ $target{plib_lflags} ]; # Allow overriding the build file name -$target{build_file} = $ENV{BUILDFILE} || $target{build_file} || "Makefile"; - -# Cache information necessary for reconfiguration -$config{cc} = $target{cc}; -$config{cxx} = $target{cxx}; -$config{build_file} = $target{build_file}; - -# For cflags, lflags, plib_lflags, ex_libs and defines, add the debug_ -# or release_ attributes. -# Do it in such a way that no spurious space is appended (hence the grep). -$config{defines} = []; -$config{cflags} = ""; -$config{cxxflags} = ""; -$config{ex_libs} = ""; -$config{shared_ldflag} = ""; +$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile"; + +my %disabled_info = (); # For configdata.pm +foreach my $what (sort keys %disabled) { + $config{options} .= " no-$what"; + + if (!grep { $what eq $_ } ( 'dso', 'threads', 'shared', 'pic', + 'dynamic-engine', 'makedepend', + 'zlib-dynamic', 'zlib', 'sse2' )) { + (my $WHAT = uc $what) =~ s|-|_|g; + + # Fix up C macro end names + $WHAT = "RMD160" if $what eq "ripemd"; + + # fix-up crypto/directory name(s) + $what = "ripemd" if $what eq "rmd160"; + $what = "whrlpool" if $what eq "whirlpool"; + + my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT"; + + if ((grep { $what eq $_ } @{$config{sdirs}}) + && $what ne 'async' && $what ne 'err') { + @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}}; + $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ]; + + if ($what ne 'engine') { + push @{$config{openssl_algorithm_defines}}, $macro; + } else { + @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}}; + push @{$disabled_info{engine}->{skipped}}, catdir('engines'); + push @{$config{openssl_other_defines}}, $macro; + } + } else { + push @{$config{openssl_other_defines}}, $macro; + } + + } +} # Make sure build_scheme is consistent. $target{build_scheme} = [ $target{build_scheme} ] @@ -1014,24 +1128,45 @@ $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) +if ($target =~ /^mingw/ && `$config{cc} --target-help 2>&1` =~ m/-mno-cygwin/m) { - $config{cflags} .= " -mno-cygwin"; - $config{shared_ldflag} .= " -mno-cygwin"; + push @{$config{cflags}}, "-mno-cygwin"; + push @{$config{cxxflags}}, "-mno-cygwin" if $config{cxx}; + push @{$config{shared_ldflag}}, "-mno-cygwin"; } -if ($target =~ /linux.*-mips/ && !$disabled{asm} && $user_cflags !~ /-m(ips|arch=)/) { +if ($target =~ /linux.*-mips/ && !$disabled{asm} + && !grep { $_ !~ /-m(ips|arch=)/ } (@{$user{CFLAGS}}, + @{$useradd{CFLAGS}})) { # minimally required architecture flags for assembly modules - $config{cflags}="-mips2 $config{cflags}" if ($target =~ /mips32/); - $config{cflags}="-mips3 $config{cflags}" if ($target =~ /mips64/); + my $value; + $value = '-mips2' if ($target =~ /mips32/); + $value = '-mips3' if ($target =~ /mips64/); + unshift @{$config{cflags}}, $value; + unshift @{$config{cxxflags}}, $value if $config{cxx}; } -my $no_shared_warn=0; -my $no_user_cflags=0; -my $no_user_defines=0; - # The DSO code currently always implements all functions so that no # applications will have to worry about that from a compilation point # of view. However, the "method"s may return zero unless that platform @@ -1055,17 +1190,6 @@ 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}}; - } - } - # If threads aren't disabled, check how possible they are unless ($disabled{threads}) { if ($auto_threads) { @@ -1082,7 +1206,8 @@ unless ($disabled{threads}) { # system-dependent compiler options that are necessary. We # can't truly check that the given options are correct, but # we expect the user to know what [s]He is doing. - if ($no_user_cflags && $no_user_defines) { + if (!@{$user{CFLAGS}} && !@{$useradd{CFLAGS}} + && !@{$user{CPPDEFINES}} && !@{$useradd{CPPDEFINES}}) { die "You asked for multi-threading support, but didn't\n" ,"provide any system-specific compiler options\n"; } @@ -1093,9 +1218,7 @@ unless ($disabled{threads}) { # If threads still aren't disabled, add a C macro to ensure the source # code knows about it. Any other flag is taken care of by the configs. unless($disabled{threads}) { - foreach (("defines", "openssl_thread_defines")) { - push @{$config{$_}}, "OPENSSL_THREADS"; - } + push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS"; } # With "deprecated" disable all deprecated features. @@ -1103,11 +1226,11 @@ if (defined($disabled{"deprecated"})) { $config{api} = $maxapi; } +my $no_shared_warn=0; 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"; @@ -1122,22 +1245,27 @@ if ($disabled{"dynamic-engine"}) { } unless ($disabled{asan}) { - $config{cflags} .= "-fsanitize=address "; + push @{$config{cflags}}, "-fsanitize=address"; + push @{$config{cxxflags}}, "-fsanitize=address" if $config{cxx}; } unless ($disabled{ubsan}) { # -DPEDANTIC or -fnosanitize=alignment may also be required on some # platforms. - $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all "; + push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"; + push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all" + if $config{cxx}; } unless ($disabled{msan}) { - $config{cflags} .= "-fsanitize=memory "; + push @{$config{cflags}}, "-fsanitize=memory"; + push @{$config{cxxflags}}, "-fsanitize=memory" if $config{cxx}; } unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) { - $config{cflags} .= "-fno-omit-frame-pointer -g "; + push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g"; + push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{cxx}; } # # Platform fix-ups @@ -1146,8 +1274,14 @@ 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_cppflag + shared_defines shared_includes shared_ldflag + dso_cflags dso_cxxflags dso_cppflags + dso_defines dso_includes dso_lflags)) + { + delete $config{$_}; + $target{$_} = ""; + } } else { @@ -1161,20 +1295,18 @@ if ($target{sys_id} ne "") unless ($disabled{asm}) { $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386"); + push @{$config{defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c"); + $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m})); # bn-586 is the only one implementing bn_*_part_words push @{$config{defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/); - push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/); + push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/); push @{$config{defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/); 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/); @@ -1197,7 +1329,7 @@ unless ($disabled{asm}) { push @{$config{defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//); # aes-xts.fake indicates presence of AES_xts_[en|de]crypt... push @{$config{defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//); - $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2); + $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2}); push @{$config{defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/); push @{$config{defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/); } @@ -1214,6 +1346,9 @@ unless ($disabled{asm}) { if ($target{ec_asm_src} =~ /ecp_nistz256/) { push @{$config{defines}}, "ECP_NISTZ256_ASM"; } + if ($target{ec_asm_src} =~ /x25519/) { + push @{$config{defines}}, "X25519_ASM"; + } if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) { push @{$config{defines}}, "PADLOCK_ASM"; } @@ -1222,33 +1357,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 ( ) { - # Find the version number and save the major. - m|(?:.*)\b(\d+)\.\d+\.\d+\b(?:.*)|; - my $compiler_major = $1; +my %predefined = compiler_predefined($config{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)$config{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; @@ -1276,9 +1405,12 @@ die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set # Hack cflags for better warnings (dev option) ####################### -# "Stringify" the C flags string. This permits it to be made part of a string -# and works as well on command lines. -$config{cflags} =~ s/([\\\"])/\\$1/g; +# "Stringify" the C and C++ flags string. This permits it to be made part of +# a string and works as well on command lines. +$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } + @{$config{cflags}} ]; +$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } + @{$config{cxxflags}} ] if $config{cxx}; if (defined($config{api})) { $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; @@ -1286,20 +1418,36 @@ if (defined($config{api})) { push @{$config{defines}}, $apiflag; } +if (defined($predefined{__clang__}) && !$disabled{asm}) { + push @{$config{cflags}}, "-Qunused-arguments"; + push @{$config{cxxflags}}, "-Qunused-arguments" if $config{cxx}; +} + 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|$)/) + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{cxx} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); } - if ($ecc eq "clang") + if (defined($predefined{__clang__})) { foreach $wopt (split /\s+/, $clang_devteam_warn) { - $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/) + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{cxx} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); } } } @@ -1308,21 +1456,18 @@ unless ($disabled{"crypto-mdebug-backtrace"}) { foreach my $wopt (split /\s+/, $memleak_devteam_backtrace) { - $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/) + push @{$config{cflags}}, $wopt + unless grep { $_ eq $wopt } @{$config{cflags}}; + push @{$config{cxxflags}}, $wopt + if ($config{cxx} + && !grep { $_ eq $wopt } @{$config{cxxflags}}); } if ($target =~ /^BSD-/) { - $config{ex_libs} .= " -lexecinfo"; + push @{$config{ex_libs}}, "-lexecinfo"; } } -if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; $config{cxxflags}="$config{cxxflags}$user_cflags";} -else { $no_user_cflags=1; } -if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; } -else { $no_user_defines=1; } - -# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON - unless ($disabled{afalgeng}) { $config{afalgeng}=""; if ($target =~ m/^linux/) { @@ -1347,12 +1492,29 @@ unless ($disabled{afalgeng}) { push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng}); +# Finish up %config by appending things the user gave us on the command line +# apart from "make variables" +foreach (keys %useradd) { + # The must all be lists, so we assert that here + die "internal error: \$useradd{$_} isn't an ARRAY\n" + unless ref $useradd{$_} eq 'ARRAY'; + + my $target_key = $user_to_target{$_} // lc $_; + + if (defined $config{$target_key}) { + push @{$config{$target_key}}, @{$useradd{$_}}; + } else { + $config{$target_key} = [ @{$useradd{$_}} ]; + } +} + +# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON + # If we use the unified build, collect information from build.info files 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 { @@ -1396,7 +1558,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') { @@ -1404,7 +1566,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; @@ -1449,6 +1611,7 @@ if ($builder eq "unified") { $config{build_infos} = [ ]; + my %ordinals = (); foreach (@build_infos) { my $sourced = catdir($srcdir, $_->[0]); my $buildd = catdir($blddir, $_->[0]); @@ -1470,7 +1633,6 @@ if ($builder eq "unified") { my @intermediates = (); my @rawlines = (); - my %ordinals = (); my %sources = (); my %shared_sources = (); my %includes = (); @@ -1480,8 +1642,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, @@ -1742,33 +1906,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) { @@ -1782,7 +1937,7 @@ EOF # If it isn't in the source tree, we assume it's generated # in the build tree - if (! -f $s) { + if (! -f $s || $generate{$_}) { $s = cleanfile($buildd, $_, $blddir); } # We recognise C++, C and asm files @@ -1810,17 +1965,30 @@ EOF # If it isn't in the source tree, we assume it's generated # in the build tree - if (! -f $s) { + if (! -f $s || $generate{$_}) { $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"; } @@ -1879,13 +2047,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}}; - } } } @@ -1912,6 +2073,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")) { @@ -1927,8 +2137,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) { @@ -1954,8 +2165,11 @@ foreach (grep /_(asm|aux)_src$/, keys %target) { # Write down our configuration where it fits ######################### +print "Creating configdata.pm\n"; open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n"; print OUT <<"EOF"; +#! $config{hashbangperl} + package configdata; use strict; @@ -1973,6 +2187,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" } @@ -2074,28 +2304,298 @@ if ($builder eq "unified") { EOF } -print OUT "1;\n"; -close(OUT); +print OUT + "# The following data is only used when this files is use as a script\n"; +print OUT "my \%makevars = (\n"; +foreach (sort keys %user) { + print OUT ' ',$_,' ' x (20 - length $_),'=> ', + "'",$user_to_target{$_} || lc $_,"',\n"; +} +print OUT ");\n"; +print OUT "my \%disabled_info = (\n"; +foreach my $what (sort keys %disabled_info) { + print OUT " '$what' => {\n"; + foreach my $info (sort keys %{$disabled_info{$what}}) { + if (ref $disabled_info{$what}->{$info} eq 'ARRAY') { + print OUT " $info => [ ", + join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}), + " ],\n"; + } else { + print OUT " $info => '", $disabled_info{$what}->{$info}, + "',\n"; + } + } + print OUT " },\n"; +} +print OUT ");\n"; +print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n"; +print OUT << 'EOF'; +# If run directly, we can give some answers, and even reconfigure +unless (caller) { + use Getopt::Long; + use File::Spec::Functions; + use File::Basename; + use Pod::Usage; + + my $here = dirname($0); + + my $dump = undef; + my $cmdline = undef; + my $options = undef; + my $target = undef; + my $envvars = undef; + my $makevars = undef; + my $buildparams = undef; + my $reconf = undef; + my $verbose = undef; + my $help = undef; + my $man = undef; + GetOptions('dump|d' => \$dump, + 'command-line|c' => \$cmdline, + 'options|o' => \$options, + 'target|t' => \$target, + 'environment|e' => \$envvars, + 'make-variables|m' => \$makevars, + 'build-parameters|b' => \$buildparams, + 'reconfigure|reconf|r' => \$reconf, + 'verbose|v' => \$verbose, + 'help' => \$help, + 'man' => \$man) + or die "Errors in command line arguments\n"; + + unless ($dump || $cmdline || $options || $target || $envvars || $makevars + || $buildparams || $reconf || $verbose || $help || $man) { + print STDERR <<"_____"; +You must give at least one option. +For more information, do '$0 --help' +_____ + exit(2); + } + + if ($help) { + pod2usage(-exitval => 0, + -verbose => 1); + } + if ($man) { + pod2usage(-exitval => 0, + -verbose => 2); + } + if ($dump || $cmdline) { + print "\nCommand line (with current working directory = $here):\n\n"; + print ' ',join(' ', + $config{perl}, + catfile($config{sourcedir}, 'Configure'), + @{$config{perlargv}}), "\n"; + print "\nPerl information:\n\n"; + print ' ',$config{perl_cmd},"\n"; + print ' ',$config{perl_version},' for ',$config{perl_archname},"\n"; + } + if ($dump || $options) { + my $longest = 0; + my $longest2 = 0; + foreach my $what (@disablables) { + $longest = length($what) if $longest < length($what); + $longest2 = length($disabled{$what}) + if $disabled{$what} && $longest2 < length($disabled{$what}); + } + print "\nEnabled features:\n\n"; + foreach my $what (@disablables) { + print " $what\n" unless $disabled{$what}; + } + print "\nDisabled features:\n\n"; + foreach my $what (@disablables) { + if ($disabled{$what}) { + print " $what", ' ' x ($longest - length($what) + 1), + "[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1); + print $disabled_info{$what}->{macro} + if $disabled_info{$what}->{macro}; + print ' (skip ', + join(', ', @{$disabled_info{$what}->{skipped}}), + ')' + if $disabled_info{$what}->{skipped}; + print "\n"; + } + } + } + if ($dump || $target) { + print "\nConfig target attributes:\n\n"; + foreach (sort keys %target) { + next if $_ =~ m|^_| || $_ eq 'template'; + my $quotify = sub { + map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_; + }; + print ' ', $_, ' => '; + if (ref($target{$_}) eq "ARRAY") { + print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; + } else { + print $quotify->($target{$_}), ",\n" + } + } + } + if ($dump || $envvars) { + print "\nRecorded environment:\n\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n"; + } + } + if ($dump || $makevars) { + print "\nMakevars:\n\n"; + foreach my $var (sort keys %makevars) { + my $prefix = ''; + $prefix = $config{cross_compile_prefix} + if grep { $var eq $_ } @user_crossable; + print ' ',$var,' ' x (16 - length $var),'= ', + (ref $config{$makevars{$var}} eq 'ARRAY' + ? join(' ', @{$config{$makevars{$var}}}) + : $prefix.$config{$makevars{$var}}), + "\n" + if defined $config{$makevars{$var}}; + } + + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + my $buildfile = canonpath(catdir(@buildfile)); + print <<"_____"; + +NOTE: These variables only represent the configuration view. The build file +template may have processed these variables further, please have a look at the +build file for more exact data: + $buildfile +_____ + } + if ($dump || $buildparams) { + my @buildfile = ($config{builddir}, $config{build_file}); + unshift @buildfile, $here + unless file_name_is_absolute($config{builddir}); + print "\nbuild file:\n\n"; + print " ", canonpath(catfile(@buildfile)),"\n"; + + print "\nbuild file templates:\n\n"; + foreach (@{$config{build_file_templates}}) { + my @tmpl = ($_); + unshift @tmpl, $here + unless file_name_is_absolute($config{sourcedir}); + print ' ',canonpath(catfile(@tmpl)),"\n"; + } + } + if ($reconf) { + if ($verbose) { + print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n"; + foreach (sort keys %{$config{perlenv}}) { + print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n"; + } + } + + chdir $here; + exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf'; + } +} + +1; + +__END__ + +=head1 NAME -print "\n"; -print "PROCESSOR =$config{processor}\n" if $config{processor}; -print "PERL =$config{perl}\n"; -print "PERLVERSION =$Config{version} for $Config{archname}\n"; -print "HASHBANGPERL =$config{hashbangperl}\n"; -print "CC =$config{cross_compile_prefix}$target{cc}\n"; -print "CFLAG =$target{cflags} $config{cflags}\n"; -print "CXX =$config{cross_compile_prefix}$target{cxx}\n" - if defined $target{cxx}; -print "CXXFLAG =$target{cxxflags} $config{cxxflags}\n" - if defined $target{cxx}; -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 "EX_LIBS =$target{ex_libs} $config{ex_libs}\n"; +configdata.pm - configuration data for OpenSSL builds + +=head1 SYNOPSIS + +Interactive: + + perl configdata.pm [options] + +As data bank module: + + use configdata; + +=head1 DESCRIPTION + +This module can be used in two modes, interactively and as a module containing +all the data recorded by OpenSSL's Configure script. + +When used interactively, simply run it as any perl script, with at least one +option, and you will get the information you ask for. See L below. + +When loaded as a module, you get a few databanks with useful information to +perform build related tasks. The databanks are: + + %config Configured things. + %target The OpenSSL config target with all inheritances + resolved. + %disabled The features that are disabled. + @disablables The list of features that can be disabled. + %withargs All data given through --with-THING options. + %unified_info All information that was computed from the build.info + files. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Print a brief help message and exit. + +=item B<--man> + +Print the manual page and exit. + +=item B<--dump> | B<-d> + +Print all relevant configuration data. This is equivalent to B<--command-line> +B<--options> B<--target> B<--environment> B<--make-variables> +B<--build-parameters>. + +=item B<--command-line> | B<-c> + +Print the current configuration command line. + +=item B<--options> | B<-o> + +Print the features, both enabled and disabled, and display defined macro and +skipped directories where applicable. + +=item B<--target> | B<-t> + +Print the config attributes for this config target. + +=item B<--environment> | B<-e> + +Print the environment variables and their values at the time of configuration. + +=item B<--make-variables> | B<-m> + +Print the main make variables generated in the current configuration + +=item B<--build-parameters> | B<-b> + +Print the build parameters, i.e. build file and build file templates. + +=item B<--reconfigure> | B<--reconf> | B<-r> + +Redo the configuration. + +=item B<--verbose> | B<-v> + +Verbose output. + +=back + +=cut + +EOF +close(OUT); +if ($builder_platform eq 'unix') { + my $mode = (0755 & ~umask); + chmod $mode, 'configdata.pm' + or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!); +} my %builders = ( unified => sub { + print 'Creating ',$target{build_file},"\n"; run_dofile(catfile($blddir, $target{build_file}), @{$config{build_file_templates}}); }, @@ -2127,6 +2627,18 @@ safest course of action is to clean the source directory and redo this configuration. EOF +print <<"EOF"; + +********************************************************************** +*** *** +*** If you want to report a building issue, please include the *** +*** output from this command: *** +*** *** +*** perl configdata.pm --dump *** +*** *** +********************************************************************** +EOF + exit(0); ###################################################################### @@ -2256,26 +2768,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 = ; + } + 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 = ; - $/ = $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) { @@ -2465,6 +3001,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 = ) { + $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last; + $predefined{$default_compiler}->{$1} = $2 // ''; + } + close(PIPE); + } + + return %{$predefined{$default_compiler}}; +} + sub which { my ($name)=@_; @@ -2486,6 +3048,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 @@ -2499,9 +3074,12 @@ sub print_table_entry my @sequence = ( "sys_id", + "cpp", + "cppflags", + "defines", + "includes", "cc", "cflags", - "defines", "unistd", "ld", "lflags", @@ -2594,7 +3172,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|[:\[]|;