X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=Configure;h=86f68c7ca02c16c6cc2d5d7348804b07cc296f8f;hp=c5e318421d7d008066be64e464eee97fc0886cd1;hb=a00b9560f7ece1e51bd7a8dc6a7ffb7a3d20cf86;hpb=c91a0a8343a22b5e4dff45ecfdee2eae8ab8a504 diff --git a/Configure b/Configure index c5e318421d..86f68c7ca0 100755 --- a/Configure +++ b/Configure @@ -1,13 +1,21 @@ #! /usr/bin/env perl # -*- mode: perl; -*- +# Copyright 2016-2017 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 +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html ## Configure -- OpenSSL source tree configuration script require 5.10.0; use strict; +use Config; 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/; # see INSTALL for instructions. @@ -52,13 +60,30 @@ my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lx # zlib-dynamic Like "zlib", but the zlib library is expected to be a shared # library and will be loaded in run-time by the OpenSSL library. # sctp include SCTP support -# 386 generate 80386 code # enable-weak-ssl-ciphers # Enable weak ciphers that are disabled by default. This currently # only includes RC4 based ciphers. -# no-sse2 disables IA-32 SSE2 code, above option implies no-sse2 +# 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 # no- build without specified algorithm (rsa, idea, rc5, ...) # - + compiler options are passed through +# -static while -static is also a pass-through compiler option (and +# as such is limited to environments where it's actually +# meaningful), it triggers a number configuration options, +# namely no-dso, no-pic, no-shared and no-threads. It is +# argued that the only reason to produce statically linked +# binaries (and in context it means executables linked with +# -static flag, and not just executables linked with static +# libcrypto.a) is to eliminate dependency on specific run-time, +# a.k.a. libc version. The mentioned config options are meant +# to achieve just that. Unfortunately on Linux it's impossible +# to eliminate the dependency completely for openssl executable +# because of getaddrinfo and gethostbyname calls, which can +# invoke dynamically loadable library facility anyway to meet +# the lookup requests. For this reason on Linux statically +# linked openssl executable has rather debugging value than +# production quality. # # DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items # provided to stack calls. Generates unique stack functions for @@ -67,47 +92,63 @@ my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lx # RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h # Following are set automatically by this script # -# MD5_ASM use some extra md5 assember, -# SHA1_ASM use some extra sha1 assember, must define L_ENDIAN for x86 -# RMD160_ASM use some extra ripemd160 assember, +# MD5_ASM use some extra md5 assembler, +# SHA1_ASM use some extra sha1 assembler, must define L_ENDIAN for x86 +# RMD160_ASM use some extra ripemd160 assembler, # SHA256_ASM sha256_block is implemented in assembler # SHA512_ASM sha512_block is implemented in assembler -# AES_ASM ASE_[en|de]crypt is implemented in assembler +# AES_ASM AES_[en|de]crypt is implemented in assembler # Minimum warning options... any contributions to OpenSSL should at least get # past these. -my $gcc_devteam_warn = "-DPEDANTIC -DREF_DEBUG -DDEBUG_UNUSED -DBIO_DEBUG" - . " -pedantic" +# DEBUG_UNUSED enables __owur (warn unused result) checks. +# -DPEDANTIC complements -pedantic and is meant to mask code that +# is not strictly standard-compliant and/or implementation-specific, +# e.g. inline assembly, disregards to alignment requirements, such +# that -pedantic would complain about. Incidentally -DPEDANTIC has +# to be used even in sanitized builds, because sanitizer too is +# supposed to and does take notice of non-standard behaviour. Then +# -pedantic with pre-C9x compiler would also complain about 'long +# long' not being supported. As 64-bit algorithms are common now, +# it grew impossible to resolve this without sizeable additional +# code, so we just tell compiler to be pedantic about everything +# but 'long long' type. + +my $gcc_devteam_warn = "-DDEBUG_UNUSED" + . " -Wswitch" + . " -DPEDANTIC -pedantic -Wno-long-long" . " -Wall" - . " -Wno-long-long" . " -Wsign-compare" . " -Wmissing-prototypes" . " -Wshadow" . " -Wformat" . " -Wtype-limits" + . " -Wundef" . " -Werror" ; # These are used in addition to $gcc_devteam_warn when the compiler is clang. # TODO(openssl-team): fix problems and investigate if (at least) the # following warnings can also be enabled: -# -Wswitch-enum # -Wcast-align -# -Wunreachable-code +# -Wunreachable-code -- no, too ugly/compiler-specific # -Wlanguage-extension-token -- no, we use asm() # -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" + . " -Wno-parentheses-equality" . " -Wno-missing-field-initializers" . " -Wno-language-extension-token" . " -Wno-extended-offsetof" . " -Wconditional-uninitialized" . " -Wincompatible-pointer-types-discards-qualifiers" . " -Wmissing-variable-declarations" + . " -Wundef" ; # This adds backtrace information to the memory leak info. Is only used @@ -126,7 +167,7 @@ my $strict_warnings = 0; our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT"; # -# API compability name to version number mapping. +# API compatibility name to version number mapping. # my $maxapi = "1.1.0"; # API for "no-deprecated" builds my $apitable = { @@ -149,7 +190,7 @@ sub read_config; # resolve_config(target) # -# Resolves all the late evalutations, inheritances and so on for the +# Resolves all the late evaluations, inheritances and so on for the # chosen target and any target it inherits from. sub resolve_config; @@ -161,9 +202,53 @@ my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax my $blddir = catdir(absolutedir(".")); # catdir ensures local syntax my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); +my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR'; + $config{sourcedir} = abs2rel($srcdir); $config{builddir} = abs2rel($blddir); +# Collect reconfiguration information if needed +my @argvcopy=@ARGV; + +if (grep /^reconf(igure)?$/, @argvcopy) { + if (-f "./configdata.pm") { + my $file = "./configdata.pm"; + unless (my $return = do $file) { + die "couldn't parse $file: $@" if $@; + die "couldn't do $file: $!" unless defined $return; + die "couldn't run $file" unless $return; + } + + @argvcopy = defined($configdata::config{perlargv}) ? + @{$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}; + } else { + die "Insufficient data to reconfigure, please do a normal configuration\n"; + } +} + +$config{perlargv} = [ @argvcopy ]; + # Collect version numbers $config{version} = "unknown"; $config{version_num} = "unknown"; @@ -191,49 +276,62 @@ die "erroneous version information in opensslv.h: ", # Collect target configurations my $pattern = catfile(dirname($0), "Configurations", "*.conf"); -foreach (sort glob($pattern) ) { +foreach (sort glob($pattern)) { &read_config($_); } +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'); + } + + foreach (sort glob($pattern)) { + &read_config($_); + } +} + -print "Configuring OpenSSL version $config{version} (0x$config{version_num})\n"; +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", "tools" ]; +$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", + "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "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" ]; +# test/ subdirectories to build +$config{tdirs} = [ "ossl_shim" ]; # Known TLS and DTLS protocols -my @tls = qw(ssl3 tls1 tls1_1 tls1_2); +my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); my @dtls = qw(dtls1 dtls1_2); -# Explicitelly known options that are possible to disable. They can +# Explicitly known options that are possible to disable. They can # be regexps, and will be used like this: /^no-${option}$/ # For developers: keep it sorted alphabetically my @disablables = ( - "aes", "afalgeng", + "aria", + "asan", "asm", "async", "autoalginit", @@ -266,17 +364,19 @@ my @disablables = ( "egd", "engine", "err", + "external-tests", "filenames", + "fuzz-libfuzzer", + "fuzz-afl", + "gost", "heartbeats", - "hmac", "hw(-.+)?", "idea", "makedepend", "md2", "md4", - "md5", "mdc2", - "md[-_]ghost94", + "msan", "multiblock", "nextprotoneg", "ocb", @@ -290,16 +390,12 @@ my @disablables = ( "rc5", "rdrand", "rfc3779", - "rijndael", # Old AES name - "ripemd", "rmd160", - "rsa", "scrypt", - "sct", "sctp", "seed", - "sha", "shared", + "siphash", "sock", "srp", "srtp", @@ -308,9 +404,11 @@ my @disablables = ( "ssl-trace", "static-engine", "stdio", + "tests", "threads", "tls", "ts", + "ubsan", "ui", "unit-test", "whirlpool", @@ -324,29 +422,39 @@ foreach my $proto ((@tls, @dtls)) push(@disablables, "$proto-method"); } -my @deprecated_disablables = ( - "ssl2", +my %deprecated_disablables = ( + "ssl2" => undef, + "buf-freelists" => undef, + "ripemd" => "rmd160" ); # 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", "ec_nistp_64_gcc_128" => "default", "egd" => "default", + "external-tests" => "default", + "fuzz-libfuzzer" => "default", + "fuzz-afl" => "default", + "heartbeats" => "default", "md2" => "default", + "msan" => "default", "rc5" => "default", "sctp" => "default", - "shared" => "default", "ssl-trace" => "default", "ssl3" => "default", "ssl3-method" => "default", - "static-engine" => "default", + "ubsan" => "default", + #TODO(TLS1.3): Temporarily disabled while this is a WIP + "tls1_3" => "default", "unit-test" => "default", "weak-ssl-ciphers" => "default", "zlib" => "default", "zlib-dynamic" => "default", - "crypto-mdebug" => "default", - "heartbeats" => "default", ); # Note: => pair form used for aesthetics, not to truly make a hash table @@ -357,12 +465,14 @@ my @disable_cascades = ( "ssl" => [ "ssl3" ], "ssl3-method" => [ "ssl3" ], "zlib" => [ "zlib-dynamic" ], - "rijndael" => [ "aes" ], "des" => [ "mdc2" ], "ec" => [ "ecdsa", "ecdh" ], - "dgram" => [ "dtls" ], + "dgram" => [ "dtls", "sctp" ], + "sock" => [ "dgram" ], "dtls" => [ @dtls ], + 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" ], @@ -379,10 +489,12 @@ my @disable_cascades = ( sub { $disabled{rsa} && ($disabled{dsa} || $disabled{dh}) && ($disabled{ecdsa} || $disabled{ecdh}); } - => [ "tls1", "tls1_1", "tls1_2", + => [ "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" ], @@ -396,6 +508,17 @@ my @disable_cascades = ( "pic" => [ "shared" ], "shared" => [ "dynamic-engine" ], "engine" => [ "afalgeng" ], + + # no-autoalginit is only useful when building non-shared + "autoalginit" => [ "shared", "apps" ], + + "stdio" => [ "apps", "capieng" ], + "apps" => [ "tests" ], + "comp" => [ "zlib" ], + "ec" => [ "tls1_3" ], + sub { !$disabled{"unit-test"} } => [ "heartbeats" ], + + sub { !$disabled{"msan"} } => [ "asm" ], ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -420,17 +543,6 @@ 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 @generated_headers = ( - "include/openssl/opensslconf.h", - "crypto/include/internal/bn_conf.h", - "crypto/include/internal/dso_conf.h" - ); - -my @generated_by_make_headers = ( - "crypto/buildinf.h" - ); - - my $no_sse2=0; &usage if ($#ARGV < 0); @@ -447,64 +559,11 @@ my $target=""; $config{options}=""; $config{build_type} = "release"; -my $classic = 0; - -my @argvcopy=@ARGV; - -if (grep /^reconf(igure)?$/, @argvcopy) { - if (-f "./configdata.pm") { - my $file = "./configdata.pm"; - unless (my $return = do $file) { - die "couldn't parse $file: $@" if $@; - die "couldn't do $file: $!" unless defined $return; - die "couldn't run $file" unless $return; - } - - @argvcopy = defined($configdata::config{perlargv}) ? - @{$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{CROSS_COMPILE} = $configdata::config{cc} - if defined($configdata::config{cc}); - - 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}; - } elsif (open IN, ") { - s|\R$||; - if (/^CONFIGURE_ARGS=\s*(.*)\s*/) { - # Older form, we split the string and hope for the best - @argvcopy = split /\s+/, $_; - die "Incorrect data to reconfigure, please do a normal configuration\n" - if (grep(/^reconf/,@argvcopy)); - } elsif (/^CROSS_COMPILE=\s*(.*)/) { - $ENV{CROSS_COMPILE}=$1; - } elsif (/^CC=\s*(?:\$\(CROSS_COMPILE\))?(.*?)$/) { - $ENV{CC}=$1; - } - } - # - # END OF TEMPORARY SECTION - # - } else { - die "Insufficient data to reconfigure, please do a normal configuration\n"; - } -} - -$config{perlargv} = [ @argvcopy ]; - my %unsupported_options = (); my %deprecated_options = (); -foreach (@argvcopy) +while (@argvcopy) { + $_ = shift @argvcopy; # 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. @@ -522,21 +581,17 @@ foreach (@argvcopy) s /^zlib-dynamic$/enable-zlib-dynamic/; if (/^(no|disable|enable)-(.+)$/) - { - my $word = $2; - if (grep { $word =~ /^${_}$/ } @deprecated_disablables) - { - $deprecated_options{$_} = 1; - next; - } - elsif (!grep { $word =~ /^${_}$/ } @disablables) - { - $unsupported_options{$_} = 1; - next; - } - } - if (/^no-(.+)$/ || /^disable-(.+)$/) - { + { + my $word = $2; + if (!exists $deprecated_disablables{$word} + && !grep { $word =~ /^${_}$/ } @disablables) + { + $unsupported_options{$_} = 1; + next; + } + } + if (/^no-(.+)$/ || /^disable-(.+)$/) + { foreach my $proto ((@tls, @dtls)) { if ($1 eq "$proto-method") @@ -551,6 +606,7 @@ foreach (@argvcopy) { $disabled{$proto} = "option(dtls)"; } + $disabled{"dtls"} = "option(dtls)"; } elsif ($1 eq "ssl") { @@ -574,6 +630,14 @@ foreach (@argvcopy) { $disabled{"dynamic-engine"} = "option"; } + elsif (exists $deprecated_disablables{$1}) + { + $deprecated_options{$_} = 1; + if (defined $deprecated_disablables{$1}) + { + $disabled{$deprecated_disablables{$1}} = "option"; + } + } else { $disabled{$1} = "option"; @@ -617,7 +681,7 @@ foreach (@argvcopy) { $config{processor}=386; } elsif (/^fips$/) { - $config{fips}=1; + die "FIPS mode not supported\n"; } elsif (/^rsaref$/) { @@ -627,16 +691,11 @@ foreach (@argvcopy) } elsif (/^nofipscanistercheck$/) { - $config{fips} = 1; - $nofipscanistercheck = 1; + die "FIPS mode not supported\n"; } elsif (/^[-+]/) { - if (/^--classic$/) - { - $classic=1; - } - elsif (/^--prefix=(.*)$/) + if (/^--prefix=(.*)$/) { $config{prefix}=$1; die "Directory given with --prefix MUST be absolute\n" @@ -660,15 +719,15 @@ foreach (@argvcopy) } elsif (/^--with-zlib-include=(.*)$/) { - $withargs{zlib_include}="-I$1"; + $withargs{zlib_include}=$1; } - elsif (/^--with-fipslibdir=(.*)$/) + elsif (/^--with-fuzzer-lib=(.*)$/) { - $config{fipslibdir}="$1/"; + $withargs{fuzzer_lib}=$1; } - elsif (/^--with-baseaddr=(.*)$/) + elsif (/^--with-fuzzer-include=(.*)$/) { - $config{baseaddr}="$1"; + $withargs{fuzzer_include}=$1; } elsif (/^--cross-compile-prefix=(.*)$/) { @@ -682,6 +741,22 @@ foreach (@argvcopy) { $libs.=$_." "; } + elsif (/^-rpath$/ or /^-R$/) + # -rpath is the OSF1 rpath flag + # -R is the old Solaris rpath flag + { + my $rpath = shift(@argvcopy) || ""; + $rpath .= " " if $rpath ne ""; + $libs.=$_." ".$rpath; + } + elsif (/^-static$/) + { + $libs.=$_." "; + $disabled{"dso"} = "forced"; + $disabled{"pic"} = "forced"; + $disabled{"shared"} = "forced"; + $disabled{"threads"} = "forced"; + } elsif (/^-D(.*)$/) { push @user_defines, $1; @@ -700,7 +775,7 @@ foreach (@argvcopy) unless ($_ eq $target || /^no-/ || /^disable-/) { # "no-..." follows later after implied disactivations - # have been derived. (Don't take this too seroiusly, + # have been derived. (Don't take this too seriously, # we really only write OPTIONS to the Makefile out of # nostalgia.) @@ -726,14 +801,12 @@ foreach (@argvcopy) } } -if ($config{fips}) - { - delete $disabled{"shared"} if ($disabled{"shared"} =~ /^default/); - } -else - { - @{$config{dirs}} = grep !/^fips$/, @{$config{dirs}}; - } +if ($libs =~ /(^|\s)-Wl,-rpath,/ + && !$disabled{shared} + && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) { + die "***** Cannot simultaneously use -rpath, shared libraries, and\n", + "***** any of asan, msan or ubsan\n"; +} my @tocheckfor = (keys %disabled); while (@tocheckfor) { @@ -742,15 +815,17 @@ while (@tocheckfor) { while (@cascade_copy) { my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy); if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) { - map { + foreach(grep { !defined($disabled{$_}) } @$descendents) { $new_tocheckfor{$_} = 1; $disabled{$_} = "forced"; - } grep { !defined($disabled{$_}) } @$descendents; + } } } @tocheckfor = (keys %new_tocheckfor); } +our $die = sub { die @_; }; if ($target eq "TABLE") { + local $die = sub { warn @_; }; foreach (sort keys %table) { print_table_entry($_, "TABLE"); } @@ -765,6 +840,7 @@ if ($target eq "LIST") { } if ($target eq "HASH") { + local $die = sub { warn @_; }; print "%table = (\n"; foreach (sort keys %table) { print_table_entry($_, "HASH"); @@ -806,33 +882,35 @@ foreach (sort (keys %disabled)) @{$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 ($ALGO, $algo); - ($ALGO = $algo = $_) =~ tr/[\-a-z]/[_A-Z]/; + my ($WHAT, $what); + + ($WHAT = $what = $_) =~ tr/[\-a-z]/[_A-Z]/; - if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/ || /^async$/ - || /^autoalginit/ || /^autoerrinit/) + # 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_other_defines}}, "OPENSSL_NO_$ALGO"; - print " OPENSSL_NO_$ALGO"; + push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$WHAT"; + @{$config{sdirs}} = grep { $_ ne $what} @{$config{sdirs}}; - if (/^err$/) { push @user_defines, "OPENSSL_NO_ERR"; } + print " OPENSSL_NO_$WHAT (skip dir)"; } else { - ($ALGO,$algo) = ("RMD160","rmd160") if ($algo eq "ripemd"); - - push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$ALGO"; - print " OPENSSL_NO_$ALGO"; + push @{$config{openssl_other_defines}}, "OPENSSL_NO_$WHAT"; + print " OPENSSL_NO_$WHAT"; - # fix-up crypto/directory name(s) - $algo="whrlpool" if $algo eq "whirlpool"; - $algo="ripemd" if $algo eq "rmd160"; - @{$config{sdirs}} = grep { $_ ne $algo} @{$config{sdirs}}; - - print " (skip dir)"; + if (/^err$/) { push @user_defines, "OPENSSL_NO_ERR"; } } } @@ -840,7 +918,6 @@ foreach (sort (keys %disabled)) } print "Configuring for $target\n"; - # Support for legacy targets having a name starting with 'debug-' my ($d, $t) = $target =~ m/^(debug-)?(.*)$/; if ($d) { @@ -856,12 +933,14 @@ 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" || $config{target} =~ /^(?:Cygwin|mingw)/); -$target{exe_extension}=".nlm" if ($config{target} =~ /netware/); $target{exe_extension}=".pm" if ($config{target} =~ /vos/); ($target{shared_extension_simple}=$target{shared_extension}) @@ -875,17 +954,35 @@ $config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'} if $config{cross_compile_prefix} eq ""; # Allow overriding the names of some tools. USE WITH CARE -$config{perl} = $ENV{'PERL'} || which("perl5") || which("perl") || "perl"; +# 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{ranlib} = $ENV{'RANLIB'} || $target{ranlib} || which("ranlib") || "true"; +$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"; + +# 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} = ""; @@ -893,25 +990,11 @@ $config{shared_ldflag} = ""; $target{build_scheme} = [ $target{build_scheme} ] if ref($target{build_scheme}) ne "ARRAY"; -###### TO BE REMOVED WHEN CLASSIC BUILD IS REMOVED -###### -###### If the user has chosen --classic, we give it to them. -###### If they try that with an out-of-source config, we complain. -if ($target{build_scheme}->[0] eq "unified" && $classic) { - die "Can't perform a classic build out of source tree\n" - if $srcdir ne $blddir; - - $target{build_scheme} = { unix => [ "unixmake" ], - windows => [ "mk1mf", $target{build_scheme}->[2] ], - VMS => undef } -> {$target{build_scheme}->[1]}; - - die "Classic mode unavailable on this platform\n" - unless defined($target{build_scheme}); -} - my ($builder, $builder_platform, @builder_opts) = @{$target{build_scheme}}; +push @{$config{defines}}, "NDEBUG" if $config{build_type} eq "release"; + if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` =~ m/-mno-cygwin/m) { $config{cflags} .= " -mno-cygwin"; @@ -953,15 +1036,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) { @@ -970,7 +1044,7 @@ unless ($disabled{threads}) { $disabled{threads} = "unavailable"; } } else { - # The user chose to enable threads explicitely, let's see + # The user chose to enable threads explicitly, let's see # if there's a chance that's possible if ($target{thread_scheme} eq "(unknown)") { # If the user asked for "threads" and we don't have internal @@ -1002,8 +1076,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"; @@ -1017,6 +1090,24 @@ if ($disabled{"dynamic-engine"}) { $config{dynamic_engines} = 1; } +unless ($disabled{asan}) { + $config{cflags} .= "-fsanitize=address "; +} + +unless ($disabled{ubsan}) { + # -DPEDANTIC or -fnosanitize=alignment may also be required on some + # platforms. + $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all "; +} + +unless ($disabled{msan}) { + $config{cflags} .= "-fsanitize=memory "; +} + +unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} + && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) { + $config{cflags} .= "-fno-omit-frame-pointer -g "; +} # # Platform fix-ups # @@ -1049,15 +1140,14 @@ 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/); push @{$config{defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/); } + if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) { + push @{$config{defines}}, "RC4_ASM"; + } if ($target{md5_asm_src}) { push @{$config{defines}}, "MD5_ASM"; } @@ -1089,6 +1179,9 @@ unless ($disabled{asm}) { if ($target{ec_asm_src} =~ /ecp_nistz256/) { push @{$config{defines}}, "ECP_NISTZ256_ASM"; } + if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) { + push @{$config{defines}}, "PADLOCK_ASM"; + } if ($target{poly1305_asm_src} ne "") { push @{$config{defines}}, "POLY1305_ASM"; } @@ -1108,7 +1201,7 @@ if ($^O ne "VMS" && !$disabled{makedepend}) { # 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)); + if (/clang/ || (/gcc/ && $compiler_major >= 3)); $ecc = "clang" if /clang/; $ecc = "gcc" if /gcc/; last if ($config{makedepprog} || !$lines--); @@ -1188,7 +1281,7 @@ unless ($disabled{"crypto-mdebug-backtrace"}) } } -if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; } +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; } @@ -1209,6 +1302,8 @@ unless ($disabled{afalgeng}) { } else { push @{$config{engdirs}}, "afalg"; } + } else { + $disabled{afalgeng} = "cross-compiling"; } } else { $disabled{afalgeng} = "not-linux"; @@ -1220,17 +1315,8 @@ push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afal # 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") { - # Store the name of the template file we will build the build file from - # in %config. This may be useful for the build file itself. - my $build_file_template = - catfile($srcdir, "Configurations", - $builder_platform."-".$target{build_file}.".tmpl"); - $build_file_template = - catfile($srcdir, "Configurations", $target{build_file}.".tmpl") - if (! -f $build_file_template); - $config{build_file_template} = $build_file_template; - use lib catdir(dirname(__FILE__),"util"); use with_fallback qw(Text::Template); @@ -1267,6 +1353,47 @@ if ($builder eq "unified") { return $res; } + # Store the name of the template file we will build the build file from + # in %config. This may be useful for the build file itself. + my @build_file_template_names = + ( $builder_platform."-".$target{build_file}.".tmpl", + $target{build_file}.".tmpl" ); + my @build_file_templates = (); + + # First, look in the user provided directory, if given + if (defined $ENV{$local_config_envname}) { + @build_file_templates = + map { + if ($^O eq 'VMS') { + # VMS environment variables are logical names, + # which can be used as is + $local_config_envname . ':' . $_; + } else { + catfile($ENV{$local_config_envname}, $_); + } + } + @build_file_template_names; + } + # Then, look in our standard directory + push @build_file_templates, + ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) } + @build_file_template_names ); + + my $build_file_template; + for $_ (@build_file_templates) { + $build_file_template = $_; + last if -f $build_file_template; + + $build_file_template = undef; + } + if (!defined $build_file_template) { + die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n"; + } + $config{build_file_templates} + = [ $build_file_template, + cleanfile($srcdir, catfile("Configurations", "common.tmpl"), + $blddir) ]; + my @build_infos = ( [ ".", "build.info" ] ); foreach (@{$config{dirs}}) { push @build_infos, [ $_, "build.info" ] @@ -1280,6 +1407,10 @@ if ($builder eq "unified") { push @build_infos, [ catdir("engines", $_), "build.info" ] if (-f catfile($srcdir, "engines", $_, "build.info")); } + foreach (@{$config{tdirs}}) { + push @build_infos, [ catdir("test", $_), "build.info" ] + if (-f catfile($srcdir, "test", $_, "build.info")); + } $config{build_infos} = [ ]; @@ -1292,9 +1423,13 @@ if ($builder eq "unified") { my $f = $_->[1]; # The basic things we're trying to build my @programs = (); + my @programs_install = (); my @libraries = (); + my @libraries_install = (); my @engines = (); + my @engines_install = (); my @scripts = (); + my @scripts_install = (); my @extra = (); my @overrides = (); my @intermediates = (); @@ -1302,6 +1437,7 @@ if ($builder eq "unified") { my %ordinals = (); my %sources = (); + my %shared_sources = (); my %includes = (); my %depends = (); my %renames = (); @@ -1317,6 +1453,7 @@ if ($builder eq "unified") { $template->fill_in(HASH => { config => \%config, target => \%target, disabled => \%disabled, + withargs => \%withargs, builddir => abs2rel($buildd, $blddir), sourcedir => abs2rel($sourced, $blddir), buildtop => abs2rel($blddir, $blddir), @@ -1356,45 +1493,72 @@ if ($builder eq "unified") { qr/^\s*ENDIF\s*$/ => sub { die "ENDIF out of scope" if ! @skip; pop @skip; }, - qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/ - => sub { push @programs, split(/\s+/, $1) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*LIBS\s*=\s*(.*)\s*$/ - => sub { push @libraries, split(/\s+/, $1) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*ENGINES\s*=\s*(.*)\s*$/ - => sub { push @engines, split(/\s+/, $1) - if !@skip || $skip[$#skip] > 0 }, - qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/ - => sub { push @scripts, split(/\s+/, $1) - if !@skip || $skip[$#skip] > 0 }, + qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @programs, @x; + push @programs_install, @x unless $install; + } + }, + qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @libraries, @x; + push @libraries_install, @x unless $install; + } + }, + qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @engines, @x; + push @engines_install, @x unless $install; + } + }, + qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/ + => sub { + if (!@skip || $skip[$#skip] > 0) { + my $install = $1; + my @x = tokenize($2); + push @scripts, @x; + push @scripts_install, @x unless $install; + } + }, qr/^\s*EXTRA\s*=\s*(.*)\s*$/ - => sub { push @extra, split(/\s+/, $1) + => sub { push @extra, tokenize($1) if !@skip || $skip[$#skip] > 0 }, qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/ - => sub { push @overrides, split(/\s+/, $1) + => sub { push @overrides, tokenize($1) if !@skip || $skip[$#skip] > 0 }, qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/, - => sub { push @{$ordinals{$1}}, split(/\s+/, $2) + => sub { push @{$ordinals{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$sources{$1}}, split(/\s+/, $2) + => sub { push @{$sources{$1}}, tokenize($2) + if !@skip || $skip[$#skip] > 0 }, + qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ + => sub { push @{$shared_sources{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$includes{$1}}, split(/\s+/, $2) + => sub { push @{$includes{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, - qr/^\s*DEPEND\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$depends{$1}}, split(/\s+/, $2) + qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/ + => sub { push @{$depends{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ => sub { push @{$generate{$1}}, $2 if !@skip || $skip[$#skip] > 0 }, qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$renames{$1}}, split(/\s+/, $2) + => sub { push @{$renames{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ - => sub { push @{$sharednames{$1}}, split(/\s+/, $2) + => sub { push @{$sharednames{$1}}, tokenize($2) if !@skip || $skip[$#skip] > 0 }, qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/ => sub { @@ -1413,8 +1577,19 @@ if ($builder eq "unified") { || $target_kind eq $target{build_file}."(".$builder_platform.")"); } }, - qr/^(?:#.*|\s*)$/ => sub { }, - "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" } + qr/^\s*(?:#.*)?$/ => sub { }, + "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }, + "BEFORE" => sub { + if ($buildinfo_debug) { + print STDERR "DEBUG: Parsing ",join(" ", @_),"\n"; + print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; + } + }, + "AFTER" => sub { + if ($buildinfo_debug) { + print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; + } + }, ); die "runaway IF?" if (@skip); @@ -1439,6 +1614,14 @@ if ($builder eq "unified") { $unified_info{programs}->{$program} = 1; } + foreach (@programs_install) { + my $program = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$program}) { + $program = $unified_info{rename}->{$program}; + } + $unified_info{install}->{programs}->{$program} = 1; + } + foreach (@libraries) { my $library = cleanfile($buildd, $_, $blddir); if ($unified_info{rename}->{$library}) { @@ -1447,6 +1630,14 @@ if ($builder eq "unified") { $unified_info{libraries}->{$library} = 1; } + foreach (@libraries_install) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{install}->{libraries}->{$library} = 1; + } + die <<"EOF" if scalar @engines and !$config{dynamic_engines}; ENGINES can only be used if configured with 'dynamic-engine'. This is usually a fault in a build.info file. @@ -1459,6 +1650,14 @@ EOF $unified_info{engines}->{$library} = 1; } + foreach (@engines_install) { + my $library = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$library}) { + $library = $unified_info{rename}->{$library}; + } + $unified_info{install}->{engines}->{$library} = 1; + } + foreach (@scripts) { my $script = cleanfile($buildd, $_, $blddir); if ($unified_info{rename}->{$script}) { @@ -1467,6 +1666,14 @@ EOF $unified_info{scripts}->{$script} = 1; } + foreach (@scripts_install) { + my $script = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$script}) { + $script = $unified_info{rename}->{$script}; + } + $unified_info{install}->{scripts}->{$script} = 1; + } + foreach (@extra) { my $extra = cleanfile($buildd, $_, $blddir); $unified_info{extra}->{$extra} = 1; @@ -1543,9 +1750,11 @@ EOF if (! -f $s) { $s = cleanfile($buildd, $_, $blddir); } - # We recognise C and asm files - if ($s =~ /\.[csS]\b$/) { - (my $o = $_) =~ s/\.[csS]\b$/.o/; + # We recognise C++, C and asm files + if ($s =~ /\.(cc|cpp|c|s|S)$/) { + my $o = $_; + $o =~ s/\.[csS]$/.o/; # C and assembler + $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ $o = cleanfile($buildd, $o, $blddir); $unified_info{sources}->{$ddest}->{$o} = 1; $unified_info{sources}->{$o}->{$s} = 1; @@ -1555,6 +1764,34 @@ EOF } } + foreach (keys %shared_sources) { + my $dest = $_; + my $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } + foreach (@{$shared_sources{$dest}}) { + my $s = cleanfile($sourced, $_, $blddir); + + # If it isn't in the source tree, we assume it's generated + # in the build tree + if (! -f $s) { + $s = cleanfile($buildd, $_, $blddir); + } + # We recognise C++, C and asm files + if ($s =~ /\.(cc|cpp|c|s|S)$/) { + 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; + } else { + die "unrecognised source file type for shared library: $s\n"; + } + } + } + foreach (keys %generate) { my $dest = $_; my $ddest = cleanfile($buildd, $_, $blddir); @@ -1571,9 +1808,15 @@ EOF foreach (keys %depends) { my $dest = $_; - my $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; + my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir); + + # If the destination doesn't exist in source, it can only be + # a generated file in the build tree. + if ($ddest ne "" && ! -f $ddest) { + $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } } foreach (@{$depends{$dest}}) { my $d = cleanfile($sourced, $_, $blddir); @@ -1584,36 +1827,52 @@ EOF # and that there are lines to build it in a BEGINRAW..ENDRAW # section or in the Makefile template. if (! -f $d - || !(grep { $d eq $_ } - map { cleanfile($srcdir, $_, $blddir) } - (@generated_headers, @generated_by_make_headers))) { + || (grep { $d eq $_ } + map { cleanfile($srcdir, $_, $blddir) } + grep { /\.h$/ } keys %{$unified_info{generate}})) { $d = cleanfile($buildd, $_, $blddir); } # Take note if the file to depend on is being renamed + # Take extra care with files ending with .a, they should + # be treated without that extension, and the extension + # should be added back after treatment. + $d =~ /(\.a)?$/; + my $e = $1 // ""; + $d = $`; if ($unified_info{rename}->{$d}) { $d = $unified_info{rename}->{$d}; } + $d .= $e; $unified_info{depends}->{$ddest}->{$d} = 1; - # If we depend on a header file, let's make sure it - # can get included - if ($d =~ /\.h$/) { + # 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}}, $i - unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}}; + push @{$unified_info{includes}->{$ddest}->{source}}, $i + unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}->{source}}; } } } foreach (keys %includes) { my $dest = $_; - my $ddest = cleanfile($buildd, $_, $blddir); - if ($unified_info{rename}->{$ddest}) { - $ddest = $unified_info{rename}->{$ddest}; + my $ddest = cleanfile($sourced, $_, $blddir); + + # If the destination doesn't exist in source, it can only be + # a generated file in the build tree. + if (! -f $ddest) { + $ddest = cleanfile($buildd, $_, $blddir); + if ($unified_info{rename}->{$ddest}) { + $ddest = $unified_info{rename}->{$ddest}; + } } foreach (@{$includes{$dest}}) { - my $i = cleandir($sourced, $_, $blddir); - push @{$unified_info{includes}->{$ddest}}, $i - unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}}; + my $is = cleandir($sourced, $_, $blddir); + my $ib = cleandir($buildd, $_, $blddir); + push @{$unified_info{includes}->{$ddest}->{source}}, $is + unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}}; + push @{$unified_info{includes}->{$ddest}->{build}}, $ib + unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}}; } } } @@ -1624,12 +1883,28 @@ EOF $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; } # Two level structures - foreach my $l1 (("sources", "ldadd", "depends")) { + foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) { foreach my $l2 (sort keys %{$unified_info{$l1}}) { $unified_info{$l1}->{$l2} = [ sort keys %{$unified_info{$l1}->{$l2}} ]; } } + # Includes + foreach my $dest (sort keys %{$unified_info{includes}}) { + if (defined($unified_info{includes}->{$dest}->{build})) { + my @source_includes = + ( @{$unified_info{includes}->{$dest}->{source}} ); + $unified_info{includes}->{$dest} = + [ @{$unified_info{includes}->{$dest}->{build}} ]; + foreach my $inc (@source_includes) { + push @{$unified_info{includes}->{$dest}}, $inc + unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}}; + } + } else { + $unified_info{includes}->{$dest} = + [ @{$unified_info{includes}->{$dest}->{source}} ]; + } + } } # For the schemes that need it, we provide the old *_obj configs @@ -1637,7 +1912,9 @@ EOF foreach (grep /_(asm|aux)_src$/, keys %target) { my $src = $_; (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/; - ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g; + $target{$obj} = $target{$src}; + $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler + $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++ } # Write down our configuration where it fits ######################### @@ -1652,7 +1929,7 @@ use warnings; use Exporter; #use vars qw(\@ISA \@EXPORT); our \@ISA = qw(Exporter); -our \@EXPORT = qw(\%config \%target %disabled %withargs %unified_info); +our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables); EOF print OUT "our %config = (\n"; @@ -1689,6 +1966,14 @@ print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n" print OUT <<"EOF"; ); +EOF +print OUT "our \@disablables = (\n"; +foreach (@disablables) { + print OUT " ", quotify("perl", $_), ",\n"; +} +print OUT <<"EOF"; +); + EOF print OUT "our \%disabled = (\n"; foreach (sort keys %disabled) { @@ -1757,175 +2042,32 @@ EOF print OUT "1;\n"; close(OUT); - -print "IsMK1MF =", ($builder eq "mk1mf" ? "yes" : "no"), "\n"; -print "CC =$target{cc}\n"; +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 "SHARED_CFLAG =$target{shared_cflag}\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 "LFLAG =$target{lflags}\n"; -print "PLIB_LFLAG =$target{plib_lflags}\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"; -print "APPS_OBJ =$target{apps_obj}\n"; -print "CPUID_OBJ =$target{cpuid_obj}\n"; -print "UPLINK_OBJ =$target{uplink_obj}\n"; -print "BN_ASM =$target{bn_obj}\n"; -print "EC_ASM =$target{ec_obj}\n"; -print "DES_ENC =$target{des_obj}\n"; -print "AES_ENC =$target{aes_obj}\n"; -print "BF_ENC =$target{bf_obj}\n"; -print "CAST_ENC =$target{cast_obj}\n"; -print "RC4_ENC =$target{rc4_obj}\n"; -print "RC5_ENC =$target{rc5_obj}\n"; -print "MD5_OBJ_ASM =$target{md5_obj}\n"; -print "SHA1_OBJ_ASM =$target{sha1_obj}\n"; -print "RMD160_OBJ_ASM=$target{rmd160_obj}\n"; -print "CMLL_ENC =$target{cmll_obj}\n"; -print "MODES_OBJ =$target{modes_obj}\n"; -print "PADLOCK_OBJ =$target{padlock_obj}\n"; -print "CHACHA_ENC =$target{chacha_obj}\n"; -print "POLY1305_OBJ =$target{poly1305_obj}\n"; -print "BLAKE2_OBJ =$target{blake2_obj}\n"; -print "PROCESSOR =$config{processor}\n"; -print "RANLIB =$target{ranlib}\n"; -print "ARFLAGS =$target{arflags}\n"; -print "PERL =$config{perl}\n"; -print "\n"; -print "SIXTY_FOUR_BIT_LONG mode\n" if $config{b64l}; -print "SIXTY_FOUR_BIT mode\n" if $config{b64}; -print "THIRTY_TWO_BIT mode\n" if $config{b32}; -print "BN_LLONG mode\n" if $config{bn_ll}; -print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} ne $def_int; - -for (@generated_headers) { - mkpath(catdir($blddir, dirname($_))); - run_dofile(catfile($blddir, $_), - catfile($srcdir, $_.".in")); -} - -### -### When the old "unixmake" scheme goes away, so does this function -### -sub build_Makefile { - run_dofile("Makefile","Makefile.in"); - - # Copy all Makefile.in to Makefile (except top-level) - use File::Find; - use IO::File; - find( - { - preprocess => sub { - grep(!/^\./, @_); - }, - wanted => sub { - return if ($_ ne "Makefile.in" || $File::Find::dir eq "."); - my $in = IO::File->new($_, "r") or - die sprintf "Error reading Makefile.in in %s: !$\n", - $File::Find::dir; - my $out = IO::File->new("Makefile", "w") or - die sprintf "Error writing Makefile in %s: !$\n", - $File::Find::dir; - print $out "# Generated from $_, do not edit\n"; - while (my $line = <$in>) { print $out $line } - $in->close() or - die sprintf "Error reading Makefile.in in %s: !$\n", - $File::Find::dir; - $out->close() or - die sprintf "Error writing Makefile in %s: !$\n", - $File::Find::dir; - }, - }, - "."); -} my %builders = ( unified => sub { run_dofile(catfile($blddir, $target{build_file}), - $config{build_file_template}, - catfile($srcdir, "Configurations", "common.tmpl")); - }, - unixmake => sub { - build_Makefile(); - - run_dofile("util/domd", "util/domd.in"); - chmod 0755, "util/domd"; - }, - mk1mf => sub { - my $platform = shift; - # The only reason we do this is to have something to build MINFO from - build_Makefile(); - - # create the ms/version32.rc file if needed - if ($platform ne "netware") { - my ($v1, $v2, $v3, $v4); - if ($config{version_num} =~ /^0x([0-9a-f]{1})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{1})L$/i) { - $v1=hex $1; - $v2=hex $2; - $v3=hex $3; - $v4=hex $4; - } - open (OUT,">ms/version32.rc") || die "Can't open ms/version32.rc"; - print OUT <<"EOF"; -#include - -LANGUAGE 0x09,0x01 - -1 VERSIONINFO - FILEVERSION $v1,$v2,$v3,$v4 - PRODUCTVERSION $v1,$v2,$v3,$v4 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x01L -#else - FILEFLAGS 0x00L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - // Required: - VALUE "CompanyName", "The OpenSSL Project, http://www.openssl.org/\\0" - VALUE "FileDescription", "OpenSSL Shared Library\\0" - VALUE "FileVersion", "$config{version}\\0" -#if defined(CRYPTO) - VALUE "InternalName", "libcrypto32\\0" - VALUE "OriginalFilename", "libcrypto32.dll\\0" -#elif defined(SSL) - VALUE "InternalName", "libssl32\\0" - VALUE "OriginalFilename", "libssl32.dll\\0" -#endif - VALUE "ProductName", "The OpenSSL Toolkit\\0" - VALUE "ProductVersion", "$config{version}\\0" - // Optional: - //VALUE "Comments", "\\0" - VALUE "LegalCopyright", "Copyright © 1998-2015 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0" - //VALUE "LegalTrademarks", "\\0" - //VALUE "PrivateBuild", "\\0" - //VALUE "SpecialBuild", "\\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 0x4b0 - END -END -EOF - close(OUT); - } + @{$config{build_file_templates}}); }, ); $builders{$builder}->($builder_platform, @builder_opts); -print <<"EOF"; - -Configured for $target. -EOF - print <<"EOF" if ($disabled{threads} eq "unavailable"); The library could not be configured for supporting multi-threaded @@ -1942,6 +2084,14 @@ or position independent code, please let us know (but please first make sure you have tried with a current version of OpenSSL). EOF +print <<"EOF" if (-f catfile($srcdir, "configdata.pm") && $srcdir ne $blddir); + +WARNING: there are indications that another build was made in the source +directory. This build may have picked up artifacts from that build, the +safest course of action is to clean the source directory and redo this +configuration. +EOF + exit(0); ###################################################################### @@ -1951,6 +2101,11 @@ exit(0); # Configuration file reading ######################################### +# Note: All of the helper functions are for lazy evaluation. They all +# return a CODE ref, which will return the intended value when evaluated. +# Thus, whenever there's mention of a returned value, it's about that +# intended value. + # Helper function to implement conditional inheritance depending on the # value of $disabled{asm}. Used in inherit_from values as follows: # @@ -1963,6 +2118,53 @@ sub asm { } } +# Helper function to implement conditional value variants, with a default +# plus additional values based on the value of $config{build_type}. +# Arguments are given in hash table form: +# +# picker(default => "Basic string: ", +# debug => "debug", +# release => "release") +# +# When configuring with --debug, the resulting string will be +# "Basic string: debug", and when not, it will be "Basic string: release" +# +# This can be used to create variants of sets of flags according to the +# build type: +# +# cflags => picker(default => "-Wall", +# debug => "-g -O0", +# release => "-O3") +# +sub picker { + my %opts = @_; + return sub { add($opts{default} || (), + $opts{$config{build_type}} || ())->(); } +} + +# Helper function to combine several values of different types into one. +# This is useful if you want to combine a string with the result of a +# lazy function, such as: +# +# cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" }) +# +sub combine { + my @stuff = @_; + return sub { add(@stuff)->(); } +} + +# Helper function to implement conditional values depending on the value +# of $disabled{threads}. Can be used as follows: +# +# cflags => combine("-Wall", threads("-pthread")) +# +sub threads { + my @flags = @_; + return sub { add($disabled{threads} ? () : @flags)->(); } +} + + + our $add_called = 0; # Helper function to implement adding values to already existing configuration # values. It handles elements that are ARRAYs, CODEs and scalars @@ -2033,7 +2235,8 @@ sub read_config { close(CONFFILE); my %targets = (); { - local %table = %::table; # Protect %table from tampering + # Protect certain tables from tampering + local %table = %::table; eval $content; warn $@ if $@; @@ -2048,15 +2251,17 @@ sub read_config { warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n"; } delete $targets{$_}; - } + } else { + $targets{$_}->{_conf_fname_int} = add([ $fname ]); + } } %table = (%table, %targets); } -# configuration resolver. Will only resolve all the lazy evalutation -# codeblocks for the chozen target and all those it inherits from, +# configuration resolver. Will only resolve all the lazy evaluation +# codeblocks for the chosen target and all those it inherits from, # recursively sub resolve_config { my $target = shift; @@ -2090,12 +2295,12 @@ sub resolve_config { # the config that had it. delete $inherited_config{template}; - map { + foreach (keys %inherited_config) { if (!$combined_inheritance{$_}) { $combined_inheritance{$_} = []; } push @{$combined_inheritance{$_}}, $inherited_config{$_}; - } keys %inherited_config; + } } } @@ -2109,7 +2314,7 @@ sub resolve_config { # - If a value is a coderef, it will be executed with the list of # inherited values as arguments. # - If the corresponding key doesn't have a value at all or is the - # emoty string, the inherited value list will be run through the + # empty string, the inherited value list will be run through the # default combiner (below), and the result becomes this target's # value. # - Otherwise, this target's value is assumed to be a string that @@ -2217,13 +2422,35 @@ sub run_dofile foreach (@templates) { die "Can't open $_, $!" unless -f $_; } - my $cmd = "$config{perl} \"-I.\" \"-Mconfigdata\" $dofile -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; + my $perlcmd = (quotify("maybeshell", $config{perl}))[0]; + my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; system($cmd); exit 1 if $? != 0; rename("$out.new", $out) || die "Can't rename $out.new, $!"; } +sub which +{ + my ($name)=@_; + + if (eval { require IPC::Cmd; 1; }) { + IPC::Cmd->import(); + return scalar IPC::Cmd::can_run($name); + } else { + # if there is $directories component in splitpath, + # then it's not something to test with $PATH... + return $name if (File::Spec->splitpath($name))[1]; + + foreach (File::Spec->path()) { + my $fullpath = catfile($_, "$name$target{exe_extension}"); + if (-f $fullpath and -x $fullpath) { + return $fullpath; + } + } + } +} + # Configuration printer ############################################## sub print_table_entry @@ -2243,41 +2470,53 @@ sub print_table_entry "unistd", "ld", "lflags", + "loutflag", "plib_lflags", "ex_libs", "bn_ops", - "cpuid_obj", - "bn_obj", - "ec_obj", - "des_obj", - "aes_obj", - "bf_obj", - "md5_obj", - "sha1_obj", - "cast_obj", - "rc4_obj", - "rmd160_obj", - "rc5_obj", - "wp_obj", - "cmll_obj", - "modes_obj", - "padlock_obj", + "apps_aux_src", + "cpuid_asm_src", + "uplink_aux_src", + "bn_asm_src", + "ec_asm_src", + "des_asm_src", + "aes_asm_src", + "bf_asm_src", + "md5_asm_src", + "cast_asm_src", + "sha1_asm_src", + "rc4_asm_src", + "rmd160_asm_src", + "rc5_asm_src", + "wp_asm_src", + "cmll_asm_src", + "modes_asm_src", + "padlock_asm_src", + "chacha_asm_src", + "poly1035_asm_src", "thread_scheme", "perlasm_scheme", "dso_scheme", "shared_target", "shared_cflag", + "shared_defines", "shared_ldflag", "shared_rcflag", "shared_extension", - "shared_extension_simple", - "shared_import_extension", "dso_extension", "obj_extension", "exe_extension", "ranlib", "ar", "arflags", + "aroutflag", + "rc", + "rcflags", + "rcoutflag", + "mt", + "mtflags", + "mtinflag", + "mtoutflag", "multilib", "build_scheme", ); @@ -2351,33 +2590,25 @@ sub absolutedir { return realpath($dir); } -sub which - { - my($name)=@_; - my $path; - foreach $path (split /:/, $ENV{PATH}) - { - my $fullpath = "$path/$name$target{exe_extension}"; - if (-f $fullpath and -x $fullpath) - { - return $fullpath - unless ($name eq "perl" and - system("$fullpath -e " . '\'exit($]<5.0);\'')); - } - } - } - sub quotify { my %processors = ( perl => sub { my $x = shift; $x =~ s/([\\\$\@"])/\\$1/g; return '"'.$x.'"'; }, + maybeshell => sub { my $x = shift; + (my $y = $x) =~ s/([\\\"])/\\$1/g; + if ($x ne $y || $x =~ m|\s|) { + return '"'.$y.'"'; + } else { + return $x; + } + }, ); my $for = shift; my $processor = defined($processors{$for}) ? $processors{$for} : sub { shift; }; - map { $processor->($_); } @_; + return map { $processor->($_); } @_; } # collect_from_file($filename, $line_concat_cond_re, $line_concat) @@ -2452,8 +2683,11 @@ sub collect_information { while(defined($_ = $lineiterator->())) { s|\R$||; my $found = 0; + if ($collectors{"BEFORE"}) { + $collectors{"BEFORE"}->($_); + } foreach my $re (keys %collectors) { - if ($re ne "OTHERWISE" && /$re/) { + if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) { $collectors{$re}->($lineiterator); $found = 1; }; @@ -2462,5 +2696,46 @@ sub collect_information { $collectors{"OTHERWISE"}->($lineiterator, $_) unless $found || !defined $collectors{"OTHERWISE"}; } + if ($collectors{"AFTER"}) { + $collectors{"AFTER"}->($_); + } + } +} + +# tokenize($line) +# $line is a line of text to split up into tokens +# returns a list of tokens +# +# Tokens are divided by spaces. If the tokens include spaces, they +# have to be quoted with single or double quotes. Double quotes +# inside a double quoted token must be escaped. Escaping is done +# with backslash. +# Basically, the same quoting rules apply for " and ' as in any +# Unix shell. +sub tokenize { + my $line = my $debug_line = shift; + my @result = (); + + while ($line =~ s|^\s+||, $line ne "") { + my $token = ""; + while ($line ne "" && $line !~ m|^\s|) { + if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { + $token .= $1; + $line = $'; + } elsif ($line =~ m/^'([^']*)'/) { + $token .= $1; + $line = $'; + } elsif ($line =~ m/^(\S+)/) { + $token .= $1; + $line = $'; + } + } + push @result, $token; + } + + if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { + print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n"; + print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n"; } + return @result; }