X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=Configure;h=96b6590723d1785418f460ab6d5f2791fc3cd637;hp=eeae03e2298f467b4b09583d845f924bb9e0ba7c;hb=342a1a23793cb99921abeabe882adf8652ba715d;hpb=0069806128a24dd25908ee3dbb271cda3cc92bda diff --git a/Configure b/Configure index eeae03e229..96b6590723 100755 --- a/Configure +++ b/Configure @@ -1,17 +1,20 @@ #! /usr/bin/env perl # -*- mode: perl; -*- +# Copyright 2016 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 -## If editing this file, run this command before committing -## make -f Makefile.in TABLE -## -require 5.000; +require 5.10.0; use strict; 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. @@ -63,6 +66,22 @@ my $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lx # no-sse2 disables IA-32 SSE2 code, above option implies no-sse2 # 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 @@ -71,20 +90,31 @@ 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. +my $gcc_devteam_warn = "-DDEBUG_UNUSED" + # -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. + . " -DPEDANTIC -pedantic -Wno-long-long" . " -Wall" - . " -Wno-long-long" . " -Wsign-compare" . " -Wmissing-prototypes" . " -Wshadow" @@ -130,7 +160,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 = { @@ -153,7 +183,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; @@ -165,9 +195,50 @@ 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{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 " 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"; @@ -195,14 +266,27 @@ 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"; -$config{perl}; $config{prefix}=""; $config{openssldir}=""; $config{processor}=""; @@ -216,11 +300,11 @@ 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", + "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "des", "aes", "rc2", "rc4", "rc5", "idea", "bf", "cast", "camellia", "seed", "chacha", "modes", "bn", "ec", "rsa", "dsa", "dh", "dso", "engine", "buffer", "bio", "stack", "lhash", "rand", "err", @@ -232,17 +316,19 @@ $config{sdirs} = [ my @tls = qw(ssl3 tls1 tls1_1 tls1_2); 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", + "asan", "asm", "async", "autoalginit", "autoerrinit", "bf", + "blake2", "camellia", "capieng", "cast", @@ -270,16 +356,17 @@ my @disablables = ( "engine", "err", "filenames", + "fuzz-libfuzzer", + "fuzz-afl", + "gost", "heartbeats", - "hmac", "hw(-.+)?", "idea", "makedepend", "md2", "md4", - "md5", "mdc2", - "md[-_]ghost94", + "msan", "multiblock", "nextprotoneg", "ocb", @@ -293,15 +380,10 @@ my @disablables = ( "rc5", "rdrand", "rfc3779", - "rijndael", # Old AES name - "ripemd", "rmd160", - "rsa", "scrypt", - "sct", "sctp", "seed", - "sha", "shared", "sock", "srp", @@ -314,6 +396,7 @@ my @disablables = ( "threads", "tls", "ts", + "ubsan", "ui", "unit-test", "whirlpool", @@ -327,29 +410,35 @@ 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" + "asan" => "default", + "crypto-mdebug" => "default", + "crypto-mdebug-backtrace" => "default", "ec_nistp_64_gcc_128" => "default", "egd" => "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", "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 @@ -360,11 +449,11 @@ 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 ], # SSL 3.0, (D)TLS 1.0 and TLS 1.1 require MD5 and SHA @@ -398,6 +487,17 @@ my @disable_cascades = ( # Without position independent code, there can be no shared libraries or DSOs "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" ], + sub { !$disabled{"unit-test"} } => [ "heartbeats" ], + + sub { !$disabled{"msan"} } => [ "asm" ], ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -422,17 +522,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); @@ -449,60 +538,6 @@ 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) @@ -524,21 +559,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") @@ -553,6 +584,7 @@ foreach (@argvcopy) { $disabled{$proto} = "option(dtls)"; } + $disabled{"dtls"} = "option(dtls)"; } elsif ($1 eq "ssl") { @@ -576,6 +608,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"; @@ -634,11 +674,7 @@ foreach (@argvcopy) } elsif (/^[-+]/) { - if (/^--classic$/) - { - $classic=1; - } - elsif (/^--prefix=(.*)$/) + if (/^--prefix=(.*)$/) { $config{prefix}=$1; die "Directory given with --prefix MUST be absolute\n" @@ -662,7 +698,15 @@ foreach (@argvcopy) } elsif (/^--with-zlib-include=(.*)$/) { - $withargs{zlib_include}="-I$1"; + $withargs{zlib_include}=$1; + } + elsif (/^--with-fuzzer-lib=(.*)$/) + { + $withargs{fuzzer_lib}=$1; + } + elsif (/^--with-fuzzer-include=(.*)$/) + { + $withargs{fuzzer_include}=$1; } elsif (/^--with-fipslibdir=(.*)$/) { @@ -684,6 +728,14 @@ foreach (@argvcopy) { $libs.=$_." "; } + elsif (/^-static$/) + { + $libs.=$_." "; + $disabled{"dso"} = "forced"; + $disabled{"pic"} = "forced"; + $disabled{"shared"} = "forced"; + $disabled{"threads"} = "forced"; + } elsif (/^-D(.*)$/) { push @user_defines, $1; @@ -702,7 +754,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.) @@ -728,6 +780,13 @@ foreach (@argvcopy) } } +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"; +} + if ($config{fips}) { delete $disabled{"shared"} if ($disabled{"shared"} =~ /^default/); @@ -744,15 +803,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 { - $new_tocheckfor{$_} => 1; $disabled{$_} = "forced"; - } grep { !defined($disabled{$_}) } @$descendents; + foreach(grep { !defined($disabled{$_}) } @$descendents) { + $new_tocheckfor{$_} = 1; $disabled{$_} = "forced"; + } } } @tocheckfor = (keys %new_tocheckfor); } +our $die = sub { die @_; }; if ($target eq "TABLE") { + local $die = sub { warn @_; }; foreach (sort keys %table) { print_table_entry($_, "TABLE"); } @@ -767,6 +828,7 @@ if ($target eq "LIST") { } if ($target eq "HASH") { + local $die = sub { warn @_; }; print "%table = (\n"; foreach (sort keys %table) { print_table_entry($_, "HASH"); @@ -808,33 +870,34 @@ 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]/; + + # Fix up C macro end names + $WHAT = "RMD160" if $what eq "ripemd"; - if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/ || /^async$/ - || /^autoalginit/ || /^autoerrinit/) + # fix-up crypto/directory name(s) + $what = "ripemd" if $what eq "rmd160"; + $what = "whrlpool" if $what eq "whirlpool"; + + if (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_other_defines}}, "OPENSSL_NO_$WHAT"; + print " OPENSSL_NO_$WHAT"; - push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$ALGO"; - print " OPENSSL_NO_$ALGO"; - - # 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"; } } } @@ -863,7 +926,6 @@ my %target = resolve_config($target); $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}) @@ -877,11 +939,26 @@ $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} = $ENV{'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{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{build_file} = $target{build_file}; # For cflags, lflags, plib_lflags, ex_libs and defines, add the debug_ # or release_ attributes. @@ -895,25 +972,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"; @@ -972,7 +1035,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 @@ -1019,6 +1082,28 @@ if ($disabled{"dynamic-engine"}) { $config{dynamic_engines} = 1; } +unless ($disabled{"fuzz-libfuzzer"}) { + $config{cflags} .= "-fsanitize-coverage=edge,indirect-calls "; +} + +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 # @@ -1060,6 +1145,9 @@ unless ($disabled{asm}) { 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"; } @@ -1101,8 +1189,8 @@ 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}"; - $config{makedepprog} = which('makedepend'); - open(PIPE, "$ccpcc --version 2>&1 | head -2 |"); + open(PIPE, "$ccpcc --version 2>&1 |"); + my $lines = 2; while ( ) { # Find the version number and save the major. m|(?:.*)\b(\d+)\.\d+\.\d+\b(?:.*)|; @@ -1110,12 +1198,14 @@ 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--); } close(PIPE); + $config{makedepprog} = which('makedepend') unless $config{makedepprog}; $disabled{makedepend} = "unavailable" unless $config{makedepprog}; } @@ -1150,7 +1240,7 @@ die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set # "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; +$config{cflags} =~ s/([\\\"])/\\$1/g; if (defined($config{api})) { $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; @@ -1195,8 +1285,8 @@ else { $no_user_defines=1; } # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON -unless ($disabled{engine}) { - $config{afalg}=""; +unless ($disabled{afalgeng}) { + $config{afalgeng}=""; if ($target =~ m/^linux/) { my $minver = 4*10000 + 1*100 + 0; if ($config{cross_compile_prefix} eq "") { @@ -1205,30 +1295,61 @@ unless ($disabled{engine}) { ($mi2) = $mi2 =~ /(\d+)/; my $ver = $ma*10000 + $mi1*100 + $mi2; if ($ver < $minver) { - $disabled{afalg} = "too-old-kernel"; + $disabled{afalgeng} = "too-old-kernel"; } else { push @{$config{engdirs}}, "afalg"; } + } else { + $disabled{afalgeng} = "cross-compiling"; } } else { - $disabled{afalg} = "not-linux"; + $disabled{afalgeng} = "not-linux"; } } -push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalg}); +push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng}); # 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); + 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 { catfile($srcdir, "Configurations", $_) } + @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_template} = $build_file_template; use lib catdir(dirname(__FILE__),"util"); @@ -1292,9 +1413,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 +1427,7 @@ if ($builder eq "unified") { my %ordinals = (); my %sources = (); + my %shared_sources = (); my %includes = (); my %depends = (); my %renames = (); @@ -1317,6 +1443,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 +1483,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 { @@ -1414,7 +1568,18 @@ if ($builder eq "unified") { } }, qr/^(?:#.*|\s*)$/ => sub { }, - "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" } + "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 +1604,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 +1620,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 +1640,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 +1656,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; @@ -1555,6 +1752,32 @@ 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 and asm files + if ($s =~ /\.[csS]\b$/) { + (my $o = $_) =~ s/\.[csS]\b$/.o/; + $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 +1794,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,9 +1813,9 @@ 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 @@ -1594,26 +1823,35 @@ EOF $d = $unified_info{rename}->{$d}; } $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 +1862,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 @@ -1652,7 +1906,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 +1943,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) { @@ -1758,8 +2020,7 @@ print OUT "1;\n"; close(OUT); -print "IsMK1MF =", ($builder eq "mk1mf" ? "yes" : "no"), "\n"; -print "CC =$target{cc}\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 "DEFINES =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n"; @@ -1785,8 +2046,11 @@ 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 "RANLIB =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ? + "$config{cross_compile_prefix}ranlib" : + "$target{ranlib}", "\n"; print "ARFLAGS =$target{arflags}\n"; print "PERL =$config{perl}\n"; print "\n"; @@ -1794,48 +2058,7 @@ 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} != $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; - }, - }, - "."); -} +print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} ne $def_int; my %builders = ( unified => sub { @@ -1843,79 +2066,6 @@ my %builders = ( $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); - } - }, ); $builders{$builder}->($builder_platform, @builder_opts); @@ -1941,6 +2091,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); ###################################################################### @@ -1950,6 +2108,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: # @@ -1962,6 +2125,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 @@ -2054,8 +2264,8 @@ sub read_config { } -# 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; @@ -2089,12 +2299,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; + } } } @@ -2108,7 +2318,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 @@ -2206,7 +2416,7 @@ sub usage exit(1); } -sub run_dofile() +sub run_dofile { my $out = shift; my @templates = @_; @@ -2216,13 +2426,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 @@ -2242,41 +2474,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", ); @@ -2350,33 +2594,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) @@ -2451,8 +2687,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; }; @@ -2461,5 +2700,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; }