apps/speed.c: add -seconds and -bytes options
[openssl.git] / Configure
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 # Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
4 #
5 # Licensed under the OpenSSL license (the "License").  You may not use
6 # this file except in compliance with the License.  You can obtain a copy
7 # in the file LICENSE in the source distribution or at
8 # https://www.openssl.org/source/license.html
9
10 ##  Configure -- OpenSSL source tree configuration script
11
12 use 5.10.0;
13 use strict;
14 use Config;
15 use FindBin;
16 use lib "$FindBin::Bin/util/perl";
17 use File::Basename;
18 use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
19 use File::Path qw/mkpath/;
20 use OpenSSL::Glob;
21
22 # see INSTALL for instructions.
23
24 my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
25
26 # Options:
27 #
28 # --config      add the given configuration file, which will be read after
29 #               any "Configurations*" files that are found in the same
30 #               directory as this script.
31 # --prefix      prefix for the OpenSSL installation, which includes the
32 #               directories bin, lib, include, share/man, share/doc/openssl
33 #               This becomes the value of INSTALLTOP in Makefile
34 #               (Default: /usr/local)
35 # --openssldir  OpenSSL data area, such as openssl.cnf, certificates and keys.
36 #               If it's a relative directory, it will be added on the directory
37 #               given with --prefix.
38 #               This becomes the value of OPENSSLDIR in Makefile and in C.
39 #               (Default: PREFIX/ssl)
40 #
41 # --cross-compile-prefix Add specified prefix to binutils components.
42 #
43 # --api         One of 0.9.8, 1.0.0 or 1.1.0.  Do not compile support for
44 #               interfaces deprecated as of the specified OpenSSL version.
45 #
46 # no-hw-xxx     do not compile support for specific crypto hardware.
47 #               Generic OpenSSL-style methods relating to this support
48 #               are always compiled but return NULL if the hardware
49 #               support isn't compiled.
50 # no-hw         do not compile support for any crypto hardware.
51 # [no-]threads  [don't] try to create a library that is suitable for
52 #               multithreaded applications (default is "threads" if we
53 #               know how to do it)
54 # [no-]shared   [don't] try to create shared libraries when supported.
55 # [no-]pic      [don't] try to build position independent code when supported.
56 #               If disabled, it also disables shared and dynamic-engine.
57 # no-asm        do not use assembler
58 # no-dso        do not compile in any native shared-library methods. This
59 #               will ensure that all methods just return NULL.
60 # no-egd        do not compile support for the entropy-gathering daemon APIs
61 # [no-]zlib     [don't] compile support for zlib compression.
62 # zlib-dynamic  Like "zlib", but the zlib library is expected to be a shared
63 #               library and will be loaded in run-time by the OpenSSL library.
64 # sctp          include SCTP support
65 # enable-weak-ssl-ciphers
66 #               Enable weak ciphers that are disabled by default.
67 # 386           generate 80386 code in assembly modules
68 # no-sse2       disables IA-32 SSE2 code in assembly modules, the above
69 #               mentioned '386' option implies this one
70 # no-<cipher>   build without specified algorithm (rsa, idea, rc5, ...)
71 # -<xxx> +<xxx> compiler options are passed through
72 # -static       while -static is also a pass-through compiler option (and
73 #               as such is limited to environments where it's actually
74 #               meaningful), it triggers a number configuration options,
75 #               namely no-dso, no-pic, no-shared and no-threads. It is
76 #               argued that the only reason to produce statically linked
77 #               binaries (and in context it means executables linked with
78 #               -static flag, and not just executables linked with static
79 #               libcrypto.a) is to eliminate dependency on specific run-time,
80 #               a.k.a. libc version. The mentioned config options are meant
81 #               to achieve just that. Unfortunately on Linux it's impossible
82 #               to eliminate the dependency completely for openssl executable
83 #               because of getaddrinfo and gethostbyname calls, which can
84 #               invoke dynamically loadable library facility anyway to meet
85 #               the lookup requests. For this reason on Linux statically
86 #               linked openssl executable has rather debugging value than
87 #               production quality.
88 #
89 # DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items
90 #               provided to stack calls. Generates unique stack functions for
91 #               each possible stack type.
92 # BN_LLONG      use the type 'long long' in crypto/bn/bn.h
93 # RC4_CHAR      use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
94 # Following are set automatically by this script
95 #
96 # MD5_ASM       use some extra md5 assembler,
97 # SHA1_ASM      use some extra sha1 assembler, must define L_ENDIAN for x86
98 # RMD160_ASM    use some extra ripemd160 assembler,
99 # SHA256_ASM    sha256_block is implemented in assembler
100 # SHA512_ASM    sha512_block is implemented in assembler
101 # AES_ASM       AES_[en|de]crypt is implemented in assembler
102
103 # Minimum warning options... any contributions to OpenSSL should at least get
104 # past these.
105
106 # DEBUG_UNUSED enables __owur (warn unused result) checks.
107 # -DPEDANTIC complements -pedantic and is meant to mask code that
108 # is not strictly standard-compliant and/or implementation-specific,
109 # e.g. inline assembly, disregards to alignment requirements, such
110 # that -pedantic would complain about. Incidentally -DPEDANTIC has
111 # to be used even in sanitized builds, because sanitizer too is
112 # supposed to and does take notice of non-standard behaviour. Then
113 # -pedantic with pre-C9x compiler would also complain about 'long
114 # long' not being supported. As 64-bit algorithms are common now,
115 # it grew impossible to resolve this without sizeable additional
116 # code, so we just tell compiler to be pedantic about everything
117 # but 'long long' type.
118
119 my $gcc_devteam_warn = "-DDEBUG_UNUSED"
120         . " -DPEDANTIC -pedantic -Wno-long-long"
121         . " -Wall"
122         . " -Wextra"
123         . " -Wno-unused-parameter"
124         . " -Wno-missing-field-initializers"
125         . " -Wswitch"
126         . " -Wsign-compare"
127         . " -Wmissing-prototypes"
128         . " -Wshadow"
129         . " -Wformat"
130         . " -Wtype-limits"
131         . " -Wundef"
132         . " -Werror"
133         ;
134
135 # These are used in addition to $gcc_devteam_warn when the compiler is clang.
136 # TODO(openssl-team): fix problems and investigate if (at least) the
137 # following warnings can also be enabled:
138 #       -Wcast-align
139 #       -Wunreachable-code -- no, too ugly/compiler-specific
140 #       -Wlanguage-extension-token -- no, we use asm()
141 #       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
142 #       -Wextended-offsetof -- no, needed in CMS ASN1 code
143 my $clang_devteam_warn = ""
144         . " -Wswitch-default"
145         . " -Wno-parentheses-equality"
146         . " -Wno-language-extension-token"
147         . " -Wno-extended-offsetof"
148         . " -Wconditional-uninitialized"
149         . " -Wincompatible-pointer-types-discards-qualifiers"
150         . " -Wmissing-variable-declarations"
151         . " -Wno-unknown-warning-option"
152         ;
153
154 # This adds backtrace information to the memory leak info.  Is only used
155 # when crypto-mdebug-backtrace is enabled.
156 my $memleak_devteam_backtrace = "-rdynamic";
157
158 my $strict_warnings = 0;
159
160 # As for $BSDthreads. Idea is to maintain "collective" set of flags,
161 # which would cover all BSD flavors. -pthread applies to them all,
162 # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
163 # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
164 # which has to be accompanied by explicit -D_THREAD_SAFE and
165 # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
166 # seems to be sufficient?
167 our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
168
169 #
170 # API compatibility name to version number mapping.
171 #
172 my $maxapi = "1.1.0";           # API for "no-deprecated" builds
173 my $apitable = {
174     "1.1.0" => "0x10100000L",
175     "1.0.0" => "0x10000000L",
176     "0.9.8" => "0x00908000L",
177 };
178
179 our %table = ();
180 our %config = ();
181 our %withargs = ();
182
183 # Forward declarations ###############################################
184
185 # read_config(filename)
186 #
187 # Reads a configuration file and populates %table with the contents
188 # (which the configuration file places in %targets).
189 sub read_config;
190
191 # resolve_config(target)
192 #
193 # Resolves all the late evaluations, inheritances and so on for the
194 # chosen target and any target it inherits from.
195 sub resolve_config;
196
197
198 # Information collection #############################################
199
200 # Unified build supports separate build dir
201 my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
202 my $blddir = catdir(absolutedir("."));         # catdir ensures local syntax
203 my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
204
205 my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
206
207 $config{sourcedir} = abs2rel($srcdir);
208 $config{builddir} = abs2rel($blddir);
209
210 # Collect reconfiguration information if needed
211 my @argvcopy=@ARGV;
212
213 if (grep /^reconf(igure)?$/, @argvcopy) {
214     if (-f "./configdata.pm") {
215         my $file = "./configdata.pm";
216         unless (my $return = do $file) {
217             die "couldn't parse $file: $@" if $@;
218             die "couldn't do $file: $!"    unless defined $return;
219             die "couldn't run $file"       unless $return;
220         }
221
222         @argvcopy = defined($configdata::config{perlargv}) ?
223             @{$configdata::config{perlargv}} : ();
224         die "Incorrect data to reconfigure, please do a normal configuration\n"
225             if (grep(/^reconf/,@argvcopy));
226         $ENV{CROSS_COMPILE} = $configdata::config{cross_compile_prefix}
227             if defined($configdata::config{cross_compile_prefix});
228         $ENV{CC} = $configdata::config{cc}
229             if defined($configdata::config{cc});
230         $ENV{CXX} = $configdata::config{cxx}
231             if defined($configdata::config{cxx});
232         $ENV{BUILDFILE} = $configdata::config{build_file}
233             if defined($configdata::config{build_file});
234         $ENV{$local_config_envname} = $configdata::config{local_config_dir}
235             if defined($configdata::config{local_config_dir});
236
237         print "Reconfiguring with: ", join(" ",@argvcopy), "\n";
238         print "    CROSS_COMPILE = ",$ENV{CROSS_COMPILE},"\n"
239             if $ENV{CROSS_COMPILE};
240         print "    CC = ",$ENV{CC},"\n" if $ENV{CC};
241         print "    CXX = ",$ENV{CXX},"\n" if $ENV{CXX};
242         print "    BUILDFILE = ",$ENV{BUILDFILE},"\n" if $ENV{BUILDFILE};
243         print "    $local_config_envname = ",$ENV{$local_config_envname},"\n"
244             if $ENV{$local_config_envname};
245     } else {
246         die "Insufficient data to reconfigure, please do a normal configuration\n";
247     }
248 }
249
250 $config{perlargv} = [ @argvcopy ];
251
252 # Collect version numbers
253 $config{version} = "unknown";
254 $config{version_num} = "unknown";
255 $config{shlib_version_number} = "unknown";
256 $config{shlib_version_history} = "unknown";
257
258 collect_information(
259     collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
260     qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
261     qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/      => sub { $config{version_num}=$1 },
262     qr/SHLIB_VERSION_NUMBER *"([^"]+)"/      => sub { $config{shlib_version_number}=$1 },
263     qr/SHLIB_VERSION_HISTORY *"([^"]*)"/     => sub { $config{shlib_version_history}=$1 }
264     );
265 if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
266
267 ($config{major}, $config{minor})
268     = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
269 ($config{shlib_major}, $config{shlib_minor})
270     = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
271 die "erroneous version information in opensslv.h: ",
272     "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
273     if ($config{major} eq "" || $config{minor} eq ""
274         || $config{shlib_major} eq "" ||  $config{shlib_minor} eq "");
275
276 # Collect target configurations
277
278 my $pattern = catfile(dirname($0), "Configurations", "*.conf");
279 foreach (sort glob($pattern)) {
280     &read_config($_);
281 }
282
283 if (defined $ENV{$local_config_envname}) {
284     if ($^O eq 'VMS') {
285         # VMS environment variables are logical names,
286         # which can be used as is
287         $pattern = $local_config_envname . ':' . '*.conf';
288     } else {
289         $pattern = catfile($ENV{$local_config_envname}, '*.conf');
290     }
291
292     foreach (sort glob($pattern)) {
293         &read_config($_);
294     }
295 }
296
297 $config{prefix}="";
298 $config{openssldir}="";
299 $config{processor}="";
300 $config{libdir}="";
301 $config{cross_compile_prefix}="";
302 my $auto_threads=1;    # enable threads automatically? true by default
303 my $default_ranlib;
304
305 # Top level directories to build
306 $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
307 # crypto/ subdirectories to build
308 $config{sdirs} = [
309     "objects",
310     "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
311     "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
312     "bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
313     "buffer", "bio", "stack", "lhash", "rand", "err",
314     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
315     "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
316     ];
317 # test/ subdirectories to build
318 $config{tdirs} = [ "ossl_shim" ];
319
320 # Known TLS and DTLS protocols
321 my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
322 my @dtls = qw(dtls1 dtls1_2);
323
324 # Explicitly known options that are possible to disable.  They can
325 # be regexps, and will be used like this: /^no-${option}$/
326 # For developers: keep it sorted alphabetically
327
328 my @disablables = (
329     "afalgeng",
330     "aria",
331     "asan",
332     "asm",
333     "async",
334     "autoalginit",
335     "autoerrinit",
336     "bf",
337     "blake2",
338     "camellia",
339     "capieng",
340     "cast",
341     "chacha",
342     "cmac",
343     "cms",
344     "comp",
345     "crypto-mdebug",
346     "crypto-mdebug-backtrace",
347     "ct",
348     "deprecated",
349     "des",
350     "devcryptoeng",
351     "dgram",
352     "dh",
353     "dsa",
354     "dso",
355     "dtls",
356     "dynamic-engine",
357     "ec",
358     "ec2m",
359     "ecdh",
360     "ecdsa",
361     "ec_nistp_64_gcc_128",
362     "egd",
363     "engine",
364     "err",
365     "external-tests",
366     "filenames",
367     "fuzz-libfuzzer",
368     "fuzz-afl",
369     "gost",
370     "heartbeats",
371     "hw(-.+)?",
372     "idea",
373     "makedepend",
374     "md2",
375     "md4",
376     "mdc2",
377     "msan",
378     "multiblock",
379     "nextprotoneg",
380     "ocb",
381     "ocsp",
382     "pic",
383     "poly1305",
384     "posix-io",
385     "psk",
386     "rc2",
387     "rc4",
388     "rc5",
389     "rdrand",
390     "rfc3779",
391     "rmd160",
392     "scrypt",
393     "sctp",
394     "seed",
395     "shared",
396     "siphash",
397     "sm3",
398     "sm4",
399     "sock",
400     "srp",
401     "srtp",
402     "sse2",
403     "ssl",
404     "ssl-trace",
405     "static-engine",
406     "stdio",
407     "tests",
408     "threads",
409     "tls",
410     "tls13downgrade",
411     "ts",
412     "ubsan",
413     "ui-console",
414     "unit-test",
415     "whirlpool",
416     "weak-ssl-ciphers",
417     "zlib",
418     "zlib-dynamic",
419     );
420 foreach my $proto ((@tls, @dtls))
421         {
422         push(@disablables, $proto);
423         push(@disablables, "$proto-method") unless $proto eq "tls1_3";
424         }
425
426 my %deprecated_disablables = (
427     "ssl2" => undef,
428     "buf-freelists" => undef,
429     "ripemd" => "rmd160",
430     "ui" => "ui-console",
431     );
432
433 # All of the following is disabled by default (RC5 was enabled before 0.9.8):
434
435 our %disabled = ( # "what"         => "comment"
436                   "aria"                => "default",
437                   "asan"                => "default",
438                   "crypto-mdebug"       => "default",
439                   "crypto-mdebug-backtrace" => "default",
440                   "devcryptoeng"        => "default",
441                   "ec_nistp_64_gcc_128" => "default",
442                   "egd"                 => "default",
443                   "external-tests"      => "default",
444                   "fuzz-libfuzzer"      => "default",
445                   "fuzz-afl"            => "default",
446                   "heartbeats"          => "default",
447                   "md2"                 => "default",
448                   "msan"                => "default",
449                   "rc5"                 => "default",
450                   "sctp"                => "default",
451                   "ssl-trace"           => "default",
452                   "ssl3"                => "default",
453                   "ssl3-method"         => "default",
454                   "ubsan"               => "default",
455           #TODO(TLS1.3): Temporarily disabled while this is a WIP
456                   "tls1_3"              => "default",
457                   "tls13downgrade"      => "default",
458                   "unit-test"           => "default",
459                   "weak-ssl-ciphers"    => "default",
460                   "zlib"                => "default",
461                   "zlib-dynamic"        => "default",
462                 );
463
464 # Note: => pair form used for aesthetics, not to truly make a hash table
465 my @disable_cascades = (
466     # "what"            => [ "cascade", ... ]
467     sub { $config{processor} eq "386" }
468                         => [ "sse2" ],
469     "ssl"               => [ "ssl3" ],
470     "ssl3-method"       => [ "ssl3" ],
471     "zlib"              => [ "zlib-dynamic" ],
472     "des"               => [ "mdc2" ],
473     "ec"                => [ "ecdsa", "ecdh" ],
474
475     "dgram"             => [ "dtls", "sctp" ],
476     "sock"              => [ "dgram" ],
477     "dtls"              => [ @dtls ],
478     sub { 0 == scalar grep { !$disabled{$_} } @dtls }
479                         => [ "dtls" ],
480
481     "tls"               => [ @tls ],
482     sub { 0 == scalar grep { !$disabled{$_} } @tls }
483                         => [ "tls" ],
484
485     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
486
487     # Without DSO, we can't load dynamic engines, so don't build them dynamic
488     "dso"               => [ "dynamic-engine" ],
489
490     # Without position independent code, there can be no shared libraries or DSOs
491     "pic"               => [ "shared" ],
492     "shared"            => [ "dynamic-engine" ],
493     "engine"            => [ "afalgeng", "devcryptoeng" ],
494
495     # no-autoalginit is only useful when building non-shared
496     "autoalginit"       => [ "shared", "apps" ],
497
498     "stdio"             => [ "apps", "capieng", "egd" ],
499     "apps"              => [ "tests" ],
500     "tests"             => [ "external-tests" ],
501     "comp"              => [ "zlib" ],
502     "ec"                => [ "tls1_3" ],
503     sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
504
505     sub { !$disabled{"msan"} } => [ "asm" ],
506     );
507
508 # Avoid protocol support holes.  Also disable all versions below N, if version
509 # N is disabled while N+1 is enabled.
510 #
511 my @list = (reverse @tls);
512 while ((my $first, my $second) = (shift @list, shift @list)) {
513     last unless @list;
514     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
515                               => [ @list ] );
516     unshift @list, $second;
517 }
518 my @list = (reverse @dtls);
519 while ((my $first, my $second) = (shift @list, shift @list)) {
520     last unless @list;
521     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
522                               => [ @list ] );
523     unshift @list, $second;
524 }
525
526 # Explicit "no-..." options will be collected in %disabled along with the defaults.
527 # To remove something from %disabled, use "enable-foo".
528 # For symmetry, "disable-foo" is a synonym for "no-foo".
529
530 my $no_sse2=0;
531
532 &usage if ($#ARGV < 0);
533
534 my $user_cflags="";
535 my @user_defines=();
536 $config{openssl_api_defines}=[];
537 $config{openssl_algorithm_defines}=[];
538 $config{openssl_thread_defines}=[];
539 $config{openssl_sys_defines}=[];
540 $config{openssl_other_defines}=[];
541 my $libs="";
542 my $target="";
543 $config{options}="";
544 $config{build_type} = "release";
545
546 my %unsupported_options = ();
547 my %deprecated_options = ();
548 # If you change this, update apps/version.c
549 my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
550 my @seed_sources = ();
551 while (@argvcopy)
552         {
553         $_ = shift @argvcopy;
554         # VMS is a case insensitive environment, and depending on settings
555         # out of our control, we may receive options uppercased.  Let's
556         # downcase at least the part before any equal sign.
557         if ($^O eq "VMS")
558                 {
559                 s/^([^=]*)/lc($1)/e;
560                 }
561         s /^-no-/no-/; # some people just can't read the instructions
562
563         # rewrite some options in "enable-..." form
564         s /^-?-?shared$/enable-shared/;
565         s /^sctp$/enable-sctp/;
566         s /^threads$/enable-threads/;
567         s /^zlib$/enable-zlib/;
568         s /^zlib-dynamic$/enable-zlib-dynamic/;
569
570         if (/^(no|disable|enable)-(.+)$/)
571                 {
572                 my $word = $2;
573                 if (!exists $deprecated_disablables{$word}
574                         && !grep { $word =~ /^${_}$/ } @disablables)
575                         {
576                         $unsupported_options{$_} = 1;
577                         next;
578                         }
579                 }
580         if (/^no-(.+)$/ || /^disable-(.+)$/)
581                 {
582                 foreach my $proto ((@tls, @dtls))
583                         {
584                         if ($1 eq "$proto-method")
585                                 {
586                                 $disabled{"$proto"} = "option($proto-method)";
587                                 last;
588                                 }
589                         }
590                 if ($1 eq "dtls")
591                         {
592                         foreach my $proto (@dtls)
593                                 {
594                                 $disabled{$proto} = "option(dtls)";
595                                 }
596                         $disabled{"dtls"} = "option(dtls)";
597                         }
598                 elsif ($1 eq "ssl")
599                         {
600                         # Last one of its kind
601                         $disabled{"ssl3"} = "option(ssl)";
602                         }
603                 elsif ($1 eq "tls")
604                         {
605                         # XXX: Tests will fail if all SSL/TLS
606                         # protocols are disabled.
607                         foreach my $proto (@tls)
608                                 {
609                                 $disabled{$proto} = "option(tls)";
610                                 }
611                         }
612                 elsif ($1 eq "static-engine")
613                         {
614                         delete $disabled{"dynamic-engine"};
615                         }
616                 elsif ($1 eq "dynamic-engine")
617                         {
618                         $disabled{"dynamic-engine"} = "option";
619                         }
620                 elsif (exists $deprecated_disablables{$1})
621                         {
622                         $deprecated_options{$_} = 1;
623                         if (defined $deprecated_disablables{$1})
624                                 {
625                                 $disabled{$deprecated_disablables{$1}} = "option";
626                                 }
627                         }
628                 else
629                         {
630                         $disabled{$1} = "option";
631                         }
632                 # No longer an automatic choice
633                 $auto_threads = 0 if ($1 eq "threads");
634                 }
635         elsif (/^enable-(.+)$/)
636                 {
637                 if ($1 eq "static-engine")
638                         {
639                         $disabled{"dynamic-engine"} = "option";
640                         }
641                 elsif ($1 eq "dynamic-engine")
642                         {
643                         delete $disabled{"dynamic-engine"};
644                         }
645                 elsif ($1 eq "zlib-dynamic")
646                         {
647                         delete $disabled{"zlib"};
648                         }
649                 my $algo = $1;
650                 delete $disabled{$algo};
651
652                 # No longer an automatic choice
653                 $auto_threads = 0 if ($1 eq "threads");
654                 }
655         elsif (/^--strict-warnings$/)
656                 {
657                 $strict_warnings = 1;
658                 }
659         elsif (/^--debug$/)
660                 {
661                 $config{build_type} = "debug";
662                 }
663         elsif (/^--release$/)
664                 {
665                 $config{build_type} = "release";
666                 }
667         elsif (/^386$/)
668                 { $config{processor}=386; }
669         elsif (/^fips$/)
670                 {
671                 die "FIPS mode not supported\n";
672                 }
673         elsif (/^rsaref$/)
674                 {
675                 # No RSAref support any more since it's not needed.
676                 # The check for the option is there so scripts aren't
677                 # broken
678                 }
679         elsif (/^nofipscanistercheck$/)
680                 {
681                 die "FIPS mode not supported\n";
682                 }
683         elsif (/^[-+]/)
684                 {
685                 if (/^--prefix=(.*)$/)
686                         {
687                         $config{prefix}=$1;
688                         die "Directory given with --prefix MUST be absolute\n"
689                                 unless file_name_is_absolute($config{prefix});
690                         }
691                 elsif (/^--api=(.*)$/)
692                         {
693                         $config{api}=$1;
694                         }
695                 elsif (/^--libdir=(.*)$/)
696                         {
697                         $config{libdir}=$1;
698                         }
699                 elsif (/^--openssldir=(.*)$/)
700                         {
701                         $config{openssldir}=$1;
702                         }
703                 elsif (/^--with-zlib-lib=(.*)$/)
704                         {
705                         $withargs{zlib_lib}=$1;
706                         }
707                 elsif (/^--with-zlib-include=(.*)$/)
708                         {
709                         $withargs{zlib_include}=$1;
710                         }
711                 elsif (/^--with-fuzzer-lib=(.*)$/)
712                         {
713                         $withargs{fuzzer_lib}=$1;
714                         }
715                 elsif (/^--with-fuzzer-include=(.*)$/)
716                         {
717                         $withargs{fuzzer_include}=$1;
718                         }
719                 elsif (/^--with-rand-seed=(.*)$/)
720                         {
721                         foreach my $x (split(m|,|, $1))
722                             {
723                             die "Unknown --with-rand-seed choice $x\n"
724                                 if ! grep { $x eq $_ } @known_seed_sources;
725                             push @seed_sources, $x;
726                             }
727                         }
728                 elsif (/^--cross-compile-prefix=(.*)$/)
729                         {
730                         $config{cross_compile_prefix}=$1;
731                         }
732                 elsif (/^--config=(.*)$/)
733                         {
734                         read_config $1;
735                         }
736                 elsif (/^-[lL](.*)$/ or /^-Wl,/)
737                         {
738                         $libs.=$_." ";
739                         }
740                 elsif (/^-framework$/)
741                         {
742                         $libs.=$_." ".shift(@argvcopy)." ";
743                         }
744                 elsif (/^-rpath$/ or /^-R$/)
745                         # -rpath is the OSF1 rpath flag
746                         # -R is the old Solaris rpath flag
747                         {
748                         my $rpath = shift(@argvcopy) || "";
749                         $rpath .= " " if $rpath ne "";
750                         $libs.=$_." ".$rpath;
751                         }
752                 elsif (/^-static$/)
753                         {
754                         $libs.=$_." ";
755                         $disabled{"dso"} = "forced";
756                         $disabled{"pic"} = "forced";
757                         $disabled{"shared"} = "forced";
758                         $disabled{"threads"} = "forced";
759                         }
760                 elsif (/^-D(.*)$/)
761                         {
762                         push @user_defines, $1;
763                         }
764                 else    # common if (/^[-+]/), just pass down...
765                         {
766                         $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
767                         $user_cflags.=" ".$_;
768                         }
769                 }
770         else
771                 {
772                 die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
773                 $target=$_;
774                 }
775         unless ($_ eq $target || /^no-/ || /^disable-/)
776                 {
777                 # "no-..." follows later after implied deactivations
778                 # have been derived.  (Don't take this too seriously,
779                 # we really only write OPTIONS to the Makefile out of
780                 # nostalgia.)
781
782                 if ($config{options} eq "")
783                         { $config{options} = $_; }
784                 else
785                         { $config{options} .= " ".$_; }
786                 }
787
788         if (defined($config{api}) && !exists $apitable->{$config{api}}) {
789                 die "***** Unsupported api compatibility level: $config{api}\n",
790         }
791
792         if (keys %deprecated_options)
793                 {
794                 warn "***** Deprecated options: ",
795                         join(", ", keys %deprecated_options), "\n";
796                 }
797         if (keys %unsupported_options)
798                 {
799                 die "***** Unsupported options: ",
800                         join(", ", keys %unsupported_options), "\n";
801                 }
802         }
803
804 if ($libs =~ /(^|\s)-Wl,-rpath,/
805     && !$disabled{shared}
806     && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
807     die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
808         "***** any of asan, msan or ubsan\n";
809 }
810
811 if (scalar(@seed_sources) == 0) {
812     print "Using implicit seed configuration\n";
813     push @seed_sources, 'os';
814 }
815 die "Cannot seed with none and anything else"
816     if scalar(grep { $_ eq 'none' } @seed_sources) > 0
817         && scalar(@seed_sources) > 1;
818 push @{$config{openssl_other_defines}},
819      map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
820         @seed_sources;
821
822 my @tocheckfor = (keys %disabled);
823 while (@tocheckfor) {
824     my %new_tocheckfor = ();
825     my @cascade_copy = (@disable_cascades);
826     while (@cascade_copy) {
827         my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy);
828         if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
829             foreach(grep { !defined($disabled{$_}) } @$descendents) {
830                 $new_tocheckfor{$_} = 1; $disabled{$_} = "forced";
831             }
832         }
833     }
834     @tocheckfor = (keys %new_tocheckfor);
835 }
836
837 our $die = sub { die @_; };
838 if ($target eq "TABLE") {
839     local $die = sub { warn @_; };
840     foreach (sort keys %table) {
841         print_table_entry($_, "TABLE");
842     }
843     exit 0;
844 }
845
846 if ($target eq "LIST") {
847     foreach (sort keys %table) {
848         print $_,"\n" unless $table{$_}->{template};
849     }
850     exit 0;
851 }
852
853 if ($target eq "HASH") {
854     local $die = sub { warn @_; };
855     print "%table = (\n";
856     foreach (sort keys %table) {
857         print_table_entry($_, "HASH");
858     }
859     exit 0;
860 }
861
862 print "Configuring OpenSSL version $config{version} ($config{version_num})\n";
863 print "for $target\n";
864
865 # Backward compatibility?
866 if ($target =~ m/^CygWin32(-.*)$/) {
867     $target = "Cygwin".$1;
868 }
869
870 # Support for legacy targets having a name starting with 'debug-'
871 my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
872 if ($d) {
873     $config{build_type} = "debug";
874
875     # If we do not find debug-foo in the table, the target is set to foo.
876     if (!$table{$target}) {
877         $target = $t;
878     }
879 }
880 $config{target} = $target;
881 my %target = resolve_config($target);
882
883 &usage if (!%target || $target{template});
884
885 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
886 $config{conf_files} = [ sort keys %conf_files ];
887 %target = ( %{$table{DEFAULTS}}, %target );
888
889 foreach my $feature (@{$target{disable}}) {
890     if (exists $deprecated_disablables{$feature}) {
891         warn "***** config $target disables deprecated feature $feature\n";
892     } elsif (!grep { $feature eq $_ } @disablables) {
893         die "***** config $target disables unknown feature $feature\n";
894     }
895     $disabled{$feature} = 'config';
896 }
897 foreach my $feature (@{$target{enable}}) {
898     if ("default" eq ($disabled{$_} // "")) {
899         if (exists $deprecated_disablables{$feature}) {
900             warn "***** config $target enables deprecated feature $feature\n";
901         } elsif (!grep { $feature eq $_ } @disablables) {
902             die "***** config $target enables unknown feature $feature\n";
903         }
904         delete $disabled{$_};
905     }
906 }
907
908 foreach (sort (keys %disabled))
909         {
910         $config{options} .= " no-$_";
911
912         printf "    no-%-12s %-10s", $_, "[$disabled{$_}]";
913
914         if (/^dso$/)
915                 { }
916         elsif (/^threads$/)
917                 { }
918         elsif (/^shared$/)
919                 { }
920         elsif (/^pic$/)
921                 { }
922         elsif (/^zlib$/)
923                 { }
924         elsif (/^dynamic-engine$/)
925                 { }
926         elsif (/^makedepend$/)
927                 { }
928         elsif (/^zlib-dynamic$/)
929                 { }
930         elsif (/^sse2$/)
931                 { $no_sse2 = 1; }
932         elsif (/^engine$/)
933                 {
934                 @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
935                 @{$config{sdirs}} = grep !/^engine$/, @{$config{sdirs}};
936                 push @{$config{openssl_other_defines}}, "OPENSSL_NO_ENGINE";
937                 print " OPENSSL_NO_ENGINE (skip engines)";
938                 }
939         else
940                 {
941                 my ($WHAT, $what);
942
943                 ($WHAT = $what = $_) =~ tr/[\-a-z]/[_A-Z]/;
944
945                 # Fix up C macro end names
946                 $WHAT = "RMD160" if $what eq "ripemd";
947
948                 # fix-up crypto/directory name(s)
949                 $what = "ripemd" if $what eq "rmd160";
950                 $what = "whrlpool" if $what eq "whirlpool";
951
952                 if ($what ne "async" && $what ne "err"
953                     && grep { $_ eq $what } @{$config{sdirs}})
954                         {
955                         push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$WHAT";
956                         @{$config{sdirs}} = grep { $_ ne $what} @{$config{sdirs}};
957
958                         print " OPENSSL_NO_$WHAT (skip dir)";
959                         }
960                 else
961                         {
962                         push @{$config{openssl_other_defines}}, "OPENSSL_NO_$WHAT";
963                         print " OPENSSL_NO_$WHAT";
964
965                         if (/^err$/)    { push @user_defines, "OPENSSL_NO_ERR"; }
966                         }
967                 }
968
969         print "\n";
970         }
971
972 $target{cxxflags}=$target{cflags} unless defined $target{cxxflags};
973 $target{exe_extension}="";
974 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
975                                   || $config{target} =~ /^(?:Cygwin|mingw)/);
976 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
977
978 ($target{shared_extension_simple}=$target{shared_extension})
979     =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||;
980 $target{dso_extension}=$target{shared_extension_simple};
981 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
982     if ($config{target} =~ /^(?:Cygwin|mingw)/);
983
984
985 $config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'}
986     if $config{cross_compile_prefix} eq "";
987
988 # Allow overriding the names of some tools.  USE WITH CARE
989 # Note: only Unix cares about HASHBANGPERL...  that explains
990 # the default string.
991 $config{perl} =    ($^O ne "VMS" ? $^X : "perl");
992 $config{hashbangperl} =
993     $ENV{'HASHBANGPERL'}           || $ENV{'PERL'}     || "/usr/bin/env perl";
994 $target{cc} =      $ENV{'CC'}      || $target{cc}      || "cc";
995 $target{cxx} =     $ENV{'CXX'}     || $target{cxx}     || "c++";
996 $target{ranlib} =  $ENV{'RANLIB'}  || $target{ranlib}  ||
997                    (which("$config{cross_compile_prefix}ranlib") ?
998                           "\$(CROSS_COMPILE)ranlib" : "true");
999 $target{ar} =      $ENV{'AR'}      || $target{ar}      || "ar";
1000 $target{nm} =      $ENV{'NM'}      || $target{nm}      || "nm";
1001 $target{rc} =
1002     $ENV{'RC'}  || $ENV{'WINDRES'} || $target{rc}      || "windres";
1003
1004 # Allow overriding the build file name
1005 $target{build_file} = $ENV{BUILDFILE} || $target{build_file} || "Makefile";
1006
1007 # Cache information necessary for reconfiguration
1008 $config{cc} = $target{cc};
1009 $config{cxx} = $target{cxx};
1010 $config{build_file} = $target{build_file};
1011
1012 # For cflags, lflags, plib_lflags, ex_libs and defines, add the debug_
1013 # or release_ attributes.
1014 # Do it in such a way that no spurious space is appended (hence the grep).
1015 $config{defines} = [];
1016 $config{cflags} = "";
1017 $config{cxxflags} = "";
1018 $config{ex_libs} = "";
1019 $config{shared_ldflag} = "";
1020
1021 # Make sure build_scheme is consistent.
1022 $target{build_scheme} = [ $target{build_scheme} ]
1023     if ref($target{build_scheme}) ne "ARRAY";
1024
1025 my ($builder, $builder_platform, @builder_opts) =
1026     @{$target{build_scheme}};
1027
1028 foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
1029                       $builder_platform."-checker.pm")) {
1030     my $checker_path = catfile($srcdir, "Configurations", $checker);
1031     if (-f $checker_path) {
1032         my $fn = $ENV{CONFIGURE_CHECKER_WARN}
1033             ? sub { warn $@; } : sub { die $@; };
1034         if (! do $checker_path) {
1035             if ($@) {
1036                 $fn->($@);
1037             } elsif ($!) {
1038                 $fn->($!);
1039             } else {
1040                 $fn->("The detected tools didn't match the platform\n");
1041             }
1042         }
1043         last;
1044     }
1045 }
1046
1047 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
1048
1049 if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` =~ m/-mno-cygwin/m)
1050         {
1051         $config{cflags} .= " -mno-cygwin";
1052         $config{shared_ldflag} .= " -mno-cygwin";
1053         }
1054
1055 if ($target =~ /linux.*-mips/ && !$disabled{asm} && $user_cflags !~ /-m(ips|arch=)/) {
1056         # minimally required architecture flags for assembly modules
1057         $config{cflags}="-mips2 $config{cflags}" if ($target =~ /mips32/);
1058         $config{cflags}="-mips3 $config{cflags}" if ($target =~ /mips64/);
1059 }
1060
1061 my $no_shared_warn=0;
1062 my $no_user_cflags=0;
1063 my $no_user_defines=0;
1064
1065 # The DSO code currently always implements all functions so that no
1066 # applications will have to worry about that from a compilation point
1067 # of view. However, the "method"s may return zero unless that platform
1068 # has support compiled in for them. Currently each method is enabled
1069 # by a define "DSO_<name>" ... we translate the "dso_scheme" config
1070 # string entry into using the following logic;
1071 if (!$disabled{dso} && $target{dso_scheme} ne "")
1072         {
1073         $target{dso_scheme} =~ tr/[a-z]/[A-Z]/;
1074         if ($target{dso_scheme} eq "DLFCN")
1075                 {
1076                 unshift @{$config{defines}}, "DSO_DLFCN", "HAVE_DLFCN_H";
1077                 }
1078         elsif ($target{dso_scheme} eq "DLFCN_NO_H")
1079                 {
1080                 unshift @{$config{defines}}, "DSO_DLFCN";
1081                 }
1082         else
1083                 {
1084                 unshift @{$config{defines}}, "DSO_$target{dso_scheme}";
1085                 }
1086         }
1087
1088 $config{ex_libs}="$libs$config{ex_libs}" if ($libs ne "");
1089
1090 # If threads aren't disabled, check how possible they are
1091 unless ($disabled{threads}) {
1092     if ($auto_threads) {
1093         # Enabled by default, disable it forcibly if unavailable
1094         if ($target{thread_scheme} eq "(unknown)") {
1095             $disabled{threads} = "unavailable";
1096         }
1097     } else {
1098         # The user chose to enable threads explicitly, let's see
1099         # if there's a chance that's possible
1100         if ($target{thread_scheme} eq "(unknown)") {
1101             # If the user asked for "threads" and we don't have internal
1102             # knowledge how to do it, [s]he is expected to provide any
1103             # system-dependent compiler options that are necessary.  We
1104             # can't truly check that the given options are correct, but
1105             # we expect the user to know what [s]He is doing.
1106             if ($no_user_cflags && $no_user_defines) {
1107                 die "You asked for multi-threading support, but didn't\n"
1108                     ,"provide any system-specific compiler options\n";
1109             }
1110         }
1111     }
1112 }
1113
1114 # If threads still aren't disabled, add a C macro to ensure the source
1115 # code knows about it.  Any other flag is taken care of by the configs.
1116 unless($disabled{threads}) {
1117     foreach (("defines", "openssl_thread_defines")) {
1118         push @{$config{$_}}, "OPENSSL_THREADS";
1119     }
1120 }
1121
1122 # With "deprecated" disable all deprecated features.
1123 if (defined($disabled{"deprecated"})) {
1124         $config{api} = $maxapi;
1125 }
1126
1127 if ($target{shared_target} eq "")
1128         {
1129         $no_shared_warn = 1
1130             if (!$disabled{shared} || !$disabled{"dynamic-engine"});
1131         $disabled{shared} = "no-shared-target";
1132         $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
1133             "no-shared-target";
1134         }
1135
1136 if ($disabled{"dynamic-engine"}) {
1137         push @{$config{defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
1138         $config{dynamic_engines} = 0;
1139 } else {
1140         push @{$config{defines}}, "OPENSSL_NO_STATIC_ENGINE";
1141         $config{dynamic_engines} = 1;
1142 }
1143
1144 unless ($disabled{asan}) {
1145     $config{cflags} .= "-fsanitize=address ";
1146 }
1147
1148 unless ($disabled{ubsan}) {
1149     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
1150     # platforms.
1151     $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all ";
1152 }
1153
1154 unless ($disabled{msan}) {
1155   $config{cflags} .= "-fsanitize=memory ";
1156 }
1157
1158 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
1159         && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
1160     $config{cflags} .= "-fno-omit-frame-pointer -g ";
1161 }
1162 #
1163 # Platform fix-ups
1164 #
1165
1166 # This saves the build files from having to check
1167 if ($disabled{pic})
1168         {
1169         $target{shared_cflag} = $target{shared_ldflag} =
1170                 $target{shared_rcflag} = "";
1171         }
1172 else
1173         {
1174         push @{$config{defines}}, "OPENSSL_PIC";
1175         }
1176
1177 if ($target{sys_id} ne "")
1178         {
1179         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1180         }
1181
1182 unless ($disabled{asm}) {
1183     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1184     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1185
1186     # bn-586 is the only one implementing bn_*_part_words
1187     push @{$config{defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1188     push @{$config{defines}}, "OPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/);
1189
1190     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1191     push @{$config{defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1192     push @{$config{defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1193
1194     if ($target{sha1_asm_src}) {
1195         push @{$config{defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1196         push @{$config{defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1197         push @{$config{defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1198     }
1199     if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
1200         push @{$config{defines}}, "RC4_ASM";
1201     }
1202     if ($target{md5_asm_src}) {
1203         push @{$config{defines}}, "MD5_ASM";
1204     }
1205     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1206     if ($target{rmd160_asm_src}) {
1207         push @{$config{defines}}, "RMD160_ASM";
1208     }
1209     if ($target{aes_asm_src}) {
1210         push @{$config{defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1211         # aes-ctr.fake is not a real file, only indication that assembler
1212         # module implements AES_ctr32_encrypt...
1213         push @{$config{defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1214         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1215         push @{$config{defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1216         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2);
1217         push @{$config{defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1218         push @{$config{defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1219     }
1220     if ($target{wp_asm_src} =~ /mmx/) {
1221         if ($config{processor} eq "386") {
1222             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1223         } elsif (!$disabled{"whirlpool"}) {
1224             push @{$config{defines}}, "WHIRLPOOL_ASM";
1225         }
1226     }
1227     if ($target{modes_asm_src} =~ /ghash-/) {
1228         push @{$config{defines}}, "GHASH_ASM";
1229     }
1230     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1231         push @{$config{defines}}, "ECP_NISTZ256_ASM";
1232     }
1233     if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
1234         push @{$config{defines}}, "PADLOCK_ASM";
1235     }
1236     if ($target{poly1305_asm_src} ne "") {
1237         push @{$config{defines}}, "POLY1305_ASM";
1238     }
1239 }
1240
1241 my %predefined;
1242
1243 if ($^O ne "VMS") {
1244     my $cc = "$config{cross_compile_prefix}$target{cc}";
1245
1246     # collect compiler pre-defines from gcc or gcc-alike...
1247     open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
1248     while (<PIPE>) {
1249         m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
1250         $predefined{$1} = $2 // "";
1251     }
1252     close(PIPE);
1253
1254     if (!$disabled{makedepend}) {
1255         # We know that GNU C version 3 and up as well as all clang
1256         # versions support dependency generation
1257         if ($predefined{__GNUC__} >= 3) {
1258             $config{makedepprog} = $cc;
1259         } else {
1260             $config{makedepprog} = which('makedepend');
1261             $disabled{makedepend} = "unavailable" unless $config{makedepprog};
1262         }
1263     }
1264 }
1265
1266
1267
1268 # Deal with bn_ops ###################################################
1269
1270 $config{bn_ll}                  =0;
1271 $config{export_var_as_fn}       =0;
1272 my $def_int="unsigned int";
1273 $config{rc4_int}                =$def_int;
1274 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1275
1276 my $count = 0;
1277 foreach (sort split(/\s+/,$target{bn_ops})) {
1278     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1279     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1280     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1281     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1282     ($config{b64l},$config{b64},$config{b32})
1283         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1284     ($config{b64l},$config{b64},$config{b32})
1285         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1286     ($config{b64l},$config{b64},$config{b32})
1287         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1288 }
1289 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1290     if $count > 1;
1291
1292
1293 # Hack cflags for better warnings (dev option) #######################
1294
1295 # "Stringify" the C flags string.  This permits it to be made part of a string
1296 # and works as well on command lines.
1297 $config{cflags} =~ s/([\\\"])/\\$1/g;
1298
1299 if (defined($config{api})) {
1300     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1301     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1302     push @{$config{defines}}, $apiflag;
1303 }
1304
1305 if (defined($predefined{__clang__}) && !$disabled{asm}) {
1306     $config{cflags} .= " -Qunused-arguments";
1307 }
1308
1309 if ($strict_warnings)
1310         {
1311         my $wopt;
1312         my $gccver = $predefined{__GNUC__} // -1;
1313
1314         die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike"
1315             unless $gccver >= 4;
1316         $gcc_devteam_warn .= " -Wmisleading-indentation" if $gccver >= 6;
1317         foreach $wopt (split /\s+/, $gcc_devteam_warn)
1318                 {
1319                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1320                 }
1321         if (defined($predefined{__clang__}))
1322                 {
1323                 foreach $wopt (split /\s+/, $clang_devteam_warn)
1324                         {
1325                         $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1326                         }
1327                 }
1328         }
1329
1330 unless ($disabled{"crypto-mdebug-backtrace"})
1331         {
1332         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1333                 {
1334                 $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(?:^|\s)$wopt(?:\s|$)/)
1335                 }
1336         if ($target =~ /^BSD-/)
1337                 {
1338                 $config{ex_libs} .= " -lexecinfo";
1339                 }
1340         }
1341
1342 if ($user_cflags ne "") { $config{cflags}="$config{cflags}$user_cflags"; $config{cxxflags}="$config{cxxflags}$user_cflags";}
1343 else                    { $no_user_cflags=1;  }
1344 if (@user_defines) { $config{defines}=[ @{$config{defines}}, @user_defines ]; }
1345 else               { $no_user_defines=1;    }
1346
1347 # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
1348
1349 unless ($disabled{afalgeng}) {
1350     $config{afalgeng}="";
1351     if ($target =~ m/^linux/) {
1352         my $minver = 4*10000 + 1*100 + 0;
1353         if ($config{cross_compile_prefix} eq "") {
1354             my $verstr = `uname -r`;
1355             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1356             ($mi2) = $mi2 =~ /(\d+)/;
1357             my $ver = $ma*10000 + $mi1*100 + $mi2;
1358             if ($ver < $minver) {
1359                 $disabled{afalgeng} = "too-old-kernel";
1360             } else {
1361                 push @{$config{engdirs}}, "afalg";
1362             }
1363         } else {
1364             $disabled{afalgeng} = "cross-compiling";
1365         }
1366     } else {
1367         $disabled{afalgeng}  = "not-linux";
1368     }
1369 }
1370
1371 push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
1372
1373 # If we use the unified build, collect information from build.info files
1374 my %unified_info = ();
1375
1376 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1377 if ($builder eq "unified") {
1378     use with_fallback qw(Text::Template);
1379
1380     sub cleandir {
1381         my $base = shift;
1382         my $dir = shift;
1383         my $relativeto = shift || ".";
1384
1385         $dir = catdir($base,$dir) unless isabsolute($dir);
1386
1387         # Make sure the directories we're building in exists
1388         mkpath($dir);
1389
1390         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1391         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1392         return $res;
1393     }
1394
1395     sub cleanfile {
1396         my $base = shift;
1397         my $file = shift;
1398         my $relativeto = shift || ".";
1399
1400         $file = catfile($base,$file) unless isabsolute($file);
1401
1402         my $d = dirname($file);
1403         my $f = basename($file);
1404
1405         # Make sure the directories we're building in exists
1406         mkpath($d);
1407
1408         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1409         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1410         return $res;
1411     }
1412
1413     # Store the name of the template file we will build the build file from
1414     # in %config.  This may be useful for the build file itself.
1415     my @build_file_template_names =
1416         ( $builder_platform."-".$target{build_file}.".tmpl",
1417           $target{build_file}.".tmpl" );
1418     my @build_file_templates = ();
1419
1420     # First, look in the user provided directory, if given
1421     if (defined $ENV{$local_config_envname}) {
1422         @build_file_templates =
1423             map {
1424                 if ($^O eq 'VMS') {
1425                     # VMS environment variables are logical names,
1426                     # which can be used as is
1427                     $local_config_envname . ':' . $_;
1428                 } else {
1429                     catfile($ENV{$local_config_envname}, $_);
1430                 }
1431             }
1432             @build_file_template_names;
1433     }
1434     # Then, look in our standard directory
1435     push @build_file_templates,
1436         ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
1437           @build_file_template_names );
1438
1439     my $build_file_template;
1440     for $_ (@build_file_templates) {
1441         $build_file_template = $_;
1442         last if -f $build_file_template;
1443
1444         $build_file_template = undef;
1445     }
1446     if (!defined $build_file_template) {
1447         die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
1448     }
1449     $config{build_file_templates}
1450       = [ $build_file_template,
1451           cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
1452                     $blddir) ];
1453
1454     my @build_infos = ( [ ".", "build.info" ] );
1455     foreach (@{$config{dirs}}) {
1456         push @build_infos, [ $_, "build.info" ]
1457             if (-f catfile($srcdir, $_, "build.info"));
1458     }
1459     foreach (@{$config{sdirs}}) {
1460         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1461             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1462     }
1463     foreach (@{$config{engdirs}}) {
1464         push @build_infos, [ catdir("engines", $_), "build.info" ]
1465             if (-f catfile($srcdir, "engines", $_, "build.info"));
1466     }
1467     foreach (@{$config{tdirs}}) {
1468         push @build_infos, [ catdir("test", $_), "build.info" ]
1469             if (-f catfile($srcdir, "test", $_, "build.info"));
1470     }
1471
1472     $config{build_infos} = [ ];
1473
1474     foreach (@build_infos) {
1475         my $sourced = catdir($srcdir, $_->[0]);
1476         my $buildd = catdir($blddir, $_->[0]);
1477
1478         mkpath($buildd);
1479
1480         my $f = $_->[1];
1481         # The basic things we're trying to build
1482         my @programs = ();
1483         my @programs_install = ();
1484         my @libraries = ();
1485         my @libraries_install = ();
1486         my @engines = ();
1487         my @engines_install = ();
1488         my @scripts = ();
1489         my @scripts_install = ();
1490         my @extra = ();
1491         my @overrides = ();
1492         my @intermediates = ();
1493         my @rawlines = ();
1494
1495         my %ordinals = ();
1496         my %sources = ();
1497         my %shared_sources = ();
1498         my %includes = ();
1499         my %depends = ();
1500         my %renames = ();
1501         my %sharednames = ();
1502         my %generate = ();
1503
1504         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1505         my $template =
1506             Text::Template->new(TYPE => 'FILE',
1507                                 SOURCE => catfile($sourced, $f),
1508                                 PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
1509         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1510         my @text =
1511             split /^/m,
1512             $template->fill_in(HASH => { config => \%config,
1513                                          target => \%target,
1514                                          disabled => \%disabled,
1515                                          withargs => \%withargs,
1516                                          builddir => abs2rel($buildd, $blddir),
1517                                          sourcedir => abs2rel($sourced, $blddir),
1518                                          buildtop => abs2rel($blddir, $blddir),
1519                                          sourcetop => abs2rel($srcdir, $blddir) },
1520                                DELIMITERS => [ "{-", "-}" ]);
1521
1522         # The top item of this stack has the following values
1523         # -2 positive already run and we found ELSE (following ELSIF should fail)
1524         # -1 positive already run (skip until ENDIF)
1525         # 0 negatives so far (if we're at a condition, check it)
1526         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1527         # 2 positive ELSE (following ELSIF should fail)
1528         my @skip = ();
1529         collect_information(
1530             collect_from_array([ @text ],
1531                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1532                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1533             # Info we're looking for
1534             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1535             => sub {
1536                 if (! @skip || $skip[$#skip] > 0) {
1537                     push @skip, !! $1;
1538                 } else {
1539                     push @skip, -1;
1540                 }
1541             },
1542             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1543             => sub { die "ELSIF out of scope" if ! @skip;
1544                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1545                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1546                      $skip[$#skip] = !! $1
1547                          if $skip[$#skip] == 0; },
1548             qr/^\s*ELSE\s*$/
1549             => sub { die "ELSE out of scope" if ! @skip;
1550                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1551                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1552             qr/^\s*ENDIF\s*$/
1553             => sub { die "ENDIF out of scope" if ! @skip;
1554                      pop @skip; },
1555             qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
1556             => sub {
1557                 if (!@skip || $skip[$#skip] > 0) {
1558                     my $install = $1;
1559                     my @x = tokenize($2);
1560                     push @programs, @x;
1561                     push @programs_install, @x unless $install;
1562                 }
1563             },
1564             qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
1565             => sub {
1566                 if (!@skip || $skip[$#skip] > 0) {
1567                     my $install = $1;
1568                     my @x = tokenize($2);
1569                     push @libraries, @x;
1570                     push @libraries_install, @x unless $install;
1571                 }
1572             },
1573             qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
1574             => sub {
1575                 if (!@skip || $skip[$#skip] > 0) {
1576                     my $install = $1;
1577                     my @x = tokenize($2);
1578                     push @engines, @x;
1579                     push @engines_install, @x unless $install;
1580                 }
1581             },
1582             qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
1583             => sub {
1584                 if (!@skip || $skip[$#skip] > 0) {
1585                     my $install = $1;
1586                     my @x = tokenize($2);
1587                     push @scripts, @x;
1588                     push @scripts_install, @x unless $install;
1589                 }
1590             },
1591             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1592             => sub { push @extra, tokenize($1)
1593                          if !@skip || $skip[$#skip] > 0 },
1594             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1595             => sub { push @overrides, tokenize($1)
1596                          if !@skip || $skip[$#skip] > 0 },
1597
1598             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1599             => sub { push @{$ordinals{$1}}, tokenize($2)
1600                          if !@skip || $skip[$#skip] > 0 },
1601             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1602             => sub { push @{$sources{$1}}, tokenize($2)
1603                          if !@skip || $skip[$#skip] > 0 },
1604             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1605             => sub { push @{$shared_sources{$1}}, tokenize($2)
1606                          if !@skip || $skip[$#skip] > 0 },
1607             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1608             => sub { push @{$includes{$1}}, tokenize($2)
1609                          if !@skip || $skip[$#skip] > 0 },
1610             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
1611             => sub { push @{$depends{$1}}, tokenize($2)
1612                          if !@skip || $skip[$#skip] > 0 },
1613             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1614             => sub { push @{$generate{$1}}, $2
1615                          if !@skip || $skip[$#skip] > 0 },
1616             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1617             => sub { push @{$renames{$1}}, tokenize($2)
1618                          if !@skip || $skip[$#skip] > 0 },
1619             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1620             => sub { push @{$sharednames{$1}}, tokenize($2)
1621                          if !@skip || $skip[$#skip] > 0 },
1622             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1623             => sub {
1624                 my $lineiterator = shift;
1625                 my $target_kind = $1;
1626                 while (defined $lineiterator->()) {
1627                     s|\R$||;
1628                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1629                         die "ENDRAW doesn't match BEGINRAW"
1630                             if $1 ne $target_kind;
1631                         last;
1632                     }
1633                     next if @skip && $skip[$#skip] <= 0;
1634                     push @rawlines,  $_
1635                         if ($target_kind eq $target{build_file}
1636                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1637                 }
1638             },
1639             qr/^\s*(?:#.*)?$/ => sub { },
1640             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1641             "BEFORE" => sub {
1642                 if ($buildinfo_debug) {
1643                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1644                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1645                 }
1646             },
1647             "AFTER" => sub {
1648                 if ($buildinfo_debug) {
1649                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1650                 }
1651             },
1652             );
1653         die "runaway IF?" if (@skip);
1654
1655         foreach (keys %renames) {
1656             die "$_ renamed to more than one thing: "
1657                 ,join(" ", @{$renames{$_}}),"\n"
1658                 if scalar @{$renames{$_}} > 1;
1659             my $dest = cleanfile($buildd, $_, $blddir);
1660             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1661             die "$dest renamed to more than one thing: "
1662                 ,$unified_info{rename}->{$dest}, $to
1663                 unless !defined($unified_info{rename}->{$dest})
1664                 or $unified_info{rename}->{$dest} eq $to;
1665             $unified_info{rename}->{$dest} = $to;
1666         }
1667
1668         foreach (@programs) {
1669             my $program = cleanfile($buildd, $_, $blddir);
1670             if ($unified_info{rename}->{$program}) {
1671                 $program = $unified_info{rename}->{$program};
1672             }
1673             $unified_info{programs}->{$program} = 1;
1674         }
1675
1676         foreach (@programs_install) {
1677             my $program = cleanfile($buildd, $_, $blddir);
1678             if ($unified_info{rename}->{$program}) {
1679                 $program = $unified_info{rename}->{$program};
1680             }
1681             $unified_info{install}->{programs}->{$program} = 1;
1682         }
1683
1684         foreach (@libraries) {
1685             my $library = cleanfile($buildd, $_, $blddir);
1686             if ($unified_info{rename}->{$library}) {
1687                 $library = $unified_info{rename}->{$library};
1688             }
1689             $unified_info{libraries}->{$library} = 1;
1690         }
1691
1692         foreach (@libraries_install) {
1693             my $library = cleanfile($buildd, $_, $blddir);
1694             if ($unified_info{rename}->{$library}) {
1695                 $library = $unified_info{rename}->{$library};
1696             }
1697             $unified_info{install}->{libraries}->{$library} = 1;
1698         }
1699
1700         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
1701 ENGINES can only be used if configured with 'dynamic-engine'.
1702 This is usually a fault in a build.info file.
1703 EOF
1704         foreach (@engines) {
1705             my $library = cleanfile($buildd, $_, $blddir);
1706             if ($unified_info{rename}->{$library}) {
1707                 $library = $unified_info{rename}->{$library};
1708             }
1709             $unified_info{engines}->{$library} = 1;
1710         }
1711
1712         foreach (@engines_install) {
1713             my $library = cleanfile($buildd, $_, $blddir);
1714             if ($unified_info{rename}->{$library}) {
1715                 $library = $unified_info{rename}->{$library};
1716             }
1717             $unified_info{install}->{engines}->{$library} = 1;
1718         }
1719
1720         foreach (@scripts) {
1721             my $script = cleanfile($buildd, $_, $blddir);
1722             if ($unified_info{rename}->{$script}) {
1723                 $script = $unified_info{rename}->{$script};
1724             }
1725             $unified_info{scripts}->{$script} = 1;
1726         }
1727
1728         foreach (@scripts_install) {
1729             my $script = cleanfile($buildd, $_, $blddir);
1730             if ($unified_info{rename}->{$script}) {
1731                 $script = $unified_info{rename}->{$script};
1732             }
1733             $unified_info{install}->{scripts}->{$script} = 1;
1734         }
1735
1736         foreach (@extra) {
1737             my $extra = cleanfile($buildd, $_, $blddir);
1738             $unified_info{extra}->{$extra} = 1;
1739         }
1740
1741         foreach (@overrides) {
1742             my $override = cleanfile($buildd, $_, $blddir);
1743             $unified_info{overrides}->{$override} = 1;
1744         }
1745
1746         push @{$unified_info{rawlines}}, @rawlines;
1747
1748         unless ($disabled{shared}) {
1749             # Check sharednames.
1750             foreach (keys %sharednames) {
1751                 my $dest = cleanfile($buildd, $_, $blddir);
1752                 if ($unified_info{rename}->{$dest}) {
1753                     $dest = $unified_info{rename}->{$dest};
1754                 }
1755                 die "shared_name for $dest with multiple values: "
1756                     ,join(" ", @{$sharednames{$_}}),"\n"
1757                     if scalar @{$sharednames{$_}} > 1;
1758                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
1759                 die "shared_name found for a library $dest that isn't defined\n"
1760                     unless $unified_info{libraries}->{$dest};
1761                 die "shared_name for $dest with multiple values: "
1762                     ,$unified_info{sharednames}->{$dest}, ", ", $to
1763                     unless !defined($unified_info{sharednames}->{$dest})
1764                     or $unified_info{sharednames}->{$dest} eq $to;
1765                 $unified_info{sharednames}->{$dest} = $to;
1766             }
1767
1768             # Additionally, we set up sharednames for libraries that don't
1769             # have any, as themselves.  Only for libraries that aren't
1770             # explicitly static.
1771             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
1772                 if (!defined $unified_info{sharednames}->{$_}) {
1773                     $unified_info{sharednames}->{$_} = $_
1774                 }
1775             }
1776
1777             # Check that we haven't defined any library as both shared and
1778             # explicitly static.  That is forbidden.
1779             my @doubles = ();
1780             foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
1781                 (my $l = $_) =~ s/\.a$//;
1782                 push @doubles, $l if defined $unified_info{sharednames}->{$l};
1783             }
1784             die "these libraries are both explicitly static and shared:\n  ",
1785                 join(" ", @doubles), "\n"
1786                 if @doubles;
1787         }
1788
1789         foreach (keys %ordinals) {
1790             my $dest = $_;
1791             my $ddest = cleanfile($buildd, $_, $blddir);
1792             if ($unified_info{rename}->{$ddest}) {
1793                 $ddest = $unified_info{rename}->{$ddest};
1794             }
1795             foreach (@{$ordinals{$dest}}) {
1796                 my %known_ordinals =
1797                     (
1798                      crypto =>
1799                      cleanfile($sourced, catfile("util", "libcrypto.num"), $blddir),
1800                      ssl =>
1801                      cleanfile($sourced, catfile("util", "libssl.num"), $blddir)
1802                     );
1803                 my $o = $known_ordinals{$_};
1804                 die "Ordinals for $ddest defined more than once\n"
1805                     if $unified_info{ordinals}->{$ddest};
1806                 $unified_info{ordinals}->{$ddest} = [ $_, $o ];
1807             }
1808         }
1809
1810         foreach (keys %sources) {
1811             my $dest = $_;
1812             my $ddest = cleanfile($buildd, $_, $blddir);
1813             if ($unified_info{rename}->{$ddest}) {
1814                 $ddest = $unified_info{rename}->{$ddest};
1815             }
1816             foreach (@{$sources{$dest}}) {
1817                 my $s = cleanfile($sourced, $_, $blddir);
1818
1819                 # If it isn't in the source tree, we assume it's generated
1820                 # in the build tree
1821                 if (! -f $s) {
1822                     $s = cleanfile($buildd, $_, $blddir);
1823                 }
1824                 # We recognise C++, C and asm files
1825                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
1826                     my $o = $_;
1827                     $o =~ s/\.[csS]$/.o/; # C and assembler
1828                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
1829                     $o = cleanfile($buildd, $o, $blddir);
1830                     $unified_info{sources}->{$ddest}->{$o} = 1;
1831                     $unified_info{sources}->{$o}->{$s} = 1;
1832                 } else {
1833                     $unified_info{sources}->{$ddest}->{$s} = 1;
1834                 }
1835             }
1836         }
1837
1838         foreach (keys %shared_sources) {
1839             my $dest = $_;
1840             my $ddest = cleanfile($buildd, $_, $blddir);
1841             if ($unified_info{rename}->{$ddest}) {
1842                 $ddest = $unified_info{rename}->{$ddest};
1843             }
1844             foreach (@{$shared_sources{$dest}}) {
1845                 my $s = cleanfile($sourced, $_, $blddir);
1846
1847                 # If it isn't in the source tree, we assume it's generated
1848                 # in the build tree
1849                 if (! -f $s) {
1850                     $s = cleanfile($buildd, $_, $blddir);
1851                 }
1852                 # We recognise C++, C and asm files
1853                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
1854                     my $o = $_;
1855                     $o =~ s/\.[csS]$/.o/; # C and assembler
1856                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
1857                     $o = cleanfile($buildd, $o, $blddir);
1858                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
1859                     $unified_info{sources}->{$o}->{$s} = 1;
1860                 } else {
1861                     die "unrecognised source file type for shared library: $s\n";
1862                 }
1863             }
1864         }
1865
1866         foreach (keys %generate) {
1867             my $dest = $_;
1868             my $ddest = cleanfile($buildd, $_, $blddir);
1869             if ($unified_info{rename}->{$ddest}) {
1870                 $ddest = $unified_info{rename}->{$ddest};
1871             }
1872             die "more than one generator for $dest: "
1873                     ,join(" ", @{$generate{$_}}),"\n"
1874                     if scalar @{$generate{$_}} > 1;
1875             my @generator = split /\s+/, $generate{$dest}->[0];
1876             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
1877             $unified_info{generate}->{$ddest} = [ @generator ];
1878         }
1879
1880         foreach (keys %depends) {
1881             my $dest = $_;
1882             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
1883
1884             # If the destination doesn't exist in source, it can only be
1885             # a generated file in the build tree.
1886             if ($ddest ne "" && ! -f $ddest) {
1887                 $ddest = cleanfile($buildd, $_, $blddir);
1888                 if ($unified_info{rename}->{$ddest}) {
1889                     $ddest = $unified_info{rename}->{$ddest};
1890                 }
1891             }
1892             foreach (@{$depends{$dest}}) {
1893                 my $d = cleanfile($sourced, $_, $blddir);
1894
1895                 # If we know it's generated, or assume it is because we can't
1896                 # find it in the source tree, we set file we depend on to be
1897                 # in the build tree rather than the source tree, and assume
1898                 # and that there are lines to build it in a BEGINRAW..ENDRAW
1899                 # section or in the Makefile template.
1900                 if (! -f $d
1901                     || (grep { $d eq $_ }
1902                         map { cleanfile($srcdir, $_, $blddir) }
1903                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
1904                     $d = cleanfile($buildd, $_, $blddir);
1905                 }
1906                 # Take note if the file to depend on is being renamed
1907                 # Take extra care with files ending with .a, they should
1908                 # be treated without that extension, and the extension
1909                 # should be added back after treatment.
1910                 $d =~ /(\.a)?$/;
1911                 my $e = $1 // "";
1912                 $d = $`;
1913                 if ($unified_info{rename}->{$d}) {
1914                     $d = $unified_info{rename}->{$d};
1915                 }
1916                 $d .= $e;
1917                 $unified_info{depends}->{$ddest}->{$d} = 1;
1918                 # If we depend on a header file or a perl module, let's make
1919                 # sure it can get included
1920                 if ($dest ne "" && $d =~ /\.(h|pm)$/) {
1921                     my $i = dirname($d);
1922                     push @{$unified_info{includes}->{$ddest}->{source}}, $i
1923                         unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}->{source}};
1924                 }
1925             }
1926         }
1927
1928         foreach (keys %includes) {
1929             my $dest = $_;
1930             my $ddest = cleanfile($sourced, $_, $blddir);
1931
1932             # If the destination doesn't exist in source, it can only be
1933             # a generated file in the build tree.
1934             if (! -f $ddest) {
1935                 $ddest = cleanfile($buildd, $_, $blddir);
1936                 if ($unified_info{rename}->{$ddest}) {
1937                     $ddest = $unified_info{rename}->{$ddest};
1938                 }
1939             }
1940             foreach (@{$includes{$dest}}) {
1941                 my $is = cleandir($sourced, $_, $blddir);
1942                 my $ib = cleandir($buildd, $_, $blddir);
1943                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
1944                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
1945                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
1946                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
1947             }
1948         }
1949     }
1950
1951     ### Make unified_info a bit more efficient
1952     # One level structures
1953     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
1954         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
1955     }
1956     # Two level structures
1957     foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
1958         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
1959             $unified_info{$l1}->{$l2} =
1960                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
1961         }
1962     }
1963     # Includes
1964     foreach my $dest (sort keys %{$unified_info{includes}}) {
1965         if (defined($unified_info{includes}->{$dest}->{build})) {
1966             my @source_includes =
1967                 ( @{$unified_info{includes}->{$dest}->{source}} );
1968             $unified_info{includes}->{$dest} =
1969                 [ @{$unified_info{includes}->{$dest}->{build}} ];
1970             foreach my $inc (@source_includes) {
1971                 push @{$unified_info{includes}->{$dest}}, $inc
1972                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
1973             }
1974         } else {
1975             $unified_info{includes}->{$dest} =
1976                 [ @{$unified_info{includes}->{$dest}->{source}} ];
1977         }
1978     }
1979 }
1980
1981 # For the schemes that need it, we provide the old *_obj configs
1982 # from the *_asm_obj ones
1983 foreach (grep /_(asm|aux)_src$/, keys %target) {
1984     my $src = $_;
1985     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
1986     $target{$obj} = $target{$src};
1987     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
1988     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
1989 }
1990
1991 # Write down our configuration where it fits #########################
1992
1993 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
1994 print OUT <<"EOF";
1995 package configdata;
1996
1997 use strict;
1998 use warnings;
1999
2000 use Exporter;
2001 #use vars qw(\@ISA \@EXPORT);
2002 our \@ISA = qw(Exporter);
2003 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
2004
2005 EOF
2006 print OUT "our %config = (\n";
2007 foreach (sort keys %config) {
2008     if (ref($config{$_}) eq "ARRAY") {
2009         print OUT "  ", $_, " => [ ", join(", ",
2010                                            map { quotify("perl", $_) }
2011                                            @{$config{$_}}), " ],\n";
2012     } else {
2013         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
2014     }
2015 }
2016 print OUT <<"EOF";
2017 );
2018
2019 EOF
2020 print OUT "our %target = (\n";
2021 foreach (sort keys %target) {
2022     if (ref($target{$_}) eq "ARRAY") {
2023         print OUT "  ", $_, " => [ ", join(", ",
2024                                            map { quotify("perl", $_) }
2025                                            @{$target{$_}}), " ],\n";
2026     } else {
2027         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
2028     }
2029 }
2030 print OUT <<"EOF";
2031 );
2032
2033 EOF
2034 print OUT "our \%available_protocols = (\n";
2035 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
2036 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
2037 print OUT <<"EOF";
2038 );
2039
2040 EOF
2041 print OUT "our \@disablables = (\n";
2042 foreach (@disablables) {
2043     print OUT "  ", quotify("perl", $_), ",\n";
2044 }
2045 print OUT <<"EOF";
2046 );
2047
2048 EOF
2049 print OUT "our \%disabled = (\n";
2050 foreach (sort keys %disabled) {
2051     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
2052 }
2053 print OUT <<"EOF";
2054 );
2055
2056 EOF
2057 print OUT "our %withargs = (\n";
2058 foreach (sort keys %withargs) {
2059     if (ref($withargs{$_}) eq "ARRAY") {
2060         print OUT "  ", $_, " => [ ", join(", ",
2061                                            map { quotify("perl", $_) }
2062                                            @{$withargs{$_}}), " ],\n";
2063     } else {
2064         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
2065     }
2066 }
2067 print OUT <<"EOF";
2068 );
2069
2070 EOF
2071 if ($builder eq "unified") {
2072     my $recurse;
2073     $recurse = sub {
2074         my $indent = shift;
2075         foreach (@_) {
2076             if (ref $_ eq "ARRAY") {
2077                 print OUT " "x$indent, "[\n";
2078                 foreach (@$_) {
2079                     $recurse->($indent + 4, $_);
2080                 }
2081                 print OUT " "x$indent, "],\n";
2082             } elsif (ref $_ eq "HASH") {
2083                 my %h = %$_;
2084                 print OUT " "x$indent, "{\n";
2085                 foreach (sort keys %h) {
2086                     if (ref $h{$_} eq "") {
2087                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
2088                     } else {
2089                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
2090                         $recurse->($indent + 8, $h{$_});
2091                     }
2092                 }
2093                 print OUT " "x$indent, "},\n";
2094             } else {
2095                 print OUT " "x$indent, quotify("perl", $_), ",\n";
2096             }
2097         }
2098     };
2099     print OUT "our %unified_info = (\n";
2100     foreach (sort keys %unified_info) {
2101         if (ref $unified_info{$_} eq "") {
2102             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
2103         } else {
2104             print OUT " "x4, quotify("perl", $_), " =>\n";
2105             $recurse->(8, $unified_info{$_});
2106         }
2107     }
2108     print OUT <<"EOF";
2109 );
2110
2111 EOF
2112 }
2113 print OUT "1;\n";
2114 close(OUT);
2115
2116 print "\n";
2117 print "PROCESSOR     =$config{processor}\n" if $config{processor};
2118 print "PERL          =$config{perl}\n";
2119 print "PERLVERSION   =$Config{version} for $Config{archname}\n";
2120 print "HASHBANGPERL  =$config{hashbangperl}\n";
2121 print "CC            =$config{cross_compile_prefix}$target{cc}\n";
2122 print "CFLAG         =$target{cflags} $config{cflags}\n";
2123 print "CXX           =$config{cross_compile_prefix}$target{cxx}\n"
2124     if defined $target{cxx};
2125 print "CXXFLAG       =$target{cxxflags} $config{cxxflags}\n"
2126     if defined $target{cxx};
2127 print "DEFINES       =",join(" ", @{$target{defines}}, @{$config{defines}}),"\n";
2128 #print "RANLIB        =", $target{ranlib} eq '$(CROSS_COMPILE)ranlib' ?
2129 #                             "$config{cross_compile_prefix}ranlib" :
2130 #                             "$target{ranlib}", "\n";
2131 print "EX_LIBS       =$target{ex_libs} $config{ex_libs}\n";
2132
2133 my %builders = (
2134     unified => sub {
2135         run_dofile(catfile($blddir, $target{build_file}),
2136                    @{$config{build_file_templates}});
2137     },
2138     );
2139
2140 $builders{$builder}->($builder_platform, @builder_opts);
2141
2142 print <<"EOF" if ($disabled{threads} eq "unavailable");
2143
2144 The library could not be configured for supporting multi-threaded
2145 applications as the compiler options required on this system are not known.
2146 See file INSTALL for details if you need multi-threading.
2147 EOF
2148
2149 print <<"EOF" if ($no_shared_warn);
2150
2151 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2152 platform, so we will pretend you gave the option 'no-pic', which also disables
2153 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2154 or position independent code, please let us know (but please first make sure
2155 you have tried with a current version of OpenSSL).
2156 EOF
2157
2158 print <<"EOF" if (-f catfile($srcdir, "configdata.pm") && $srcdir ne $blddir);
2159
2160 WARNING: there are indications that another build was made in the source
2161 directory.  This build may have picked up artifacts from that build, the
2162 safest course of action is to clean the source directory and redo this
2163 configuration.
2164 EOF
2165
2166 exit(0);
2167
2168 ######################################################################
2169 #
2170 # Helpers and utility functions
2171 #
2172
2173 # Configuration file reading #########################################
2174
2175 # Note: All of the helper functions are for lazy evaluation.  They all
2176 # return a CODE ref, which will return the intended value when evaluated.
2177 # Thus, whenever there's mention of a returned value, it's about that
2178 # intended value.
2179
2180 # Helper function to implement conditional inheritance depending on the
2181 # value of $disabled{asm}.  Used in inherit_from values as follows:
2182 #
2183 #      inherit_from => [ "template", asm("asm_tmpl") ]
2184 #
2185 sub asm {
2186     my @x = @_;
2187     sub {
2188         $disabled{asm} ? () : @x;
2189     }
2190 }
2191
2192 # Helper function to implement conditional value variants, with a default
2193 # plus additional values based on the value of $config{build_type}.
2194 # Arguments are given in hash table form:
2195 #
2196 #       picker(default => "Basic string: ",
2197 #              debug   => "debug",
2198 #              release => "release")
2199 #
2200 # When configuring with --debug, the resulting string will be
2201 # "Basic string: debug", and when not, it will be "Basic string: release"
2202 #
2203 # This can be used to create variants of sets of flags according to the
2204 # build type:
2205 #
2206 #       cflags => picker(default => "-Wall",
2207 #                        debug   => "-g -O0",
2208 #                        release => "-O3")
2209 #
2210 sub picker {
2211     my %opts = @_;
2212     return sub { add($opts{default} || (),
2213                      $opts{$config{build_type}} || ())->(); }
2214 }
2215
2216 # Helper function to combine several values of different types into one.
2217 # This is useful if you want to combine a string with the result of a
2218 # lazy function, such as:
2219 #
2220 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2221 #
2222 sub combine {
2223     my @stuff = @_;
2224     return sub { add(@stuff)->(); }
2225 }
2226
2227 # Helper function to implement conditional values depending on the value
2228 # of $disabled{threads}.  Can be used as follows:
2229 #
2230 #       cflags => combine("-Wall", threads("-pthread"))
2231 #
2232 sub threads {
2233     my @flags = @_;
2234     return sub { add($disabled{threads} ? () : @flags)->(); }
2235 }
2236
2237
2238
2239 our $add_called = 0;
2240 # Helper function to implement adding values to already existing configuration
2241 # values.  It handles elements that are ARRAYs, CODEs and scalars
2242 sub _add {
2243     my $separator = shift;
2244
2245     # If there's any ARRAY in the collection of values OR the separator
2246     # is undef, we will return an ARRAY of combined values, otherwise a
2247     # string of joined values with $separator as the separator.
2248     my $found_array = !defined($separator);
2249
2250     my @values =
2251         map {
2252             my $res = $_;
2253             while (ref($res) eq "CODE") {
2254                 $res = $res->();
2255             }
2256             if (defined($res)) {
2257                 if (ref($res) eq "ARRAY") {
2258                     $found_array = 1;
2259                     @$res;
2260                 } else {
2261                     $res;
2262                 }
2263             } else {
2264                 ();
2265             }
2266     } (@_);
2267
2268     $add_called = 1;
2269
2270     if ($found_array) {
2271         [ @values ];
2272     } else {
2273         join($separator, grep { defined($_) && $_ ne "" } @values);
2274     }
2275 }
2276 sub add_before {
2277     my $separator = " ";
2278     if (ref($_[$#_]) eq "HASH") {
2279         my $opts = pop;
2280         $separator = $opts->{separator};
2281     }
2282     my @x = @_;
2283     sub { _add($separator, @x, @_) };
2284 }
2285 sub add {
2286     my $separator = " ";
2287     if (ref($_[$#_]) eq "HASH") {
2288         my $opts = pop;
2289         $separator = $opts->{separator};
2290     }
2291     my @x = @_;
2292     sub { _add($separator, @_, @x) };
2293 }
2294
2295 # configuration reader, evaluates the input file as a perl script and expects
2296 # it to fill %targets with target configurations.  Those are then added to
2297 # %table.
2298 sub read_config {
2299     my $fname = shift;
2300     open(CONFFILE, "< $fname")
2301         or die "Can't open configuration file '$fname'!\n";
2302     my $x = $/;
2303     undef $/;
2304     my $content = <CONFFILE>;
2305     $/ = $x;
2306     close(CONFFILE);
2307     my %targets = ();
2308     {
2309         # Protect certain tables from tampering
2310         local %table = %::table;
2311
2312         eval $content;
2313         warn $@ if $@;
2314     }
2315
2316     # For each target, check that it's configured with a hash table.
2317     foreach (keys %targets) {
2318         if (ref($targets{$_}) ne "HASH") {
2319             if (ref($targets{$_}) eq "") {
2320                 warn "Deprecated target configuration for $_, ignoring...\n";
2321             } else {
2322                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
2323             }
2324             delete $targets{$_};
2325         } else {
2326             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
2327         }
2328     }
2329
2330     %table = (%table, %targets);
2331
2332 }
2333
2334 # configuration resolver.  Will only resolve all the lazy evaluation
2335 # codeblocks for the chosen target and all those it inherits from,
2336 # recursively
2337 sub resolve_config {
2338     my $target = shift;
2339     my @breadcrumbs = @_;
2340
2341 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
2342
2343     if (grep { $_ eq $target } @breadcrumbs) {
2344         die "inherit_from loop!  target backtrace:\n  "
2345             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
2346     }
2347
2348     if (!defined($table{$target})) {
2349         warn "Warning! target $target doesn't exist!\n";
2350         return ();
2351     }
2352     # Recurse through all inheritances.  They will be resolved on the
2353     # fly, so when this operation is done, they will all just be a
2354     # bunch of attributes with string values.
2355     # What we get here, though, are keys with references to lists of
2356     # the combined values of them all.  We will deal with lists after
2357     # this stage is done.
2358     my %combined_inheritance = ();
2359     if ($table{$target}->{inherit_from}) {
2360         my @inherit_from =
2361             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
2362         foreach (@inherit_from) {
2363             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
2364
2365             # 'template' is a marker that's considered private to
2366             # the config that had it.
2367             delete $inherited_config{template};
2368
2369             foreach (keys %inherited_config) {
2370                 if (!$combined_inheritance{$_}) {
2371                     $combined_inheritance{$_} = [];
2372                 }
2373                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
2374             }
2375         }
2376     }
2377
2378     # We won't need inherit_from in this target any more, since we've
2379     # resolved all the inheritances that lead to this
2380     delete $table{$target}->{inherit_from};
2381
2382     # Now is the time to deal with those lists.  Here's the place to
2383     # decide what shall be done with those lists, all based on the
2384     # values of the target we're currently dealing with.
2385     # - If a value is a coderef, it will be executed with the list of
2386     #   inherited values as arguments.
2387     # - If the corresponding key doesn't have a value at all or is the
2388     #   empty string, the inherited value list will be run through the
2389     #   default combiner (below), and the result becomes this target's
2390     #   value.
2391     # - Otherwise, this target's value is assumed to be a string that
2392     #   will simply override the inherited list of values.
2393     my $default_combiner = add();
2394
2395     my %all_keys =
2396         map { $_ => 1 } (keys %combined_inheritance,
2397                          keys %{$table{$target}});
2398
2399     sub process_values {
2400         my $object    = shift;
2401         my $inherited = shift;  # Always a [ list ]
2402         my $target    = shift;
2403         my $entry     = shift;
2404
2405         $add_called = 0;
2406
2407         while(ref($object) eq "CODE") {
2408             $object = $object->(@$inherited);
2409         }
2410         if (!defined($object)) {
2411             return ();
2412         }
2413         elsif (ref($object) eq "ARRAY") {
2414             local $add_called;  # To make sure recursive calls don't affect it
2415             return [ map { process_values($_, $inherited, $target, $entry) }
2416                      @$object ];
2417         } elsif (ref($object) eq "") {
2418             return $object;
2419         } else {
2420             die "cannot handle reference type ",ref($object)
2421                 ," found in target ",$target," -> ",$entry,"\n";
2422         }
2423     }
2424
2425     foreach (sort keys %all_keys) {
2426         my $previous = $combined_inheritance{$_};
2427
2428         # Current target doesn't have a value for the current key?
2429         # Assign it the default combiner, the rest of this loop body
2430         # will handle it just like any other coderef.
2431         if (!exists $table{$target}->{$_}) {
2432             $table{$target}->{$_} = $default_combiner;
2433         }
2434
2435         $table{$target}->{$_} = process_values($table{$target}->{$_},
2436                                                $combined_inheritance{$_},
2437                                                $target, $_);
2438         unless(defined($table{$target}->{$_})) {
2439             delete $table{$target}->{$_};
2440         }
2441 #        if ($extra_checks &&
2442 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
2443 #            warn "$_ got replaced in $target\n";
2444 #        }
2445     }
2446
2447     # Finally done, return the result.
2448     return %{$table{$target}};
2449 }
2450
2451 sub usage
2452         {
2453         print STDERR $usage;
2454         print STDERR "\npick os/compiler from:\n";
2455         my $j=0;
2456         my $i;
2457         my $k=0;
2458         foreach $i (sort keys %table)
2459                 {
2460                 next if $table{$i}->{template};
2461                 next if $i =~ /^debug/;
2462                 $k += length($i) + 1;
2463                 if ($k > 78)
2464                         {
2465                         print STDERR "\n";
2466                         $k=length($i);
2467                         }
2468                 print STDERR $i . " ";
2469                 }
2470         foreach $i (sort keys %table)
2471                 {
2472                 next if $table{$i}->{template};
2473                 next if $i !~ /^debug/;
2474                 $k += length($i) + 1;
2475                 if ($k > 78)
2476                         {
2477                         print STDERR "\n";
2478                         $k=length($i);
2479                         }
2480                 print STDERR $i . " ";
2481                 }
2482         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
2483         exit(1);
2484         }
2485
2486 sub run_dofile
2487 {
2488     my $out = shift;
2489     my @templates = @_;
2490
2491     unlink $out || warn "Can't remove $out, $!"
2492         if -f $out;
2493     foreach (@templates) {
2494         die "Can't open $_, $!" unless -f $_;
2495     }
2496     my $perlcmd = (quotify("maybeshell", $config{perl}))[0];
2497     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
2498     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
2499     system($cmd);
2500     exit 1 if $? != 0;
2501     rename("$out.new", $out) || die "Can't rename $out.new, $!";
2502 }
2503
2504 sub which
2505 {
2506     my ($name)=@_;
2507
2508     if (eval { require IPC::Cmd; 1; }) {
2509         IPC::Cmd->import();
2510         return scalar IPC::Cmd::can_run($name);
2511     } else {
2512         # if there is $directories component in splitpath,
2513         # then it's not something to test with $PATH...
2514         return $name if (File::Spec->splitpath($name))[1];
2515
2516         foreach (File::Spec->path()) {
2517             my $fullpath = catfile($_, "$name$target{exe_extension}");
2518             if (-f $fullpath and -x $fullpath) {
2519                 return $fullpath;
2520             }
2521         }
2522     }
2523 }
2524
2525 # Configuration printer ##############################################
2526
2527 sub print_table_entry
2528 {
2529     my $target = shift;
2530     my %target = resolve_config($target);
2531     my $type = shift;
2532
2533     # Don't print the templates
2534     return if $target{template};
2535
2536     my @sequence = (
2537         "sys_id",
2538         "cc",
2539         "cflags",
2540         "defines",
2541         "unistd",
2542         "ld",
2543         "lflags",
2544         "loutflag",
2545         "plib_lflags",
2546         "ex_libs",
2547         "bn_ops",
2548         "apps_aux_src",
2549         "cpuid_asm_src",
2550         "uplink_aux_src",
2551         "bn_asm_src",
2552         "ec_asm_src",
2553         "des_asm_src",
2554         "aes_asm_src",
2555         "bf_asm_src",
2556         "md5_asm_src",
2557         "cast_asm_src",
2558         "sha1_asm_src",
2559         "rc4_asm_src",
2560         "rmd160_asm_src",
2561         "rc5_asm_src",
2562         "wp_asm_src",
2563         "cmll_asm_src",
2564         "modes_asm_src",
2565         "padlock_asm_src",
2566         "chacha_asm_src",
2567         "poly1035_asm_src",
2568         "thread_scheme",
2569         "perlasm_scheme",
2570         "dso_scheme",
2571         "shared_target",
2572         "shared_cflag",
2573         "shared_defines",
2574         "shared_ldflag",
2575         "shared_rcflag",
2576         "shared_extension",
2577         "dso_extension",
2578         "obj_extension",
2579         "exe_extension",
2580         "ranlib",
2581         "ar",
2582         "arflags",
2583         "aroutflag",
2584         "rc",
2585         "rcflags",
2586         "rcoutflag",
2587         "mt",
2588         "mtflags",
2589         "mtinflag",
2590         "mtoutflag",
2591         "multilib",
2592         "build_scheme",
2593         );
2594
2595     if ($type eq "TABLE") {
2596         print "\n";
2597         print "*** $target\n";
2598         foreach (@sequence) {
2599             if (ref($target{$_}) eq "ARRAY") {
2600                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
2601             } else {
2602                 printf "\$%-12s = %s\n", $_, $target{$_};
2603             }
2604         }
2605     } elsif ($type eq "HASH") {
2606         my $largest =
2607             length((sort { length($a) <=> length($b) } @sequence)[-1]);
2608         print "    '$target' => {\n";
2609         foreach (@sequence) {
2610             if ($target{$_}) {
2611                 if (ref($target{$_}) eq "ARRAY") {
2612                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
2613                 } else {
2614                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
2615                 }
2616             }
2617         }
2618         print "    },\n";
2619     }
2620 }
2621
2622 # Utility routines ###################################################
2623
2624 # On VMS, if the given file is a logical name, File::Spec::Functions
2625 # will consider it an absolute path.  There are cases when we want a
2626 # purely syntactic check without checking the environment.
2627 sub isabsolute {
2628     my $file = shift;
2629
2630     # On non-platforms, we just use file_name_is_absolute().
2631     return file_name_is_absolute($file) unless $^O eq "VMS";
2632
2633     # If the file spec includes a device or a directory spec,
2634     # file_name_is_absolute() is perfectly safe.
2635     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
2636
2637     # Here, we know the given file spec isn't absolute
2638     return 0;
2639 }
2640
2641 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
2642 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
2643 # realpath() requires that at least all path components except the last is an
2644 # existing directory.  On VMS, the last component of the directory spec must
2645 # exist.
2646 sub absolutedir {
2647     my $dir = shift;
2648
2649     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
2650     # will return the volume name for the device, no matter what.  Also,
2651     # it will return an incorrect directory spec if the argument is a
2652     # directory that doesn't exist.
2653     if ($^O eq "VMS") {
2654         return rel2abs($dir);
2655     }
2656
2657     # We use realpath() on Unix, since no other will properly clean out
2658     # a directory spec.
2659     use Cwd qw/realpath/;
2660
2661     return realpath($dir);
2662 }
2663
2664 sub quotify {
2665     my %processors = (
2666         perl    => sub { my $x = shift;
2667                          $x =~ s/([\\\$\@"])/\\$1/g;
2668                          return '"'.$x.'"'; },
2669         maybeshell => sub { my $x = shift;
2670                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
2671                             if ($x ne $y || $x =~ m|\s|) {
2672                                 return '"'.$y.'"';
2673                             } else {
2674                                 return $x;
2675                             }
2676                         },
2677         );
2678     my $for = shift;
2679     my $processor =
2680         defined($processors{$for}) ? $processors{$for} : sub { shift; };
2681
2682     return map { $processor->($_); } @_;
2683 }
2684
2685 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
2686 # $filename is a file name to read from
2687 # $line_concat_cond_re is a regexp detecting a line continuation ending
2688 # $line_concat is a CODEref that takes care of concatenating two lines
2689 sub collect_from_file {
2690     my $filename = shift;
2691     my $line_concat_cond_re = shift;
2692     my $line_concat = shift;
2693
2694     open my $fh, $filename || die "unable to read $filename: $!\n";
2695     return sub {
2696         my $saved_line = "";
2697         $_ = "";
2698         while (<$fh>) {
2699             s|\R$||;
2700             if (defined $line_concat) {
2701                 $_ = $line_concat->($saved_line, $_);
2702                 $saved_line = "";
2703             }
2704             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2705                 $saved_line = $_;
2706                 next;
2707             }
2708             return $_;
2709         }
2710         die "$filename ending with continuation line\n" if $_;
2711         close $fh;
2712         return undef;
2713     }
2714 }
2715
2716 # collect_from_array($array, $line_concat_cond_re, $line_concat)
2717 # $array is an ARRAYref of lines
2718 # $line_concat_cond_re is a regexp detecting a line continuation ending
2719 # $line_concat is a CODEref that takes care of concatenating two lines
2720 sub collect_from_array {
2721     my $array = shift;
2722     my $line_concat_cond_re = shift;
2723     my $line_concat = shift;
2724     my @array = (@$array);
2725
2726     return sub {
2727         my $saved_line = "";
2728         $_ = "";
2729         while (defined($_ = shift @array)) {
2730             s|\R$||;
2731             if (defined $line_concat) {
2732                 $_ = $line_concat->($saved_line, $_);
2733                 $saved_line = "";
2734             }
2735             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
2736                 $saved_line = $_;
2737                 next;
2738             }
2739             return $_;
2740         }
2741         die "input text ending with continuation line\n" if $_;
2742         return undef;
2743     }
2744 }
2745
2746 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
2747 # $lineiterator is a CODEref that delivers one line at a time.
2748 # All following arguments are regex/CODEref pairs, where the regexp detects a
2749 # line and the CODEref does something with the result of the regexp.
2750 sub collect_information {
2751     my $lineiterator = shift;
2752     my %collectors = @_;
2753
2754     while(defined($_ = $lineiterator->())) {
2755         s|\R$||;
2756         my $found = 0;
2757         if ($collectors{"BEFORE"}) {
2758             $collectors{"BEFORE"}->($_);
2759         }
2760         foreach my $re (keys %collectors) {
2761             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
2762                 $collectors{$re}->($lineiterator);
2763                 $found = 1;
2764             };
2765         }
2766         if ($collectors{"OTHERWISE"}) {
2767             $collectors{"OTHERWISE"}->($lineiterator, $_)
2768                 unless $found || !defined $collectors{"OTHERWISE"};
2769         }
2770         if ($collectors{"AFTER"}) {
2771             $collectors{"AFTER"}->($_);
2772         }
2773     }
2774 }
2775
2776 # tokenize($line)
2777 # $line is a line of text to split up into tokens
2778 # returns a list of tokens
2779 #
2780 # Tokens are divided by spaces.  If the tokens include spaces, they
2781 # have to be quoted with single or double quotes.  Double quotes
2782 # inside a double quoted token must be escaped.  Escaping is done
2783 # with backslash.
2784 # Basically, the same quoting rules apply for " and ' as in any
2785 # Unix shell.
2786 sub tokenize {
2787     my $line = my $debug_line = shift;
2788     my @result = ();
2789
2790     while ($line =~ s|^\s+||, $line ne "") {
2791         my $token = "";
2792         while ($line ne "" && $line !~ m|^\s|) {
2793             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
2794                 $token .= $1;
2795                 $line = $';
2796             } elsif ($line =~ m/^'([^']*)'/) {
2797                 $token .= $1;
2798                 $line = $';
2799             } elsif ($line =~ m/^(\S+)/) {
2800                 $token .= $1;
2801                 $line = $';
2802             }
2803         }
2804         push @result, $token;
2805     }
2806
2807     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
2808         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
2809         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
2810     }
2811     return @result;
2812 }