]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssl/Configure
unbount: Vendor import 1.14.0rc1
[FreeBSD/FreeBSD.git] / crypto / openssl / Configure
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 # Copyright 2016-2021 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 $orig_death_handler = $SIG{__DIE__};
25 $SIG{__DIE__} = \&death_handler;
26
27 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-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
28
29 # Options:
30 #
31 # --config      add the given configuration file, which will be read after
32 #               any "Configurations*" files that are found in the same
33 #               directory as this script.
34 # --prefix      prefix for the OpenSSL installation, which includes the
35 #               directories bin, lib, include, share/man, share/doc/openssl
36 #               This becomes the value of INSTALLTOP in Makefile
37 #               (Default: /usr/local)
38 # --openssldir  OpenSSL data area, such as openssl.cnf, certificates and keys.
39 #               If it's a relative directory, it will be added on the directory
40 #               given with --prefix.
41 #               This becomes the value of OPENSSLDIR in Makefile and in C.
42 #               (Default: PREFIX/ssl)
43 #
44 # --cross-compile-prefix Add specified prefix to binutils components.
45 #
46 # --api         One of 0.9.8, 1.0.0 or 1.1.0.  Do not compile support for
47 #               interfaces deprecated as of the specified OpenSSL version.
48 #
49 # no-hw-xxx     do not compile support for specific crypto hardware.
50 #               Generic OpenSSL-style methods relating to this support
51 #               are always compiled but return NULL if the hardware
52 #               support isn't compiled.
53 # no-hw         do not compile support for any crypto hardware.
54 # [no-]threads  [don't] try to create a library that is suitable for
55 #               multithreaded applications (default is "threads" if we
56 #               know how to do it)
57 # [no-]shared   [don't] try to create shared libraries when supported.
58 # [no-]pic      [don't] try to build position independent code when supported.
59 #               If disabled, it also disables shared and dynamic-engine.
60 # no-asm        do not use assembler
61 # no-egd        do not compile support for the entropy-gathering daemon APIs
62 # [no-]zlib     [don't] compile support for zlib compression.
63 # zlib-dynamic  Like "zlib", but the zlib library is expected to be a shared
64 #               library and will be loaded in run-time by the OpenSSL library.
65 # sctp          include SCTP support
66 # enable-weak-ssl-ciphers
67 #               Enable weak ciphers that are disabled by default.
68 # 386           generate 80386 code in assembly modules
69 # no-sse2       disables IA-32 SSE2 code in assembly modules, the above
70 #               mentioned '386' option implies this one
71 # no-<cipher>   build without specified algorithm (rsa, idea, rc5, ...)
72 # -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
73 # /<xxx>        passed through to the compiler. Unix-style options beginning
74 #               with a '-' or '+' are recognized, as well as Windows-style
75 #               options beginning with a '/'. If the option contains arguments
76 #               separated by spaces, then the URL-style notation %20 can be
77 #               used for the space character in order to avoid having to quote
78 #               the option. For example, -opt%20arg gets expanded to -opt arg.
79 #               In fact, any ASCII character can be encoded as %xx using its
80 #               hexadecimal encoding.
81 # -static       while -static is also a pass-through compiler option (and
82 #               as such is limited to environments where it's actually
83 #               meaningful), it triggers a number configuration options,
84 #               namely no-pic, no-shared and no-threads. It is
85 #               argued that the only reason to produce statically linked
86 #               binaries (and in context it means executables linked with
87 #               -static flag, and not just executables linked with static
88 #               libcrypto.a) is to eliminate dependency on specific run-time,
89 #               a.k.a. libc version. The mentioned config options are meant
90 #               to achieve just that. Unfortunately on Linux it's impossible
91 #               to eliminate the dependency completely for openssl executable
92 #               because of getaddrinfo and gethostbyname calls, which can
93 #               invoke dynamically loadable library facility anyway to meet
94 #               the lookup requests. For this reason on Linux statically
95 #               linked openssl executable has rather debugging value than
96 #               production quality.
97 #
98 # BN_LLONG      use the type 'long long' in crypto/bn/bn.h
99 # RC4_CHAR      use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
100 # Following are set automatically by this script
101 #
102 # MD5_ASM       use some extra md5 assembler,
103 # SHA1_ASM      use some extra sha1 assembler, must define L_ENDIAN for x86
104 # RMD160_ASM    use some extra ripemd160 assembler,
105 # SHA256_ASM    sha256_block is implemented in assembler
106 # SHA512_ASM    sha512_block is implemented in assembler
107 # AES_ASM       AES_[en|de]crypt is implemented in assembler
108
109 # Minimum warning options... any contributions to OpenSSL should at least
110 # get past these.  Note that we only use these with C compilers, not with
111 # C++ compilers.
112
113 # DEBUG_UNUSED enables __owur (warn unused result) checks.
114 # -DPEDANTIC complements -pedantic and is meant to mask code that
115 # is not strictly standard-compliant and/or implementation-specific,
116 # e.g. inline assembly, disregards to alignment requirements, such
117 # that -pedantic would complain about. Incidentally -DPEDANTIC has
118 # to be used even in sanitized builds, because sanitizer too is
119 # supposed to and does take notice of non-standard behaviour. Then
120 # -pedantic with pre-C9x compiler would also complain about 'long
121 # long' not being supported. As 64-bit algorithms are common now,
122 # it grew impossible to resolve this without sizeable additional
123 # code, so we just tell compiler to be pedantic about everything
124 # but 'long long' type.
125
126 my @gcc_devteam_warn = qw(
127     -DDEBUG_UNUSED
128     -DPEDANTIC -pedantic -Wno-long-long
129     -Wall
130     -Wextra
131     -Wno-unused-parameter
132     -Wno-missing-field-initializers
133     -Wswitch
134     -Wsign-compare
135     -Wshadow
136     -Wformat
137     -Wtype-limits
138     -Wundef
139     -Werror
140     -Wmissing-prototypes
141     -Wstrict-prototypes
142 );
143
144 # These are used in addition to $gcc_devteam_warn when the compiler is clang.
145 # TODO(openssl-team): fix problems and investigate if (at least) the
146 # following warnings can also be enabled:
147 #       -Wcast-align
148 #       -Wunreachable-code -- no, too ugly/compiler-specific
149 #       -Wlanguage-extension-token -- no, we use asm()
150 #       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
151 #       -Wextended-offsetof -- no, needed in CMS ASN1 code
152 my @clang_devteam_warn = qw(
153     -Wno-unknown-warning-option
154     -Wswitch-default
155     -Wno-parentheses-equality
156     -Wno-language-extension-token
157     -Wno-extended-offsetof
158     -Wconditional-uninitialized
159     -Wincompatible-pointer-types-discards-qualifiers
160     -Wmissing-variable-declarations
161 );
162
163 my @cl_devteam_warn = qw(
164     /WX
165 );
166
167 # This adds backtrace information to the memory leak info.  Is only used
168 # when crypto-mdebug-backtrace is enabled.
169 my $memleak_devteam_backtrace = "-rdynamic";
170
171 my $strict_warnings = 0;
172
173 # As for $BSDthreads. Idea is to maintain "collective" set of flags,
174 # which would cover all BSD flavors. -pthread applies to them all,
175 # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
176 # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
177 # which has to be accompanied by explicit -D_THREAD_SAFE and
178 # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
179 # seems to be sufficient?
180 our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
181
182 #
183 # API compatibility name to version number mapping.
184 #
185 my $maxapi = "1.1.0";           # API for "no-deprecated" builds
186 my $apitable = {
187     "1.1.0" => "0x10100000L",
188     "1.0.0" => "0x10000000L",
189     "0.9.8" => "0x00908000L",
190 };
191
192 our %table = ();
193 our %config = ();
194 our %withargs = ();
195 our $now_printing;      # set to current entry's name in print_table_entry
196                         # (todo: right thing would be to encapsulate name
197                         # into %target [class] and make print_table_entry
198                         # a method)
199
200 # Forward declarations ###############################################
201
202 # read_config(filename)
203 #
204 # Reads a configuration file and populates %table with the contents
205 # (which the configuration file places in %targets).
206 sub read_config;
207
208 # resolve_config(target)
209 #
210 # Resolves all the late evaluations, inheritances and so on for the
211 # chosen target and any target it inherits from.
212 sub resolve_config;
213
214
215 # Information collection #############################################
216
217 # Unified build supports separate build dir
218 my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
219 my $blddir = catdir(absolutedir("."));         # catdir ensures local syntax
220
221 # File::Spec::Unix doesn't detect case insensitivity, so we make sure to
222 # check if the source and build directory are really the same, and make
223 # them so.  This avoids all kinds of confusion later on.
224 # We must check @File::Spec::ISA rather than using File::Spec->isa() to
225 # know if File::Spec ended up loading File::Spec::Unix.
226 $srcdir = $blddir
227     if (grep(/::Unix$/, @File::Spec::ISA)
228         && samedir($srcdir, $blddir));
229
230 my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
231
232 my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
233
234 $config{sourcedir} = abs2rel($srcdir, $blddir);
235 $config{builddir} = abs2rel($blddir, $blddir);
236
237 # Collect reconfiguration information if needed
238 my @argvcopy=@ARGV;
239
240 if (grep /^reconf(igure)?$/, @argvcopy) {
241     die "reconfiguring with other arguments present isn't supported"
242         if scalar @argvcopy > 1;
243     if (-f "./configdata.pm") {
244         my $file = "./configdata.pm";
245         unless (my $return = do $file) {
246             die "couldn't parse $file: $@" if $@;
247             die "couldn't do $file: $!"    unless defined $return;
248             die "couldn't run $file"       unless $return;
249         }
250
251         @argvcopy = defined($configdata::config{perlargv}) ?
252             @{$configdata::config{perlargv}} : ();
253         die "Incorrect data to reconfigure, please do a normal configuration\n"
254             if (grep(/^reconf/,@argvcopy));
255         $config{perlenv} = $configdata::config{perlenv} // {};
256     } else {
257         die "Insufficient data to reconfigure, please do a normal configuration\n";
258     }
259 }
260
261 $config{perlargv} = [ @argvcopy ];
262
263 # Collect version numbers
264 $config{version} = "unknown";
265 $config{version_num} = "unknown";
266 $config{shlib_version_number} = "unknown";
267 $config{shlib_version_history} = "unknown";
268
269 collect_information(
270     collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
271     qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
272     qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/      => sub { $config{version_num}=$1 },
273     qr/SHLIB_VERSION_NUMBER *"([^"]+)"/      => sub { $config{shlib_version_number}=$1 },
274     qr/SHLIB_VERSION_HISTORY *"([^"]*)"/     => sub { $config{shlib_version_history}=$1 }
275     );
276 if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
277
278 ($config{major}, $config{minor})
279     = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
280 ($config{shlib_major}, $config{shlib_minor})
281     = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
282 die "erroneous version information in opensslv.h: ",
283     "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
284     if ($config{major} eq "" || $config{minor} eq ""
285         || $config{shlib_major} eq "" ||  $config{shlib_minor} eq "");
286
287 # Collect target configurations
288
289 my $pattern = catfile(dirname($0), "Configurations", "*.conf");
290 foreach (sort glob($pattern)) {
291     &read_config($_);
292 }
293
294 if (defined env($local_config_envname)) {
295     if ($^O eq 'VMS') {
296         # VMS environment variables are logical names,
297         # which can be used as is
298         $pattern = $local_config_envname . ':' . '*.conf';
299     } else {
300         $pattern = catfile(env($local_config_envname), '*.conf');
301     }
302
303     foreach (sort glob($pattern)) {
304         &read_config($_);
305     }
306 }
307
308 # Save away perl command information
309 $config{perl_cmd} = $^X;
310 $config{perl_version} = $Config{version};
311 $config{perl_archname} = $Config{archname};
312
313 $config{prefix}="";
314 $config{openssldir}="";
315 $config{processor}="";
316 $config{libdir}="";
317 my $auto_threads=1;    # enable threads automatically? true by default
318 my $default_ranlib;
319
320 # Top level directories to build
321 $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
322 # crypto/ subdirectories to build
323 $config{sdirs} = [
324     "objects",
325     "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
326     "des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
327     "bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine",
328     "buffer", "bio", "stack", "lhash", "rand", "err",
329     "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
330     "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
331     ];
332 # test/ subdirectories to build
333 $config{tdirs} = [ "ossl_shim" ];
334
335 # Known TLS and DTLS protocols
336 my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
337 my @dtls = qw(dtls1 dtls1_2);
338
339 # Explicitly known options that are possible to disable.  They can
340 # be regexps, and will be used like this: /^no-${option}$/
341 # For developers: keep it sorted alphabetically
342
343 my @disablables = (
344     "afalgeng",
345     "aria",
346     "asan",
347     "asm",
348     "async",
349     "autoalginit",
350     "autoerrinit",
351     "autoload-config",
352     "bf",
353     "blake2",
354     "buildtest-c\\+\\+",
355     "camellia",
356     "capieng",
357     "cast",
358     "chacha",
359     "cmac",
360     "cms",
361     "comp",
362     "crypto-mdebug",
363     "crypto-mdebug-backtrace",
364     "ct",
365     "deprecated",
366     "des",
367     "devcryptoeng",
368     "dgram",
369     "dh",
370     "dsa",
371     "dso",
372     "dtls",
373     "dynamic-engine",
374     "ec",
375     "ec2m",
376     "ecdh",
377     "ecdsa",
378     "ec_nistp_64_gcc_128",
379     "egd",
380     "engine",
381     "err",
382     "external-tests",
383     "filenames",
384     "fuzz-libfuzzer",
385     "fuzz-afl",
386     "gost",
387     "heartbeats",
388     "hw(-.+)?",
389     "idea",
390     "ktls",
391     "makedepend",
392     "md2",
393     "md4",
394     "mdc2",
395     "msan",
396     "multiblock",
397     "nextprotoneg",
398     "pinshared",
399     "ocb",
400     "ocsp",
401     "pic",
402     "poly1305",
403     "posix-io",
404     "psk",
405     "rc2",
406     "rc4",
407     "rc5",
408     "rdrand",
409     "rfc3779",
410     "rmd160",
411     "scrypt",
412     "sctp",
413     "seed",
414     "shared",
415     "siphash",
416     "sm2",
417     "sm3",
418     "sm4",
419     "sock",
420     "srp",
421     "srtp",
422     "sse2",
423     "ssl",
424     "ssl-trace",
425     "static-engine",
426     "stdio",
427     "tests",
428     "threads",
429     "tls",
430     "ts",
431     "ubsan",
432     "ui-console",
433     "unit-test",
434     "whirlpool",
435     "weak-ssl-ciphers",
436     "zlib",
437     "zlib-dynamic",
438     );
439 foreach my $proto ((@tls, @dtls))
440         {
441         push(@disablables, $proto);
442         push(@disablables, "$proto-method") unless $proto eq "tls1_3";
443         }
444
445 my %deprecated_disablables = (
446     "ssl2" => undef,
447     "buf-freelists" => undef,
448     "ripemd" => "rmd160",
449     "ui" => "ui-console",
450     );
451
452 # All of the following are disabled by default:
453
454 our %disabled = ( # "what"         => "comment"
455                   "asan"                => "default",
456                   "buildtest-c++"       => "default",
457                   "crypto-mdebug"       => "default",
458                   "crypto-mdebug-backtrace" => "default",
459                   "devcryptoeng"        => "default",
460                   "ec_nistp_64_gcc_128" => "default",
461                   "egd"                 => "default",
462                   "external-tests"      => "default",
463                   "fuzz-libfuzzer"      => "default",
464                   "fuzz-afl"            => "default",
465                   "heartbeats"          => "default",
466                   "md2"                 => "default",
467                   "msan"                => "default",
468                   "rc5"                 => "default",
469                   "sctp"                => "default",
470                   "ssl-trace"           => "default",
471                   "ssl3"                => "default",
472                   "ssl3-method"         => "default",
473                   "ubsan"               => "default",
474                   "unit-test"           => "default",
475                   "weak-ssl-ciphers"    => "default",
476                   "zlib"                => "default",
477                   "zlib-dynamic"        => "default",
478                   "ktls"                => "default",
479                 );
480
481 # Note: => pair form used for aesthetics, not to truly make a hash table
482 my @disable_cascades = (
483     # "what"            => [ "cascade", ... ]
484     sub { $config{processor} eq "386" }
485                         => [ "sse2" ],
486     "ssl"               => [ "ssl3" ],
487     "ssl3-method"       => [ "ssl3" ],
488     "zlib"              => [ "zlib-dynamic" ],
489     "des"               => [ "mdc2" ],
490     "ec"                => [ "ecdsa", "ecdh" ],
491
492     "dgram"             => [ "dtls", "sctp" ],
493     "sock"              => [ "dgram" ],
494     "dtls"              => [ @dtls ],
495     sub { 0 == scalar grep { !$disabled{$_} } @dtls }
496                         => [ "dtls" ],
497
498     "tls"               => [ @tls ],
499     sub { 0 == scalar grep { !$disabled{$_} } @tls }
500                         => [ "tls" ],
501
502     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
503
504     # Without position independent code, there can be no shared libraries or DSOs
505     "pic"               => [ "shared" ],
506     "shared"            => [ "dynamic-engine" ],
507     "dso"               => [ "dynamic-engine" ],
508     "engine"            => [ "afalgeng", "devcryptoeng" ],
509
510     # no-autoalginit is only useful when building non-shared
511     "autoalginit"       => [ "shared", "apps" ],
512
513     "stdio"             => [ "apps", "capieng", "egd" ],
514     "apps"              => [ "tests" ],
515     "tests"             => [ "external-tests" ],
516     "comp"              => [ "zlib" ],
517     "ec"                => [ "tls1_3", "sm2" ],
518     "sm3"               => [ "sm2" ],
519     sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
520
521     sub { !$disabled{"msan"} } => [ "asm" ],
522     );
523
524 # Avoid protocol support holes.  Also disable all versions below N, if version
525 # N is disabled while N+1 is enabled.
526 #
527 my @list = (reverse @tls);
528 while ((my $first, my $second) = (shift @list, shift @list)) {
529     last unless @list;
530     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
531                               => [ @list ] );
532     unshift @list, $second;
533 }
534 my @list = (reverse @dtls);
535 while ((my $first, my $second) = (shift @list, shift @list)) {
536     last unless @list;
537     push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
538                               => [ @list ] );
539     unshift @list, $second;
540 }
541
542 # Explicit "no-..." options will be collected in %disabled along with the defaults.
543 # To remove something from %disabled, use "enable-foo".
544 # For symmetry, "disable-foo" is a synonym for "no-foo".
545
546 &usage if ($#ARGV < 0);
547
548 # For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
549 # platform specific list separators.  Users from those platforms should
550 # recognise those separators from how you set up the PATH to find executables.
551 # The default is the Unix like separator, :, but as an exception, we also
552 # support the space as separator.
553 my $list_separator_re =
554     { VMS           => qr/(?<!\^),/,
555       MSWin32       => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/;
556 # All the "make variables" we support
557 # Some get pre-populated for the sake of backward compatibility
558 # (we supported those before the change to "make variable" support.
559 my %user = (
560     AR          => env('AR'),
561     ARFLAGS     => [],
562     AS          => undef,
563     ASFLAGS     => [],
564     CC          => env('CC'),
565     CFLAGS      => [ env('CFLAGS') || () ],
566     CXX         => env('CXX'),
567     CXXFLAGS    => [ env('CXXFLAGS') || () ],
568     CPP         => undef,
569     CPPFLAGS    => [ env('CPPFLAGS') || () ],  # -D, -I, -Wp,
570     CPPDEFINES  => [],  # Alternative for -D
571     CPPINCLUDES => [],  # Alternative for -I
572     CROSS_COMPILE => env('CROSS_COMPILE'),
573     HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'),
574     LD          => undef,
575     LDFLAGS     => [ env('LDFLAGS') || () ],  # -L, -Wl,
576     LDLIBS      => [ env('LDLIBS') || () ],  # -l
577     MT          => undef,
578     MTFLAGS     => [],
579     PERL        => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
580     RANLIB      => env('RANLIB'),
581     RC          => env('RC') || env('WINDRES'),
582     RCFLAGS     => [ env('RCFLAGS') || () ],
583     RM          => undef,
584    );
585 # Info about what "make variables" may be prefixed with the cross compiler
586 # prefix.  This should NEVER mention any such variable with a list for value.
587 my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC );
588 # The same but for flags given as Configure options.  These are *additional*
589 # input, as opposed to the VAR=string option that override the corresponding
590 # config target attributes
591 my %useradd = (
592     CPPDEFINES  => [],
593     CPPINCLUDES => [],
594     CPPFLAGS    => [],
595     CFLAGS      => [],
596     CXXFLAGS    => [],
597     LDFLAGS     => [],
598     LDLIBS      => [],
599     RCFLAGS     => [],
600    );
601
602 my %user_synonyms = (
603     HASHBANGPERL=> 'PERL',
604     RC          => 'WINDRES',
605    );
606
607 # Some target attributes have been renamed, this is the translation table
608 my %target_attr_translate =(
609     ar          => 'AR',
610     as          => 'AS',
611     cc          => 'CC',
612     cxx         => 'CXX',
613     cpp         => 'CPP',
614     hashbangperl => 'HASHBANGPERL',
615     ld          => 'LD',
616     mt          => 'MT',
617     ranlib      => 'RANLIB',
618     rc          => 'RC',
619     rm          => 'RM',
620    );
621
622 # Initialisers coming from 'config' scripts
623 $config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ];
624 $config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ];
625 $config{cppflags} = [ env('__CNF_CPPFLAGS') || () ];
626 $config{cflags} = [ env('__CNF_CFLAGS') || () ];
627 $config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ];
628 $config{lflags} = [ env('__CNF_LDFLAGS') || () ];
629 $config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
630
631 $config{openssl_api_defines}=[];
632 $config{openssl_algorithm_defines}=[];
633 $config{openssl_thread_defines}=[];
634 $config{openssl_sys_defines}=[];
635 $config{openssl_other_defines}=[];
636 $config{options}="";
637 $config{build_type} = "release";
638 my $target="";
639
640 my %cmdvars = ();               # Stores FOO='blah' type arguments
641 my %unsupported_options = ();
642 my %deprecated_options = ();
643 # If you change this, update apps/version.c
644 my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
645 my @seed_sources = ();
646 while (@argvcopy)
647         {
648         $_ = shift @argvcopy;
649
650         # Support env variable assignments among the options
651         if (m|^(\w+)=(.+)?$|)
652                 {
653                 $cmdvars{$1} = $2;
654                 # Every time a variable is given as a configuration argument,
655                 # it acts as a reset if the variable.
656                 if (exists $user{$1})
657                         {
658                         $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
659                         }
660                 #if (exists $useradd{$1})
661                 #       {
662                 #       $useradd{$1} = [];
663                 #       }
664                 next;
665                 }
666
667         # VMS is a case insensitive environment, and depending on settings
668         # out of our control, we may receive options uppercased.  Let's
669         # downcase at least the part before any equal sign.
670         if ($^O eq "VMS")
671                 {
672                 s/^([^=]*)/lc($1)/e;
673                 }
674
675         # some people just can't read the instructions, clang people have to...
676         s/^-no-(?!integrated-as)/no-/;
677
678         # rewrite some options in "enable-..." form
679         s /^-?-?shared$/enable-shared/;
680         s /^sctp$/enable-sctp/;
681         s /^threads$/enable-threads/;
682         s /^zlib$/enable-zlib/;
683         s /^zlib-dynamic$/enable-zlib-dynamic/;
684
685         if (/^(no|disable|enable)-(.+)$/)
686                 {
687                 my $word = $2;
688                 if (!exists $deprecated_disablables{$word}
689                         && !grep { $word =~ /^${_}$/ } @disablables)
690                         {
691                         $unsupported_options{$_} = 1;
692                         next;
693                         }
694                 }
695         if (/^no-(.+)$/ || /^disable-(.+)$/)
696                 {
697                 foreach my $proto ((@tls, @dtls))
698                         {
699                         if ($1 eq "$proto-method")
700                                 {
701                                 $disabled{"$proto"} = "option($proto-method)";
702                                 last;
703                                 }
704                         }
705                 if ($1 eq "dtls")
706                         {
707                         foreach my $proto (@dtls)
708                                 {
709                                 $disabled{$proto} = "option(dtls)";
710                                 }
711                         $disabled{"dtls"} = "option(dtls)";
712                         }
713                 elsif ($1 eq "ssl")
714                         {
715                         # Last one of its kind
716                         $disabled{"ssl3"} = "option(ssl)";
717                         }
718                 elsif ($1 eq "tls")
719                         {
720                         # XXX: Tests will fail if all SSL/TLS
721                         # protocols are disabled.
722                         foreach my $proto (@tls)
723                                 {
724                                 $disabled{$proto} = "option(tls)";
725                                 }
726                         }
727                 elsif ($1 eq "static-engine")
728                         {
729                         delete $disabled{"dynamic-engine"};
730                         }
731                 elsif ($1 eq "dynamic-engine")
732                         {
733                         $disabled{"dynamic-engine"} = "option";
734                         }
735                 elsif (exists $deprecated_disablables{$1})
736                         {
737                         if ($deprecated_disablables{$1} ne "")
738                                 {
739                                 $deprecated_options{$_} = 1;
740                                 if (defined $deprecated_disablables{$1})
741                                         {
742                                         $disabled{$deprecated_disablables{$1}} = "option";
743                                         }
744                                 }
745                         }
746                 else
747                         {
748                         $disabled{$1} = "option";
749                         }
750                 # No longer an automatic choice
751                 $auto_threads = 0 if ($1 eq "threads");
752                 }
753         elsif (/^enable-(.+)$/)
754                 {
755                 if ($1 eq "static-engine")
756                         {
757                         $disabled{"dynamic-engine"} = "option";
758                         }
759                 elsif ($1 eq "dynamic-engine")
760                         {
761                         delete $disabled{"dynamic-engine"};
762                         }
763                 elsif ($1 eq "zlib-dynamic")
764                         {
765                         delete $disabled{"zlib"};
766                         }
767                 my $algo = $1;
768                 delete $disabled{$algo};
769
770                 # No longer an automatic choice
771                 $auto_threads = 0 if ($1 eq "threads");
772                 }
773         elsif (/^--strict-warnings$/)
774                 {
775                 # Pretend that our strict flags is a C flag, and replace it
776                 # with the proper flags later on
777                 push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
778                 $strict_warnings=1;
779                 }
780         elsif (/^--debug$/)
781                 {
782                 $config{build_type} = "debug";
783                 }
784         elsif (/^--release$/)
785                 {
786                 $config{build_type} = "release";
787                 }
788         elsif (/^386$/)
789                 { $config{processor}=386; }
790         elsif (/^fips$/)
791                 {
792                 die "FIPS mode not supported\n";
793                 }
794         elsif (/^rsaref$/)
795                 {
796                 # No RSAref support any more since it's not needed.
797                 # The check for the option is there so scripts aren't
798                 # broken
799                 }
800         elsif (/^nofipscanistercheck$/)
801                 {
802                 die "FIPS mode not supported\n";
803                 }
804         elsif (m|^[-+/]|)
805                 {
806                 if (/^--prefix=(.*)$/)
807                         {
808                         $config{prefix}=$1;
809                         die "Directory given with --prefix MUST be absolute\n"
810                                 unless file_name_is_absolute($config{prefix});
811                         }
812                 elsif (/^--api=(.*)$/)
813                         {
814                         $config{api}=$1;
815                         }
816                 elsif (/^--libdir=(.*)$/)
817                         {
818                         $config{libdir}=$1;
819                         }
820                 elsif (/^--openssldir=(.*)$/)
821                         {
822                         $config{openssldir}=$1;
823                         }
824                 elsif (/^--with-zlib-lib=(.*)$/)
825                         {
826                         $withargs{zlib_lib}=$1;
827                         }
828                 elsif (/^--with-zlib-include=(.*)$/)
829                         {
830                         $withargs{zlib_include}=$1;
831                         }
832                 elsif (/^--with-fuzzer-lib=(.*)$/)
833                         {
834                         $withargs{fuzzer_lib}=$1;
835                         }
836                 elsif (/^--with-fuzzer-include=(.*)$/)
837                         {
838                         $withargs{fuzzer_include}=$1;
839                         }
840                 elsif (/^--with-rand-seed=(.*)$/)
841                         {
842                         foreach my $x (split(m|,|, $1))
843                             {
844                             die "Unknown --with-rand-seed choice $x\n"
845                                 if ! grep { $x eq $_ } @known_seed_sources;
846                             push @seed_sources, $x;
847                             }
848                         }
849                 elsif (/^--cross-compile-prefix=(.*)$/)
850                         {
851                         $user{CROSS_COMPILE}=$1;
852                         }
853                 elsif (/^--config=(.*)$/)
854                         {
855                         read_config $1;
856                         }
857                 elsif (/^-l(.*)$/)
858                         {
859                         push @{$useradd{LDLIBS}}, $_;
860                         }
861                 elsif (/^-framework$/)
862                         {
863                         push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
864                         }
865                 elsif (/^-L(.*)$/ or /^-Wl,/)
866                         {
867                         push @{$useradd{LDFLAGS}}, $_;
868                         }
869                 elsif (/^-rpath$/ or /^-R$/)
870                         # -rpath is the OSF1 rpath flag
871                         # -R is the old Solaris rpath flag
872                         {
873                         my $rpath = shift(@argvcopy) || "";
874                         $rpath .= " " if $rpath ne "";
875                         push @{$useradd{LDFLAGS}}, $_, $rpath;
876                         }
877                 elsif (/^-static$/)
878                         {
879                         push @{$useradd{LDFLAGS}}, $_;
880                         }
881                 elsif (m|^[-/]D(.*)$|)
882                         {
883                         push @{$useradd{CPPDEFINES}}, $1;
884                         }
885                 elsif (m|^[-/]I(.*)$|)
886                         {
887                         push @{$useradd{CPPINCLUDES}}, $1;
888                         }
889                 elsif (/^-Wp,$/)
890                         {
891                         push @{$useradd{CPPFLAGS}}, $1;
892                         }
893                 else    # common if (/^[-+]/), just pass down...
894                         {
895                         # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
896                         # This provides a simple way to pass options with arguments separated
897                         # by spaces without quoting (e.g. -opt%20arg translates to -opt arg).
898                         $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
899                         push @{$useradd{CFLAGS}}, $_;
900                         push @{$useradd{CXXFLAGS}}, $_;
901                         }
902                 }
903         elsif (m|^/|)
904                 {
905                 # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
906                 # This provides a simple way to pass options with arguments separated
907                 # by spaces without quoting (e.g. /opt%20arg translates to /opt arg).
908                 $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
909                 push @{$useradd{CFLAGS}}, $_;
910                 push @{$useradd{CXXFLAGS}}, $_;
911                 }
912         else
913                 {
914                 die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
915                 $target=$_;
916                 }
917         unless ($_ eq $target || /^no-/ || /^disable-/)
918                 {
919                 # "no-..." follows later after implied deactivations
920                 # have been derived.  (Don't take this too seriously,
921                 # we really only write OPTIONS to the Makefile out of
922                 # nostalgia.)
923
924                 if ($config{options} eq "")
925                         { $config{options} = $_; }
926                 else
927                         { $config{options} .= " ".$_; }
928                 }
929         }
930
931 if (defined($config{api}) && !exists $apitable->{$config{api}}) {
932         die "***** Unsupported api compatibility level: $config{api}\n",
933 }
934
935 if (keys %deprecated_options)
936         {
937         warn "***** Deprecated options: ",
938                 join(", ", keys %deprecated_options), "\n";
939         }
940 if (keys %unsupported_options)
941         {
942         die "***** Unsupported options: ",
943                 join(", ", keys %unsupported_options), "\n";
944         }
945
946 # If any %useradd entry has been set, we must check that the "make
947 # variables" haven't been set.  We start by checking of any %useradd entry
948 # is set.
949 if (grep { scalar @$_ > 0 } values %useradd) {
950     # Hash of env / make variables names.  The possible values are:
951     # 1 - "make vars"
952     # 2 - %useradd entry set
953     # 3 - both set
954     my %detected_vars =
955         map { my $v = 0;
956               $v += 1 if $cmdvars{$_};
957               $v += 2 if @{$useradd{$_}};
958               $_ => $v }
959         keys %useradd;
960
961     # If any of the corresponding "make variables" is set, we error
962     if (grep { $_ & 1 } values %detected_vars) {
963         my $names = join(', ', grep { $detected_vars{$_} > 0 }
964                                sort keys %detected_vars);
965         die <<"_____";
966 ***** Mixing make variables and additional compiler/linker flags as
967 ***** configure command line option is not permitted.
968 ***** Affected make variables: $names
969 _____
970     }
971 }
972
973 # Check through all supported command line variables to see if any of them
974 # were set, and canonicalise the values we got.  If no compiler or linker
975 # flag or anything else that affects %useradd was set, we also check the
976 # environment for values.
977 my $anyuseradd =
978     grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
979 foreach (keys %user) {
980     my $value = $cmdvars{$_};
981     $value //= env($_) unless $anyuseradd;
982     $value //=
983         defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
984     $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
985         unless $anyuseradd;
986
987     if (defined $value) {
988         if (ref $user{$_} eq 'ARRAY') {
989             if ($_ eq 'CPPDEFINES' || $_ eq 'CPPINCLUDES') {
990                 $user{$_} = [ split /$list_separator_re/, $value ];
991             } else {
992                 $user{$_} = [ $value ];
993             }
994         } elsif (!defined $user{$_}) {
995             $user{$_} = $value;
996         }
997     }
998 }
999
1000 if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
1001     && !$disabled{shared}
1002     && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
1003     die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
1004         "***** any of asan, msan or ubsan\n";
1005 }
1006
1007 sub disable {
1008     my $disable_type = shift;
1009
1010     for (@_) {
1011         $disabled{$_} = $disable_type;
1012     }
1013
1014     my @tocheckfor = (@_ ? @_ : keys %disabled);
1015     while (@tocheckfor) {
1016         my %new_tocheckfor = ();
1017         my @cascade_copy = (@disable_cascades);
1018         while (@cascade_copy) {
1019             my ($test, $descendents) =
1020                 (shift @cascade_copy, shift @cascade_copy);
1021             if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
1022                 foreach (grep { !defined($disabled{$_}) } @$descendents) {
1023                     $new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
1024                 }
1025             }
1026         }
1027         @tocheckfor = (keys %new_tocheckfor);
1028     }
1029 }
1030 disable();                     # First cascade run
1031
1032 our $die = sub { die @_; };
1033 if ($target eq "TABLE") {
1034     local $die = sub { warn @_; };
1035     foreach (sort keys %table) {
1036         print_table_entry($_, "TABLE");
1037     }
1038     exit 0;
1039 }
1040
1041 if ($target eq "LIST") {
1042     foreach (sort keys %table) {
1043         print $_,"\n" unless $table{$_}->{template};
1044     }
1045     exit 0;
1046 }
1047
1048 if ($target eq "HASH") {
1049     local $die = sub { warn @_; };
1050     print "%table = (\n";
1051     foreach (sort keys %table) {
1052         print_table_entry($_, "HASH");
1053     }
1054     exit 0;
1055 }
1056
1057 print "Configuring OpenSSL version $config{version} ($config{version_num}) ";
1058 print "for $target\n";
1059
1060 if (scalar(@seed_sources) == 0) {
1061     print "Using os-specific seed configuration\n";
1062     push @seed_sources, 'os';
1063 }
1064 if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) {
1065     delete $disabled{'egd'};
1066 }
1067 if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
1068     die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
1069     warn <<_____ if scalar(@seed_sources) == 1;
1070
1071 ============================== WARNING ===============================
1072 You have selected the --with-rand-seed=none option, which effectively
1073 disables automatic reseeding of the OpenSSL random generator.
1074 All operations depending on the random generator such as creating keys
1075 will not work unless the random generator is seeded manually by the
1076 application.
1077
1078 Please read the 'Note on random number generation' section in the
1079 INSTALL instructions and the RAND_DRBG(7) manual page for more details.
1080 ============================== WARNING ===============================
1081
1082 _____
1083 }
1084 push @{$config{openssl_other_defines}},
1085      map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
1086         @seed_sources;
1087
1088 # Backward compatibility?
1089 if ($target =~ m/^CygWin32(-.*)$/) {
1090     $target = "Cygwin".$1;
1091 }
1092
1093 # Support for legacy targets having a name starting with 'debug-'
1094 my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
1095 if ($d) {
1096     $config{build_type} = "debug";
1097
1098     # If we do not find debug-foo in the table, the target is set to foo.
1099     if (!$table{$target}) {
1100         $target = $t;
1101     }
1102 }
1103
1104 &usage if !$table{$target} || $table{$target}->{template};
1105
1106 $config{target} = $target;
1107 my %target = resolve_config($target);
1108
1109 foreach (keys %target_attr_translate) {
1110     $target{$target_attr_translate{$_}} = $target{$_}
1111         if $target{$_};
1112     delete $target{$_};
1113 }
1114
1115 %target = ( %{$table{DEFAULTS}}, %target );
1116
1117 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
1118 $config{conf_files} = [ sort keys %conf_files ];
1119
1120 # Using sub disable within these loops may prove fragile, so we run
1121 # a cascade afterwards
1122 foreach my $feature (@{$target{disable}}) {
1123     if (exists $deprecated_disablables{$feature}) {
1124         warn "***** config $target disables deprecated feature $feature\n";
1125     } elsif (!grep { $feature eq $_ } @disablables) {
1126         die "***** config $target disables unknown feature $feature\n";
1127     }
1128     $disabled{$feature} = 'config';
1129 }
1130 foreach my $feature (@{$target{enable}}) {
1131     if ("default" eq ($disabled{$feature} // "")) {
1132         if (exists $deprecated_disablables{$feature}) {
1133             warn "***** config $target enables deprecated feature $feature\n";
1134         } elsif (!grep { $feature eq $_ } @disablables) {
1135             die "***** config $target enables unknown feature $feature\n";
1136         }
1137         delete $disabled{$feature};
1138     }
1139 }
1140 disable();                      # Run a cascade now
1141
1142 $target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
1143 $target{cxxflags}//=$target{cflags} if $target{CXX};
1144 $target{exe_extension}="";
1145 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
1146                                   || $config{target} =~ /^(?:Cygwin|mingw)/);
1147 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
1148
1149 ($target{shared_extension_simple}=$target{shared_extension})
1150     =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||
1151     unless defined($target{shared_extension_simple});
1152 $target{dso_extension}//=$target{shared_extension_simple};
1153 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
1154     if ($config{target} =~ /^(?:Cygwin|mingw)/);
1155
1156 # Fill %config with values from %user, and in case those are undefined or
1157 # empty, use values from %target (acting as a default).
1158 foreach (keys %user) {
1159     my $ref_type = ref $user{$_};
1160
1161     # Temporary function.  Takes an intended ref type (empty string or "ARRAY")
1162     # and a value that's to be coerced into that type.
1163     my $mkvalue = sub {
1164         my $type = shift;
1165         my $value = shift;
1166         my $undef_p = shift;
1167
1168         die "Too many arguments for \$mkvalue" if @_;
1169
1170         while (ref $value eq 'CODE') {
1171             $value = $value->();
1172         }
1173
1174         if ($type eq 'ARRAY') {
1175             return undef unless defined $value;
1176             return undef if ref $value ne 'ARRAY' && !$value;
1177             return undef if ref $value eq 'ARRAY' && !@$value;
1178             return [ $value ] unless ref $value eq 'ARRAY';
1179         }
1180         return undef unless $value;
1181         return $value;
1182     };
1183
1184     $config{$_} =
1185         $mkvalue->($ref_type, $user{$_})
1186         || $mkvalue->($ref_type, $target{$_});
1187     delete $config{$_} unless defined $config{$_};
1188 }
1189
1190 # Finish up %config by appending things the user gave us on the command line
1191 # apart from "make variables"
1192 foreach (keys %useradd) {
1193     # The must all be lists, so we assert that here
1194     die "internal error: \$useradd{$_} isn't an ARRAY\n"
1195         unless ref $useradd{$_} eq 'ARRAY';
1196
1197     if (defined $config{$_}) {
1198         push @{$config{$_}}, @{$useradd{$_}};
1199     } else {
1200         $config{$_} = [ @{$useradd{$_}} ];
1201     }
1202 }
1203 # At this point, we can forget everything about %user and %useradd,
1204 # because it's now all been merged into the corresponding $config entry
1205
1206 if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
1207     disable('static', 'pic', 'threads');
1208 }
1209
1210 # Allow overriding the build file name
1211 $config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
1212
1213 # Make sure build_scheme is consistent.
1214 $target{build_scheme} = [ $target{build_scheme} ]
1215     if ref($target{build_scheme}) ne "ARRAY";
1216
1217 my ($builder, $builder_platform, @builder_opts) =
1218     @{$target{build_scheme}};
1219
1220 foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
1221                       $builder_platform."-checker.pm")) {
1222     my $checker_path = catfile($srcdir, "Configurations", $checker);
1223     if (-f $checker_path) {
1224         my $fn = $ENV{CONFIGURE_CHECKER_WARN}
1225             ? sub { warn $@; } : sub { die $@; };
1226         if (! do $checker_path) {
1227             if ($@) {
1228                 $fn->($@);
1229             } elsif ($!) {
1230                 $fn->($!);
1231             } else {
1232                 $fn->("The detected tools didn't match the platform\n");
1233             }
1234         }
1235         last;
1236     }
1237 }
1238
1239 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
1240
1241 if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
1242         {
1243         push @{$config{cflags}}, "-mno-cygwin";
1244         push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
1245         push @{$config{shared_ldflag}}, "-mno-cygwin";
1246         }
1247
1248 if ($target =~ /linux.*-mips/ && !$disabled{asm}
1249         && !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
1250         # minimally required architecture flags for assembly modules
1251         my $value;
1252         $value = '-mips2' if ($target =~ /mips32/);
1253         $value = '-mips3' if ($target =~ /mips64/);
1254         unshift @{$config{cflags}}, $value;
1255         unshift @{$config{cxxflags}}, $value if $config{CXX};
1256 }
1257
1258 # If threads aren't disabled, check how possible they are
1259 unless ($disabled{threads}) {
1260     if ($auto_threads) {
1261         # Enabled by default, disable it forcibly if unavailable
1262         if ($target{thread_scheme} eq "(unknown)") {
1263             disable("unavailable", 'threads');
1264         }
1265     } else {
1266         # The user chose to enable threads explicitly, let's see
1267         # if there's a chance that's possible
1268         if ($target{thread_scheme} eq "(unknown)") {
1269             # If the user asked for "threads" and we don't have internal
1270             # knowledge how to do it, [s]he is expected to provide any
1271             # system-dependent compiler options that are necessary.  We
1272             # can't truly check that the given options are correct, but
1273             # we expect the user to know what [s]He is doing.
1274             if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
1275                 die "You asked for multi-threading support, but didn't\n"
1276                     ,"provide any system-specific compiler options\n";
1277             }
1278         }
1279     }
1280 }
1281
1282 # If threads still aren't disabled, add a C macro to ensure the source
1283 # code knows about it.  Any other flag is taken care of by the configs.
1284 unless($disabled{threads}) {
1285     push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS";
1286 }
1287
1288 # With "deprecated" disable all deprecated features.
1289 if (defined($disabled{"deprecated"})) {
1290         $config{api} = $maxapi;
1291 }
1292
1293 my $no_shared_warn=0;
1294 if ($target{shared_target} eq "")
1295         {
1296         $no_shared_warn = 1
1297             if (!$disabled{shared} || !$disabled{"dynamic-engine"});
1298         disable('no-shared-target', 'pic');
1299         }
1300
1301 if ($disabled{"dynamic-engine"}) {
1302         $config{dynamic_engines} = 0;
1303 } else {
1304         $config{dynamic_engines} = 1;
1305 }
1306
1307 unless ($disabled{asan}) {
1308     push @{$config{cflags}}, "-fsanitize=address";
1309 }
1310
1311 unless ($disabled{ubsan}) {
1312     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
1313     # platforms.
1314     push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
1315 }
1316
1317 unless ($disabled{msan}) {
1318   push @{$config{cflags}}, "-fsanitize=memory";
1319 }
1320
1321 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
1322         && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
1323     push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
1324     push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
1325 }
1326 #
1327 # Platform fix-ups
1328 #
1329
1330 # This saves the build files from having to check
1331 if ($disabled{pic})
1332         {
1333         foreach (qw(shared_cflag shared_cxxflag shared_cppflag
1334                     shared_defines shared_includes shared_ldflag
1335                     module_cflags module_cxxflags module_cppflags
1336                     module_defines module_includes module_lflags))
1337                 {
1338                 delete $config{$_};
1339                 $target{$_} = "";
1340                 }
1341         }
1342 else
1343         {
1344         push @{$config{lib_defines}}, "OPENSSL_PIC";
1345         }
1346
1347 if ($target{sys_id} ne "")
1348         {
1349         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1350         }
1351
1352 unless ($disabled{asm}) {
1353     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1354     push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c");
1355
1356     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1357
1358     # bn-586 is the only one implementing bn_*_part_words
1359     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1360     push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/);
1361
1362     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1363     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1364     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1365     push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/);
1366
1367     if ($target{sha1_asm_src}) {
1368         push @{$config{lib_defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1369         push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1370         push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1371     }
1372     if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
1373         push @{$config{lib_defines}}, "KECCAK1600_ASM";
1374     }
1375     if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
1376         push @{$config{lib_defines}}, "RC4_ASM";
1377     }
1378     if ($target{md5_asm_src}) {
1379         push @{$config{lib_defines}}, "MD5_ASM";
1380     }
1381     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1382     if ($target{rmd160_asm_src}) {
1383         push @{$config{lib_defines}}, "RMD160_ASM";
1384     }
1385     if ($target{aes_asm_src}) {
1386         push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1387         push @{$config{lib_defines}}, "AESNI_ASM" if ($target{aes_asm_src} =~ m/\baesni-/);;
1388         # aes-ctr.fake is not a real file, only indication that assembler
1389         # module implements AES_ctr32_encrypt...
1390         push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1391         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1392         push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1393         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
1394         push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1395         push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1396     }
1397     if ($target{wp_asm_src} =~ /mmx/) {
1398         if ($config{processor} eq "386") {
1399             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1400         } elsif (!$disabled{"whirlpool"}) {
1401             push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
1402         }
1403     }
1404     if ($target{modes_asm_src} =~ /ghash-/) {
1405         push @{$config{lib_defines}}, "GHASH_ASM";
1406     }
1407     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1408         push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
1409     }
1410     if ($target{ec_asm_src} =~ /x25519/) {
1411         push @{$config{lib_defines}}, "X25519_ASM";
1412     }
1413     if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
1414         push @{$config{dso_defines}}, "PADLOCK_ASM";
1415     }
1416     if ($target{poly1305_asm_src} ne "") {
1417         push @{$config{lib_defines}}, "POLY1305_ASM";
1418     }
1419 }
1420
1421 my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
1422 my %predefined_CXX = $config{CXX}
1423     ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
1424     : ();
1425
1426 # Check for makedepend capabilities.
1427 if (!$disabled{makedepend}) {
1428     if ($config{target} =~ /^(VC|vms)-/) {
1429         # For VC- and vms- targets, there's nothing more to do here.  The
1430         # functionality is hard coded in the corresponding build files for
1431         # cl (Windows) and CC/DECC (VMS).
1432     } elsif (($predefined_C{__GNUC__} // -1) >= 3
1433              && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
1434         # We know that GNU C version 3 and up as well as all clang
1435         # versions support dependency generation, but Xcode did not
1436         # handle $cc -M before clang support (but claims __GNUC__ = 3)
1437         $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}";
1438     } else {
1439         # In all other cases, we look for 'makedepend', and disable the
1440         # capability if not found.
1441         $config{makedepprog} = which('makedepend');
1442         disable('unavailable', 'makedepend') unless $config{makedepprog};
1443     }
1444 }
1445
1446 if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
1447     # probe for -Wa,--noexecstack option...
1448     if ($predefined_C{__clang__}) {
1449         # clang has builtin assembler, which doesn't recognize --help,
1450         # but it apparently recognizes the option in question on all
1451         # supported platforms even when it's meaningless. In other words
1452         # probe would fail, but probed option always accepted...
1453         push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
1454     } else {
1455         my $cc = $config{CROSS_COMPILE}.$config{CC};
1456         open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
1457         while(<PIPE>) {
1458             if (m/--noexecstack/) {
1459                 push @{$config{cflags}}, "-Wa,--noexecstack";
1460                 last;
1461             }
1462         }
1463         close(PIPE);
1464         unlink("null.$$.o");
1465     }
1466 }
1467
1468 # Deal with bn_ops ###################################################
1469
1470 $config{bn_ll}                  =0;
1471 $config{export_var_as_fn}       =0;
1472 my $def_int="unsigned int";
1473 $config{rc4_int}                =$def_int;
1474 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1475
1476 my $count = 0;
1477 foreach (sort split(/\s+/,$target{bn_ops})) {
1478     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1479     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1480     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1481     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1482     ($config{b64l},$config{b64},$config{b32})
1483         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1484     ($config{b64l},$config{b64},$config{b32})
1485         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1486     ($config{b64l},$config{b64},$config{b32})
1487         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1488 }
1489 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1490     if $count > 1;
1491
1492
1493 # Hack cflags for better warnings (dev option) #######################
1494
1495 # "Stringify" the C and C++ flags string.  This permits it to be made part of
1496 # a string and works as well on command lines.
1497 $config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1498                         @{$config{cflags}} ];
1499 $config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1500                           @{$config{cxxflags}} ] if $config{CXX};
1501
1502 if (defined($config{api})) {
1503     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1504     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1505     push @{$config{defines}}, $apiflag;
1506 }
1507
1508 my @strict_warnings_collection=();
1509 if ($strict_warnings)
1510         {
1511         my $wopt;
1512         my $gccver = $predefined_C{__GNUC__} // -1;
1513
1514         if ($gccver >= 4)
1515                 {
1516                 push @strict_warnings_collection, @gcc_devteam_warn;
1517                 push @strict_warnings_collection, @clang_devteam_warn
1518                     if (defined($predefined_C{__clang__}));
1519                 }
1520         elsif ($config{target} =~ /^VC-/)
1521                 {
1522                 push @strict_warnings_collection, @cl_devteam_warn;
1523                 }
1524         else
1525                 {
1526                 warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike, or MSVC"
1527                 }
1528         }
1529
1530 $config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
1531                               ? @strict_warnings_collection
1532                               : ( $_ ) }
1533                     @{$config{CFLAGS}} ];
1534
1535 unless ($disabled{"crypto-mdebug-backtrace"})
1536         {
1537         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1538                 {
1539                 push @{$config{cflags}}, $wopt
1540                         unless grep { $_ eq $wopt } @{$config{cflags}};
1541                 }
1542         if ($target =~ /^BSD-/)
1543                 {
1544                 push @{$config{ex_libs}}, "-lexecinfo";
1545                 }
1546         }
1547
1548 unless ($disabled{afalgeng}) {
1549     $config{afalgeng}="";
1550     if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
1551         my $minver = 4*10000 + 1*100 + 0;
1552         if ($config{CROSS_COMPILE} eq "") {
1553             my $verstr = `uname -r`;
1554             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1555             ($mi2) = $mi2 =~ /(\d+)/;
1556             my $ver = $ma*10000 + $mi1*100 + $mi2;
1557             if ($ver < $minver) {
1558                 disable('too-old-kernel', 'afalgeng');
1559             } else {
1560                 push @{$config{engdirs}}, "afalg";
1561             }
1562         } else {
1563             disable('cross-compiling', 'afalgeng');
1564         }
1565     } else {
1566         disable('not-linux', 'afalgeng');
1567     }
1568 }
1569
1570 unless ($disabled{devcryptoeng}) {
1571     if ($target =~ m/^BSD/) {
1572         my $maxver = 5*100 + 7;
1573         my $sysstr = `uname -s`;
1574         my $verstr = `uname -r`;
1575         $sysstr =~ s|\R$||;
1576         $verstr =~ s|\R$||;
1577         my ($ma, $mi, @rest) = split m|\.|, $verstr;
1578         my $ver = $ma*100 + $mi;
1579         if ($sysstr eq 'OpenBSD' && $ver >= $maxver) {
1580             disable('too-new-kernel', 'devcryptoeng');
1581         }
1582     }
1583 }
1584
1585 unless ($disabled{ktls}) {
1586     $config{ktls}="";
1587     if ($target =~ m/^linux/) {
1588         my $usr = "/usr/$config{cross_compile_prefix}";
1589         chop($usr);
1590         if ($config{cross_compile_prefix} eq "") {
1591             $usr = "/usr";
1592         }
1593         my $minver = (4 << 16) + (13 << 8) + 0;
1594         my @verstr = split(" ",`cat $usr/include/linux/version.h | grep LINUX_VERSION_CODE`);
1595
1596         if ($verstr[2] < $minver) {
1597             disable('too-old-kernel', 'ktls');
1598         }
1599     } elsif ($target =~ m/^BSD/) {
1600         my $cc = $config{CROSS_COMPILE}.$config{CC};
1601         system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
1602         if ($? != 0) {
1603             disable('too-old-freebsd', 'ktls');
1604         }
1605     } else {
1606         disable('not-linux-or-freebsd', 'ktls');
1607     }
1608 }
1609
1610 push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
1611
1612 # Get the extra flags used when building shared libraries and modules.  We
1613 # do this late because some of them depend on %disabled.
1614
1615 # Make the flags to build DSOs the same as for shared libraries unless they
1616 # are already defined
1617 $target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
1618 $target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
1619 $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
1620 {
1621     my $shared_info_pl =
1622         catfile(dirname($0), "Configurations", "shared-info.pl");
1623     my %shared_info = read_eval_file($shared_info_pl);
1624     push @{$target{_conf_fname_int}}, $shared_info_pl;
1625     my $si = $target{shared_target};
1626     while (ref $si ne "HASH") {
1627         last if ! defined $si;
1628         if (ref $si eq "CODE") {
1629             $si = $si->();
1630         } else {
1631             $si = $shared_info{$si};
1632         }
1633     }
1634
1635     # Some of the 'shared_target' values don't have any entries in
1636     # %shared_info.  That's perfectly fine, AS LONG AS the build file
1637     # template knows how to handle this.  That is currently the case for
1638     # Windows and VMS.
1639     if (defined $si) {
1640         # Just as above, copy certain shared_* attributes to the corresponding
1641         # module_ attribute unless the latter is already defined
1642         $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
1643         $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
1644         $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
1645         foreach (sort keys %$si) {
1646             $target{$_} = defined $target{$_}
1647                 ? add($si->{$_})->($target{$_})
1648                 : $si->{$_};
1649         }
1650     }
1651 }
1652
1653 # ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
1654
1655 my %disabled_info = ();         # For configdata.pm
1656 foreach my $what (sort keys %disabled) {
1657     $config{options} .= " no-$what";
1658
1659     if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic',
1660                                 'dynamic-engine', 'makedepend',
1661                                 'zlib-dynamic', 'zlib', 'sse2' )) {
1662         (my $WHAT = uc $what) =~ s|-|_|g;
1663
1664         # Fix up C macro end names
1665         $WHAT = "RMD160" if $what eq "ripemd";
1666
1667         # fix-up crypto/directory name(s)
1668         $what = "ripemd" if $what eq "rmd160";
1669         $what = "whrlpool" if $what eq "whirlpool";
1670
1671         my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
1672
1673         if ((grep { $what eq $_ } @{$config{sdirs}})
1674                 && $what ne 'async' && $what ne 'err' && $what ne 'dso') {
1675             @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}};
1676             $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ];
1677
1678             if ($what ne 'engine') {
1679                 push @{$config{openssl_algorithm_defines}}, $macro;
1680             } else {
1681                 @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
1682                 push @{$disabled_info{engine}->{skipped}}, catdir('engines');
1683                 push @{$config{openssl_other_defines}}, $macro;
1684             }
1685         } else {
1686             push @{$config{openssl_other_defines}}, $macro;
1687         }
1688
1689     }
1690 }
1691
1692 if ($disabled{"dynamic-engine"}) {
1693     push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
1694 } else {
1695     push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE";
1696 }
1697
1698 # If we use the unified build, collect information from build.info files
1699 my %unified_info = ();
1700
1701 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1702 if ($builder eq "unified") {
1703     use with_fallback qw(Text::Template);
1704
1705     sub cleandir {
1706         my $base = shift;
1707         my $dir = shift;
1708         my $relativeto = shift || ".";
1709
1710         $dir = catdir($base,$dir) unless isabsolute($dir);
1711
1712         # Make sure the directories we're building in exists
1713         mkpath($dir);
1714
1715         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1716         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1717         return $res;
1718     }
1719
1720     sub cleanfile {
1721         my $base = shift;
1722         my $file = shift;
1723         my $relativeto = shift || ".";
1724
1725         $file = catfile($base,$file) unless isabsolute($file);
1726
1727         my $d = dirname($file);
1728         my $f = basename($file);
1729
1730         # Make sure the directories we're building in exists
1731         mkpath($d);
1732
1733         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1734         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1735         return $res;
1736     }
1737
1738     # Store the name of the template file we will build the build file from
1739     # in %config.  This may be useful for the build file itself.
1740     my @build_file_template_names =
1741         ( $builder_platform."-".$target{build_file}.".tmpl",
1742           $target{build_file}.".tmpl" );
1743     my @build_file_templates = ();
1744
1745     # First, look in the user provided directory, if given
1746     if (defined env($local_config_envname)) {
1747         @build_file_templates =
1748             map {
1749                 if ($^O eq 'VMS') {
1750                     # VMS environment variables are logical names,
1751                     # which can be used as is
1752                     $local_config_envname . ':' . $_;
1753                 } else {
1754                     catfile(env($local_config_envname), $_);
1755                 }
1756             }
1757             @build_file_template_names;
1758     }
1759     # Then, look in our standard directory
1760     push @build_file_templates,
1761         ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
1762           @build_file_template_names );
1763
1764     my $build_file_template;
1765     for $_ (@build_file_templates) {
1766         $build_file_template = $_;
1767         last if -f $build_file_template;
1768
1769         $build_file_template = undef;
1770     }
1771     if (!defined $build_file_template) {
1772         die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
1773     }
1774     $config{build_file_templates}
1775       = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
1776                     $blddir),
1777           $build_file_template,
1778           cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
1779                     $blddir) ];
1780
1781     my @build_infos = ( [ ".", "build.info" ] );
1782     foreach (@{$config{dirs}}) {
1783         push @build_infos, [ $_, "build.info" ]
1784             if (-f catfile($srcdir, $_, "build.info"));
1785     }
1786     foreach (@{$config{sdirs}}) {
1787         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1788             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1789     }
1790     foreach (@{$config{engdirs}}) {
1791         push @build_infos, [ catdir("engines", $_), "build.info" ]
1792             if (-f catfile($srcdir, "engines", $_, "build.info"));
1793     }
1794     foreach (@{$config{tdirs}}) {
1795         push @build_infos, [ catdir("test", $_), "build.info" ]
1796             if (-f catfile($srcdir, "test", $_, "build.info"));
1797     }
1798
1799     $config{build_infos} = [ ];
1800
1801     my %ordinals = ();
1802     foreach (@build_infos) {
1803         my $sourced = catdir($srcdir, $_->[0]);
1804         my $buildd = catdir($blddir, $_->[0]);
1805
1806         mkpath($buildd);
1807
1808         my $f = $_->[1];
1809         # The basic things we're trying to build
1810         my @programs = ();
1811         my @programs_install = ();
1812         my @libraries = ();
1813         my @libraries_install = ();
1814         my @engines = ();
1815         my @engines_install = ();
1816         my @scripts = ();
1817         my @scripts_install = ();
1818         my @extra = ();
1819         my @overrides = ();
1820         my @intermediates = ();
1821         my @rawlines = ();
1822
1823         my %sources = ();
1824         my %shared_sources = ();
1825         my %includes = ();
1826         my %depends = ();
1827         my %renames = ();
1828         my %sharednames = ();
1829         my %generate = ();
1830
1831         # We want to detect configdata.pm in the source tree, so we
1832         # don't use it if the build tree is different.
1833         my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
1834
1835         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1836         my $template =
1837             Text::Template->new(TYPE => 'FILE',
1838                                 SOURCE => catfile($sourced, $f),
1839                                 PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
1840         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1841         my @text =
1842             split /^/m,
1843             $template->fill_in(HASH => { config => \%config,
1844                                          target => \%target,
1845                                          disabled => \%disabled,
1846                                          withargs => \%withargs,
1847                                          builddir => abs2rel($buildd, $blddir),
1848                                          sourcedir => abs2rel($sourced, $blddir),
1849                                          buildtop => abs2rel($blddir, $blddir),
1850                                          sourcetop => abs2rel($srcdir, $blddir) },
1851                                DELIMITERS => [ "{-", "-}" ]);
1852
1853         # The top item of this stack has the following values
1854         # -2 positive already run and we found ELSE (following ELSIF should fail)
1855         # -1 positive already run (skip until ENDIF)
1856         # 0 negatives so far (if we're at a condition, check it)
1857         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1858         # 2 positive ELSE (following ELSIF should fail)
1859         my @skip = ();
1860         collect_information(
1861             collect_from_array([ @text ],
1862                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1863                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1864             # Info we're looking for
1865             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1866             => sub {
1867                 if (! @skip || $skip[$#skip] > 0) {
1868                     push @skip, !! $1;
1869                 } else {
1870                     push @skip, -1;
1871                 }
1872             },
1873             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1874             => sub { die "ELSIF out of scope" if ! @skip;
1875                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1876                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1877                      $skip[$#skip] = !! $1
1878                          if $skip[$#skip] == 0; },
1879             qr/^\s*ELSE\s*$/
1880             => sub { die "ELSE out of scope" if ! @skip;
1881                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1882                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1883             qr/^\s*ENDIF\s*$/
1884             => sub { die "ENDIF out of scope" if ! @skip;
1885                      pop @skip; },
1886             qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
1887             => sub {
1888                 if (!@skip || $skip[$#skip] > 0) {
1889                     my $install = $1;
1890                     my @x = tokenize($2);
1891                     push @programs, @x;
1892                     push @programs_install, @x unless $install;
1893                 }
1894             },
1895             qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
1896             => sub {
1897                 if (!@skip || $skip[$#skip] > 0) {
1898                     my $install = $1;
1899                     my @x = tokenize($2);
1900                     push @libraries, @x;
1901                     push @libraries_install, @x unless $install;
1902                 }
1903             },
1904             qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
1905             => sub {
1906                 if (!@skip || $skip[$#skip] > 0) {
1907                     my $install = $1;
1908                     my @x = tokenize($2);
1909                     push @engines, @x;
1910                     push @engines_install, @x unless $install;
1911                 }
1912             },
1913             qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
1914             => sub {
1915                 if (!@skip || $skip[$#skip] > 0) {
1916                     my $install = $1;
1917                     my @x = tokenize($2);
1918                     push @scripts, @x;
1919                     push @scripts_install, @x unless $install;
1920                 }
1921             },
1922             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1923             => sub { push @extra, tokenize($1)
1924                          if !@skip || $skip[$#skip] > 0 },
1925             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1926             => sub { push @overrides, tokenize($1)
1927                          if !@skip || $skip[$#skip] > 0 },
1928
1929             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1930             => sub { push @{$ordinals{$1}}, tokenize($2)
1931                          if !@skip || $skip[$#skip] > 0 },
1932             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1933             => sub { push @{$sources{$1}}, tokenize($2)
1934                          if !@skip || $skip[$#skip] > 0 },
1935             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1936             => sub { push @{$shared_sources{$1}}, tokenize($2)
1937                          if !@skip || $skip[$#skip] > 0 },
1938             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1939             => sub { push @{$includes{$1}}, tokenize($2)
1940                          if !@skip || $skip[$#skip] > 0 },
1941             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
1942             => sub { push @{$depends{$1}}, tokenize($2)
1943                          if !@skip || $skip[$#skip] > 0 },
1944             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1945             => sub { push @{$generate{$1}}, $2
1946                          if !@skip || $skip[$#skip] > 0 },
1947             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1948             => sub { push @{$renames{$1}}, tokenize($2)
1949                          if !@skip || $skip[$#skip] > 0 },
1950             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1951             => sub { push @{$sharednames{$1}}, tokenize($2)
1952                          if !@skip || $skip[$#skip] > 0 },
1953             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1954             => sub {
1955                 my $lineiterator = shift;
1956                 my $target_kind = $1;
1957                 while (defined $lineiterator->()) {
1958                     s|\R$||;
1959                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1960                         die "ENDRAW doesn't match BEGINRAW"
1961                             if $1 ne $target_kind;
1962                         last;
1963                     }
1964                     next if @skip && $skip[$#skip] <= 0;
1965                     push @rawlines,  $_
1966                         if ($target_kind eq $target{build_file}
1967                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1968                 }
1969             },
1970             qr/^\s*(?:#.*)?$/ => sub { },
1971             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1972             "BEFORE" => sub {
1973                 if ($buildinfo_debug) {
1974                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1975                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1976                 }
1977             },
1978             "AFTER" => sub {
1979                 if ($buildinfo_debug) {
1980                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1981                 }
1982             },
1983             );
1984         die "runaway IF?" if (@skip);
1985
1986         foreach (keys %renames) {
1987             die "$_ renamed to more than one thing: "
1988                 ,join(" ", @{$renames{$_}}),"\n"
1989                 if scalar @{$renames{$_}} > 1;
1990             my $dest = cleanfile($buildd, $_, $blddir);
1991             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1992             die "$dest renamed to more than one thing: "
1993                 ,$unified_info{rename}->{$dest}, $to
1994                 unless !defined($unified_info{rename}->{$dest})
1995                 or $unified_info{rename}->{$dest} eq $to;
1996             $unified_info{rename}->{$dest} = $to;
1997         }
1998
1999         foreach (@programs) {
2000             my $program = cleanfile($buildd, $_, $blddir);
2001             if ($unified_info{rename}->{$program}) {
2002                 $program = $unified_info{rename}->{$program};
2003             }
2004             $unified_info{programs}->{$program} = 1;
2005         }
2006
2007         foreach (@programs_install) {
2008             my $program = cleanfile($buildd, $_, $blddir);
2009             if ($unified_info{rename}->{$program}) {
2010                 $program = $unified_info{rename}->{$program};
2011             }
2012             $unified_info{install}->{programs}->{$program} = 1;
2013         }
2014
2015         foreach (@libraries) {
2016             my $library = cleanfile($buildd, $_, $blddir);
2017             if ($unified_info{rename}->{$library}) {
2018                 $library = $unified_info{rename}->{$library};
2019             }
2020             $unified_info{libraries}->{$library} = 1;
2021         }
2022
2023         foreach (@libraries_install) {
2024             my $library = cleanfile($buildd, $_, $blddir);
2025             if ($unified_info{rename}->{$library}) {
2026                 $library = $unified_info{rename}->{$library};
2027             }
2028             $unified_info{install}->{libraries}->{$library} = 1;
2029         }
2030
2031         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
2032 ENGINES can only be used if configured with 'dynamic-engine'.
2033 This is usually a fault in a build.info file.
2034 EOF
2035         foreach (@engines) {
2036             my $library = cleanfile($buildd, $_, $blddir);
2037             if ($unified_info{rename}->{$library}) {
2038                 $library = $unified_info{rename}->{$library};
2039             }
2040             $unified_info{engines}->{$library} = 1;
2041         }
2042
2043         foreach (@engines_install) {
2044             my $library = cleanfile($buildd, $_, $blddir);
2045             if ($unified_info{rename}->{$library}) {
2046                 $library = $unified_info{rename}->{$library};
2047             }
2048             $unified_info{install}->{engines}->{$library} = 1;
2049         }
2050
2051         foreach (@scripts) {
2052             my $script = cleanfile($buildd, $_, $blddir);
2053             if ($unified_info{rename}->{$script}) {
2054                 $script = $unified_info{rename}->{$script};
2055             }
2056             $unified_info{scripts}->{$script} = 1;
2057         }
2058
2059         foreach (@scripts_install) {
2060             my $script = cleanfile($buildd, $_, $blddir);
2061             if ($unified_info{rename}->{$script}) {
2062                 $script = $unified_info{rename}->{$script};
2063             }
2064             $unified_info{install}->{scripts}->{$script} = 1;
2065         }
2066
2067         foreach (@extra) {
2068             my $extra = cleanfile($buildd, $_, $blddir);
2069             $unified_info{extra}->{$extra} = 1;
2070         }
2071
2072         foreach (@overrides) {
2073             my $override = cleanfile($buildd, $_, $blddir);
2074             $unified_info{overrides}->{$override} = 1;
2075         }
2076
2077         push @{$unified_info{rawlines}}, @rawlines;
2078
2079         unless ($disabled{shared}) {
2080             # Check sharednames.
2081             foreach (keys %sharednames) {
2082                 my $dest = cleanfile($buildd, $_, $blddir);
2083                 if ($unified_info{rename}->{$dest}) {
2084                     $dest = $unified_info{rename}->{$dest};
2085                 }
2086                 die "shared_name for $dest with multiple values: "
2087                     ,join(" ", @{$sharednames{$_}}),"\n"
2088                     if scalar @{$sharednames{$_}} > 1;
2089                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
2090                 die "shared_name found for a library $dest that isn't defined\n"
2091                     unless $unified_info{libraries}->{$dest};
2092                 die "shared_name for $dest with multiple values: "
2093                     ,$unified_info{sharednames}->{$dest}, ", ", $to
2094                     unless !defined($unified_info{sharednames}->{$dest})
2095                     or $unified_info{sharednames}->{$dest} eq $to;
2096                 $unified_info{sharednames}->{$dest} = $to;
2097             }
2098
2099             # Additionally, we set up sharednames for libraries that don't
2100             # have any, as themselves.  Only for libraries that aren't
2101             # explicitly static.
2102             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
2103                 if (!defined $unified_info{sharednames}->{$_}) {
2104                     $unified_info{sharednames}->{$_} = $_
2105                 }
2106             }
2107
2108             # Check that we haven't defined any library as both shared and
2109             # explicitly static.  That is forbidden.
2110             my @doubles = ();
2111             foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
2112                 (my $l = $_) =~ s/\.a$//;
2113                 push @doubles, $l if defined $unified_info{sharednames}->{$l};
2114             }
2115             die "these libraries are both explicitly static and shared:\n  ",
2116                 join(" ", @doubles), "\n"
2117                 if @doubles;
2118         }
2119
2120         foreach (keys %sources) {
2121             my $dest = $_;
2122             my $ddest = cleanfile($buildd, $_, $blddir);
2123             if ($unified_info{rename}->{$ddest}) {
2124                 $ddest = $unified_info{rename}->{$ddest};
2125             }
2126             foreach (@{$sources{$dest}}) {
2127                 my $s = cleanfile($sourced, $_, $blddir);
2128
2129                 # If it isn't in the source tree, we assume it's generated
2130                 # in the build tree
2131                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
2132                     $s = cleanfile($buildd, $_, $blddir);
2133                 }
2134                 # We recognise C++, C and asm files
2135                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
2136                     my $o = $_;
2137                     $o =~ s/\.[csS]$/.o/; # C and assembler
2138                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
2139                     $o = cleanfile($buildd, $o, $blddir);
2140                     $unified_info{sources}->{$ddest}->{$o} = 1;
2141                     $unified_info{sources}->{$o}->{$s} = 1;
2142                 } elsif ($s =~ /\.rc$/) {
2143                     # We also recognise resource files
2144                     my $o = $_;
2145                     $o =~ s/\.rc$/.res/; # Resource configuration
2146                     my $o = cleanfile($buildd, $o, $blddir);
2147                     $unified_info{sources}->{$ddest}->{$o} = 1;
2148                     $unified_info{sources}->{$o}->{$s} = 1;
2149                 } else {
2150                     $unified_info{sources}->{$ddest}->{$s} = 1;
2151                 }
2152             }
2153         }
2154
2155         foreach (keys %shared_sources) {
2156             my $dest = $_;
2157             my $ddest = cleanfile($buildd, $_, $blddir);
2158             if ($unified_info{rename}->{$ddest}) {
2159                 $ddest = $unified_info{rename}->{$ddest};
2160             }
2161             foreach (@{$shared_sources{$dest}}) {
2162                 my $s = cleanfile($sourced, $_, $blddir);
2163
2164                 # If it isn't in the source tree, we assume it's generated
2165                 # in the build tree
2166                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
2167                     $s = cleanfile($buildd, $_, $blddir);
2168                 }
2169
2170                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
2171                     # We recognise C++, C and asm files
2172                     my $o = $_;
2173                     $o =~ s/\.[csS]$/.o/; # C and assembler
2174                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
2175                     $o = cleanfile($buildd, $o, $blddir);
2176                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
2177                     $unified_info{sources}->{$o}->{$s} = 1;
2178                 } elsif ($s =~ /\.rc$/) {
2179                     # We also recognise resource files
2180                     my $o = $_;
2181                     $o =~ s/\.rc$/.res/; # Resource configuration
2182                     my $o = cleanfile($buildd, $o, $blddir);
2183                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
2184                     $unified_info{sources}->{$o}->{$s} = 1;
2185                 } elsif ($s =~ /\.(def|map|opt)$/) {
2186                     # We also recognise .def / .map / .opt files
2187                     # We know they are generated files
2188                     my $def = cleanfile($buildd, $s, $blddir);
2189                     $unified_info{shared_sources}->{$ddest}->{$def} = 1;
2190                 } else {
2191                     die "unrecognised source file type for shared library: $s\n";
2192                 }
2193             }
2194         }
2195
2196         foreach (keys %generate) {
2197             my $dest = $_;
2198             my $ddest = cleanfile($buildd, $_, $blddir);
2199             if ($unified_info{rename}->{$ddest}) {
2200                 $ddest = $unified_info{rename}->{$ddest};
2201             }
2202             die "more than one generator for $dest: "
2203                     ,join(" ", @{$generate{$_}}),"\n"
2204                     if scalar @{$generate{$_}} > 1;
2205             my @generator = split /\s+/, $generate{$dest}->[0];
2206             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
2207             $unified_info{generate}->{$ddest} = [ @generator ];
2208         }
2209
2210         foreach (keys %depends) {
2211             my $dest = $_;
2212             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
2213
2214             # If the destination doesn't exist in source, it can only be
2215             # a generated file in the build tree.
2216             if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) {
2217                 $ddest = cleanfile($buildd, $_, $blddir);
2218                 if ($unified_info{rename}->{$ddest}) {
2219                     $ddest = $unified_info{rename}->{$ddest};
2220                 }
2221             }
2222             foreach (@{$depends{$dest}}) {
2223                 my $d = cleanfile($sourced, $_, $blddir);
2224
2225                 # If we know it's generated, or assume it is because we can't
2226                 # find it in the source tree, we set file we depend on to be
2227                 # in the build tree rather than the source tree, and assume
2228                 # and that there are lines to build it in a BEGINRAW..ENDRAW
2229                 # section or in the Makefile template.
2230                 if ($d eq $src_configdata
2231                     || ! -f $d
2232                     || (grep { $d eq $_ }
2233                         map { cleanfile($srcdir, $_, $blddir) }
2234                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
2235                     $d = cleanfile($buildd, $_, $blddir);
2236                 }
2237                 # Take note if the file to depend on is being renamed
2238                 # Take extra care with files ending with .a, they should
2239                 # be treated without that extension, and the extension
2240                 # should be added back after treatment.
2241                 $d =~ /(\.a)?$/;
2242                 my $e = $1 // "";
2243                 $d = $`;
2244                 if ($unified_info{rename}->{$d}) {
2245                     $d = $unified_info{rename}->{$d};
2246                 }
2247                 $d .= $e;
2248                 $unified_info{depends}->{$ddest}->{$d} = 1;
2249             }
2250         }
2251
2252         foreach (keys %includes) {
2253             my $dest = $_;
2254             my $ddest = cleanfile($sourced, $_, $blddir);
2255
2256             # If the destination doesn't exist in source, it can only be
2257             # a generated file in the build tree.
2258             if ($ddest eq $src_configdata || ! -f $ddest) {
2259                 $ddest = cleanfile($buildd, $_, $blddir);
2260                 if ($unified_info{rename}->{$ddest}) {
2261                     $ddest = $unified_info{rename}->{$ddest};
2262                 }
2263             }
2264             foreach (@{$includes{$dest}}) {
2265                 my $is = cleandir($sourced, $_, $blddir);
2266                 my $ib = cleandir($buildd, $_, $blddir);
2267                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
2268                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
2269                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
2270                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
2271             }
2272         }
2273     }
2274
2275     my $ordinals_text = join(', ', sort keys %ordinals);
2276     warn <<"EOF" if $ordinals_text;
2277
2278 WARNING: ORDINALS were specified for $ordinals_text
2279 They are ignored and should be replaced with a combination of GENERATE,
2280 DEPEND and SHARED_SOURCE.
2281 EOF
2282
2283     # Massage the result
2284
2285     # If the user configured no-shared, we allow no shared sources
2286     if ($disabled{shared}) {
2287         foreach (keys %{$unified_info{shared_sources}}) {
2288             foreach (keys %{$unified_info{shared_sources}->{$_}}) {
2289                 delete $unified_info{sources}->{$_};
2290             }
2291         }
2292         $unified_info{shared_sources} = {};
2293     }
2294
2295     # If we depend on a header file or a perl module, add an inclusion of
2296     # its directory to allow smoothe inclusion
2297     foreach my $dest (keys %{$unified_info{depends}}) {
2298         next if $dest eq "";
2299         foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
2300             next unless $d =~ /\.(h|pm)$/;
2301             my $i = dirname($d);
2302             my $spot =
2303                 $d eq "configdata.pm" || defined($unified_info{generate}->{$d})
2304                 ? 'build' : 'source';
2305             push @{$unified_info{includes}->{$dest}->{$spot}}, $i
2306                 unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
2307         }
2308     }
2309
2310     # Trickle down includes placed on libraries, engines and programs to
2311     # their sources (i.e. object files)
2312     foreach my $dest (keys %{$unified_info{engines}},
2313                       keys %{$unified_info{libraries}},
2314                       keys %{$unified_info{programs}}) {
2315         foreach my $k (("source", "build")) {
2316             next unless defined($unified_info{includes}->{$dest}->{$k});
2317             my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
2318             foreach my $obj (grep /\.o$/,
2319                              (keys %{$unified_info{sources}->{$dest} // {}},
2320                               keys %{$unified_info{shared_sources}->{$dest} // {}})) {
2321                 foreach my $inc (@incs) {
2322                     unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
2323                         unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
2324                 }
2325             }
2326         }
2327         delete $unified_info{includes}->{$dest};
2328     }
2329
2330     ### Make unified_info a bit more efficient
2331     # One level structures
2332     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
2333         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
2334     }
2335     # Two level structures
2336     foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
2337         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
2338             $unified_info{$l1}->{$l2} =
2339                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
2340         }
2341     }
2342     # Includes
2343     foreach my $dest (sort keys %{$unified_info{includes}}) {
2344         if (defined($unified_info{includes}->{$dest}->{build})) {
2345             my @source_includes = ();
2346             @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
2347                 if defined($unified_info{includes}->{$dest}->{source});
2348             $unified_info{includes}->{$dest} =
2349                 [ @{$unified_info{includes}->{$dest}->{build}} ];
2350             foreach my $inc (@source_includes) {
2351                 push @{$unified_info{includes}->{$dest}}, $inc
2352                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
2353             }
2354         } else {
2355             $unified_info{includes}->{$dest} =
2356                 [ @{$unified_info{includes}->{$dest}->{source}} ];
2357         }
2358     }
2359
2360     # For convenience collect information regarding directories where
2361     # files are generated, those generated files and the end product
2362     # they end up in where applicable.  Then, add build rules for those
2363     # directories
2364     my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
2365                      "dso" => [ @{$unified_info{engines}} ],
2366                      "bin" => [ @{$unified_info{programs}} ],
2367                      "script" => [ @{$unified_info{scripts}} ] );
2368     foreach my $type (keys %loopinfo) {
2369         foreach my $product (@{$loopinfo{$type}}) {
2370             my %dirs = ();
2371             my $pd = dirname($product);
2372
2373             foreach (@{$unified_info{sources}->{$product} // []},
2374                      @{$unified_info{shared_sources}->{$product} // []}) {
2375                 my $d = dirname($_);
2376
2377                 # We don't want to create targets for source directories
2378                 # when building out of source
2379                 next if ($config{sourcedir} ne $config{builddir}
2380                              && $d =~ m|^\Q$config{sourcedir}\E|);
2381                 # We already have a "test" target, and the current directory
2382                 # is just silly to make a target for
2383                 next if $d eq "test" || $d eq ".";
2384
2385                 $dirs{$d} = 1;
2386                 push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
2387                     if $d ne $pd;
2388             }
2389             foreach (keys %dirs) {
2390                 push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
2391                     $product;
2392             }
2393         }
2394     }
2395 }
2396
2397 # For the schemes that need it, we provide the old *_obj configs
2398 # from the *_asm_obj ones
2399 foreach (grep /_(asm|aux)_src$/, keys %target) {
2400     my $src = $_;
2401     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
2402     $target{$obj} = $target{$src};
2403     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
2404     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
2405 }
2406
2407 # Write down our configuration where it fits #########################
2408
2409 print "Creating configdata.pm\n";
2410 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
2411 print OUT <<"EOF";
2412 #! $config{HASHBANGPERL}
2413
2414 package configdata;
2415
2416 use strict;
2417 use warnings;
2418
2419 use Exporter;
2420 #use vars qw(\@ISA \@EXPORT);
2421 our \@ISA = qw(Exporter);
2422 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
2423
2424 EOF
2425 print OUT "our %config = (\n";
2426 foreach (sort keys %config) {
2427     if (ref($config{$_}) eq "ARRAY") {
2428         print OUT "  ", $_, " => [ ", join(", ",
2429                                            map { quotify("perl", $_) }
2430                                            @{$config{$_}}), " ],\n";
2431     } elsif (ref($config{$_}) eq "HASH") {
2432         print OUT "  ", $_, " => {";
2433         if (scalar keys %{$config{$_}} > 0) {
2434             print OUT "\n";
2435             foreach my $key (sort keys %{$config{$_}}) {
2436                 print OUT "      ",
2437                     join(" => ",
2438                          quotify("perl", $key),
2439                          defined $config{$_}->{$key}
2440                              ? quotify("perl", $config{$_}->{$key})
2441                              : "undef");
2442                 print OUT ",\n";
2443             }
2444             print OUT "  ";
2445         }
2446         print OUT "},\n";
2447     } else {
2448         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
2449     }
2450 }
2451 print OUT <<"EOF";
2452 );
2453
2454 EOF
2455 print OUT "our %target = (\n";
2456 foreach (sort keys %target) {
2457     if (ref($target{$_}) eq "ARRAY") {
2458         print OUT "  ", $_, " => [ ", join(", ",
2459                                            map { quotify("perl", $_) }
2460                                            @{$target{$_}}), " ],\n";
2461     } else {
2462         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
2463     }
2464 }
2465 print OUT <<"EOF";
2466 );
2467
2468 EOF
2469 print OUT "our \%available_protocols = (\n";
2470 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
2471 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
2472 print OUT <<"EOF";
2473 );
2474
2475 EOF
2476 print OUT "our \@disablables = (\n";
2477 foreach (@disablables) {
2478     print OUT "  ", quotify("perl", $_), ",\n";
2479 }
2480 print OUT <<"EOF";
2481 );
2482
2483 EOF
2484 print OUT "our \%disabled = (\n";
2485 foreach (sort keys %disabled) {
2486     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
2487 }
2488 print OUT <<"EOF";
2489 );
2490
2491 EOF
2492 print OUT "our %withargs = (\n";
2493 foreach (sort keys %withargs) {
2494     if (ref($withargs{$_}) eq "ARRAY") {
2495         print OUT "  ", $_, " => [ ", join(", ",
2496                                            map { quotify("perl", $_) }
2497                                            @{$withargs{$_}}), " ],\n";
2498     } else {
2499         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
2500     }
2501 }
2502 print OUT <<"EOF";
2503 );
2504
2505 EOF
2506 if ($builder eq "unified") {
2507     my $recurse;
2508     $recurse = sub {
2509         my $indent = shift;
2510         foreach (@_) {
2511             if (ref $_ eq "ARRAY") {
2512                 print OUT " "x$indent, "[\n";
2513                 foreach (@$_) {
2514                     $recurse->($indent + 4, $_);
2515                 }
2516                 print OUT " "x$indent, "],\n";
2517             } elsif (ref $_ eq "HASH") {
2518                 my %h = %$_;
2519                 print OUT " "x$indent, "{\n";
2520                 foreach (sort keys %h) {
2521                     if (ref $h{$_} eq "") {
2522                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
2523                     } else {
2524                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
2525                         $recurse->($indent + 8, $h{$_});
2526                     }
2527                 }
2528                 print OUT " "x$indent, "},\n";
2529             } else {
2530                 print OUT " "x$indent, quotify("perl", $_), ",\n";
2531             }
2532         }
2533     };
2534     print OUT "our %unified_info = (\n";
2535     foreach (sort keys %unified_info) {
2536         if (ref $unified_info{$_} eq "") {
2537             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
2538         } else {
2539             print OUT " "x4, quotify("perl", $_), " =>\n";
2540             $recurse->(8, $unified_info{$_});
2541         }
2542     }
2543     print OUT <<"EOF";
2544 );
2545
2546 EOF
2547 }
2548 print OUT
2549     "# The following data is only used when this files is use as a script\n";
2550 print OUT "my \@makevars = (\n";
2551 foreach (sort keys %user) {
2552     print OUT "    '",$_,"',\n";
2553 }
2554 print OUT ");\n";
2555 print OUT "my \%disabled_info = (\n";
2556 foreach my $what (sort keys %disabled_info) {
2557     print OUT "    '$what' => {\n";
2558     foreach my $info (sort keys %{$disabled_info{$what}}) {
2559         if (ref $disabled_info{$what}->{$info} eq 'ARRAY') {
2560             print OUT "        $info => [ ",
2561                 join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}),
2562                 " ],\n";
2563         } else {
2564             print OUT "        $info => '", $disabled_info{$what}->{$info},
2565                 "',\n";
2566         }
2567     }
2568     print OUT "    },\n";
2569 }
2570 print OUT ");\n";
2571 print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n";
2572 print OUT << 'EOF';
2573 # If run directly, we can give some answers, and even reconfigure
2574 unless (caller) {
2575     use Getopt::Long;
2576     use File::Spec::Functions;
2577     use File::Basename;
2578     use Pod::Usage;
2579
2580     my $here = dirname($0);
2581
2582     my $dump = undef;
2583     my $cmdline = undef;
2584     my $options = undef;
2585     my $target = undef;
2586     my $envvars = undef;
2587     my $makevars = undef;
2588     my $buildparams = undef;
2589     my $reconf = undef;
2590     my $verbose = undef;
2591     my $help = undef;
2592     my $man = undef;
2593     GetOptions('dump|d'                 => \$dump,
2594                'command-line|c'         => \$cmdline,
2595                'options|o'              => \$options,
2596                'target|t'               => \$target,
2597                'environment|e'          => \$envvars,
2598                'make-variables|m'       => \$makevars,
2599                'build-parameters|b'     => \$buildparams,
2600                'reconfigure|reconf|r'   => \$reconf,
2601                'verbose|v'              => \$verbose,
2602                'help'                   => \$help,
2603                'man'                    => \$man)
2604         or die "Errors in command line arguments\n";
2605
2606     unless ($dump || $cmdline || $options || $target || $envvars || $makevars
2607             || $buildparams || $reconf || $verbose || $help || $man) {
2608         print STDERR <<"_____";
2609 You must give at least one option.
2610 For more information, do '$0 --help'
2611 _____
2612         exit(2);
2613     }
2614
2615     if ($help) {
2616         pod2usage(-exitval => 0,
2617                   -verbose => 1);
2618     }
2619     if ($man) {
2620         pod2usage(-exitval => 0,
2621                   -verbose => 2);
2622     }
2623     if ($dump || $cmdline) {
2624         print "\nCommand line (with current working directory = $here):\n\n";
2625         print '    ',join(' ',
2626                           $config{PERL},
2627                           catfile($config{sourcedir}, 'Configure'),
2628                           @{$config{perlargv}}), "\n";
2629         print "\nPerl information:\n\n";
2630         print '    ',$config{perl_cmd},"\n";
2631         print '    ',$config{perl_version},' for ',$config{perl_archname},"\n";
2632     }
2633     if ($dump || $options) {
2634         my $longest = 0;
2635         my $longest2 = 0;
2636         foreach my $what (@disablables) {
2637             $longest = length($what) if $longest < length($what);
2638             $longest2 = length($disabled{$what})
2639                 if $disabled{$what} && $longest2 < length($disabled{$what});
2640         }
2641         print "\nEnabled features:\n\n";
2642         foreach my $what (@disablables) {
2643             print "    $what\n"
2644                 unless grep { $_ =~ /^${what}$/ } keys %disabled;
2645         }
2646         print "\nDisabled features:\n\n";
2647         foreach my $what (@disablables) {
2648             my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled;
2649             my $what3 = $what2[0];
2650             if ($what3) {
2651                 print "    $what3", ' ' x ($longest - length($what3) + 1),
2652                     "[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1);
2653                 print $disabled_info{$what3}->{macro}
2654                     if $disabled_info{$what3}->{macro};
2655                 print ' (skip ',
2656                     join(', ', @{$disabled_info{$what3}->{skipped}}),
2657                     ')'
2658                     if $disabled_info{$what3}->{skipped};
2659                 print "\n";
2660             }
2661         }
2662     }
2663     if ($dump || $target) {
2664         print "\nConfig target attributes:\n\n";
2665         foreach (sort keys %target) {
2666             next if $_ =~ m|^_| || $_ eq 'template';
2667             my $quotify = sub {
2668                 map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
2669             };
2670             print '    ', $_, ' => ';
2671             if (ref($target{$_}) eq "ARRAY") {
2672                 print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
2673             } else {
2674                 print $quotify->($target{$_}), ",\n"
2675             }
2676         }
2677     }
2678     if ($dump || $envvars) {
2679         print "\nRecorded environment:\n\n";
2680         foreach (sort keys %{$config{perlenv}}) {
2681             print '    ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
2682         }
2683     }
2684     if ($dump || $makevars) {
2685         print "\nMakevars:\n\n";
2686         foreach my $var (@makevars) {
2687             my $prefix = '';
2688             $prefix = $config{CROSS_COMPILE}
2689                 if grep { $var eq $_ } @user_crossable;
2690             $prefix //= '';
2691             print '    ',$var,' ' x (16 - length $var),'= ',
2692                 (ref $config{$var} eq 'ARRAY'
2693                  ? join(' ', @{$config{$var}})
2694                  : $prefix.$config{$var}),
2695                 "\n"
2696                 if defined $config{$var};
2697         }
2698
2699         my @buildfile = ($config{builddir}, $config{build_file});
2700         unshift @buildfile, $here
2701             unless file_name_is_absolute($config{builddir});
2702         my $buildfile = canonpath(catdir(@buildfile));
2703         print <<"_____";
2704
2705 NOTE: These variables only represent the configuration view.  The build file
2706 template may have processed these variables further, please have a look at the
2707 build file for more exact data:
2708     $buildfile
2709 _____
2710     }
2711     if ($dump || $buildparams) {
2712         my @buildfile = ($config{builddir}, $config{build_file});
2713         unshift @buildfile, $here
2714             unless file_name_is_absolute($config{builddir});
2715         print "\nbuild file:\n\n";
2716         print "    ", canonpath(catfile(@buildfile)),"\n";
2717
2718         print "\nbuild file templates:\n\n";
2719         foreach (@{$config{build_file_templates}}) {
2720             my @tmpl = ($_);
2721             unshift @tmpl, $here
2722                 unless file_name_is_absolute($config{sourcedir});
2723             print '    ',canonpath(catfile(@tmpl)),"\n";
2724         }
2725     }
2726     if ($reconf) {
2727         if ($verbose) {
2728             print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
2729             foreach (sort keys %{$config{perlenv}}) {
2730                 print '    ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
2731             }
2732         }
2733
2734         chdir $here;
2735         exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
2736     }
2737 }
2738
2739 1;
2740
2741 __END__
2742
2743 =head1 NAME
2744
2745 configdata.pm - configuration data for OpenSSL builds
2746
2747 =head1 SYNOPSIS
2748
2749 Interactive:
2750
2751   perl configdata.pm [options]
2752
2753 As data bank module:
2754
2755   use configdata;
2756
2757 =head1 DESCRIPTION
2758
2759 This module can be used in two modes, interactively and as a module containing
2760 all the data recorded by OpenSSL's Configure script.
2761
2762 When used interactively, simply run it as any perl script, with at least one
2763 option, and you will get the information you ask for.  See L</OPTIONS> below.
2764
2765 When loaded as a module, you get a few databanks with useful information to
2766 perform build related tasks.  The databanks are:
2767
2768     %config             Configured things.
2769     %target             The OpenSSL config target with all inheritances
2770                         resolved.
2771     %disabled           The features that are disabled.
2772     @disablables        The list of features that can be disabled.
2773     %withargs           All data given through --with-THING options.
2774     %unified_info       All information that was computed from the build.info
2775                         files.
2776
2777 =head1 OPTIONS
2778
2779 =over 4
2780
2781 =item B<--help>
2782
2783 Print a brief help message and exit.
2784
2785 =item B<--man>
2786
2787 Print the manual page and exit.
2788
2789 =item B<--dump> | B<-d>
2790
2791 Print all relevant configuration data.  This is equivalent to B<--command-line>
2792 B<--options> B<--target> B<--environment> B<--make-variables>
2793 B<--build-parameters>.
2794
2795 =item B<--command-line> | B<-c>
2796
2797 Print the current configuration command line.
2798
2799 =item B<--options> | B<-o>
2800
2801 Print the features, both enabled and disabled, and display defined macro and
2802 skipped directories where applicable.
2803
2804 =item B<--target> | B<-t>
2805
2806 Print the config attributes for this config target.
2807
2808 =item B<--environment> | B<-e>
2809
2810 Print the environment variables and their values at the time of configuration.
2811
2812 =item B<--make-variables> | B<-m>
2813
2814 Print the main make variables generated in the current configuration
2815
2816 =item B<--build-parameters> | B<-b>
2817
2818 Print the build parameters, i.e. build file and build file templates.
2819
2820 =item B<--reconfigure> | B<--reconf> | B<-r>
2821
2822 Redo the configuration.
2823
2824 =item B<--verbose> | B<-v>
2825
2826 Verbose output.
2827
2828 =back
2829
2830 =cut
2831
2832 EOF
2833 close(OUT);
2834 if ($builder_platform eq 'unix') {
2835     my $mode = (0755 & ~umask);
2836     chmod $mode, 'configdata.pm'
2837         or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
2838 }
2839
2840 my %builders = (
2841     unified => sub {
2842         print 'Creating ',$target{build_file},"\n";
2843         run_dofile(catfile($blddir, $target{build_file}),
2844                    @{$config{build_file_templates}});
2845     },
2846     );
2847
2848 $builders{$builder}->($builder_platform, @builder_opts);
2849
2850 $SIG{__DIE__} = $orig_death_handler;
2851
2852 print <<"EOF" if ($disabled{threads} eq "unavailable");
2853
2854 The library could not be configured for supporting multi-threaded
2855 applications as the compiler options required on this system are not known.
2856 See file INSTALL for details if you need multi-threading.
2857 EOF
2858
2859 print <<"EOF" if ($no_shared_warn);
2860
2861 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2862 platform, so we will pretend you gave the option 'no-pic', which also disables
2863 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2864 or position independent code, please let us know (but please first make sure
2865 you have tried with a current version of OpenSSL).
2866 EOF
2867
2868 print <<"EOF";
2869
2870 **********************************************************************
2871 ***                                                                ***
2872 ***   OpenSSL has been successfully configured                     ***
2873 ***                                                                ***
2874 ***   If you encounter a problem while building, please open an    ***
2875 ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
2876 ***   and include the output from the following command:           ***
2877 ***                                                                ***
2878 ***       perl configdata.pm --dump                                ***
2879 ***                                                                ***
2880 ***   (If you are new to OpenSSL, you might want to consult the    ***
2881 ***   'Troubleshooting' section in the INSTALL file first)         ***
2882 ***                                                                ***
2883 **********************************************************************
2884 EOF
2885
2886 exit(0);
2887
2888 ######################################################################
2889 #
2890 # Helpers and utility functions
2891 #
2892
2893 # Death handler, to print a helpful message in case of failure #######
2894 #
2895 sub death_handler {
2896     die @_ if $^S;              # To prevent the added message in eval blocks
2897     my $build_file = $target{build_file} // "build file";
2898     my @message = ( <<"_____", @_ );
2899
2900 Failure!  $build_file wasn't produced.
2901 Please read INSTALL and associated NOTES files.  You may also have to look over
2902 your available compiler tool chain or change your configuration.
2903
2904 _____
2905
2906     # Dying is terminal, so it's ok to reset the signal handler here.
2907     $SIG{__DIE__} = $orig_death_handler;
2908     die @message;
2909 }
2910
2911 # Configuration file reading #########################################
2912
2913 # Note: All of the helper functions are for lazy evaluation.  They all
2914 # return a CODE ref, which will return the intended value when evaluated.
2915 # Thus, whenever there's mention of a returned value, it's about that
2916 # intended value.
2917
2918 # Helper function to implement conditional inheritance depending on the
2919 # value of $disabled{asm}.  Used in inherit_from values as follows:
2920 #
2921 #      inherit_from => [ "template", asm("asm_tmpl") ]
2922 #
2923 sub asm {
2924     my @x = @_;
2925     sub {
2926         $disabled{asm} ? () : @x;
2927     }
2928 }
2929
2930 # Helper function to implement conditional value variants, with a default
2931 # plus additional values based on the value of $config{build_type}.
2932 # Arguments are given in hash table form:
2933 #
2934 #       picker(default => "Basic string: ",
2935 #              debug   => "debug",
2936 #              release => "release")
2937 #
2938 # When configuring with --debug, the resulting string will be
2939 # "Basic string: debug", and when not, it will be "Basic string: release"
2940 #
2941 # This can be used to create variants of sets of flags according to the
2942 # build type:
2943 #
2944 #       cflags => picker(default => "-Wall",
2945 #                        debug   => "-g -O0",
2946 #                        release => "-O3")
2947 #
2948 sub picker {
2949     my %opts = @_;
2950     return sub { add($opts{default} || (),
2951                      $opts{$config{build_type}} || ())->(); }
2952 }
2953
2954 # Helper function to combine several values of different types into one.
2955 # This is useful if you want to combine a string with the result of a
2956 # lazy function, such as:
2957 #
2958 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2959 #
2960 sub combine {
2961     my @stuff = @_;
2962     return sub { add(@stuff)->(); }
2963 }
2964
2965 # Helper function to implement conditional values depending on the value
2966 # of $disabled{threads}.  Can be used as follows:
2967 #
2968 #       cflags => combine("-Wall", threads("-pthread"))
2969 #
2970 sub threads {
2971     my @flags = @_;
2972     return sub { add($disabled{threads} ? () : @flags)->(); }
2973 }
2974
2975 sub shared {
2976     my @flags = @_;
2977     return sub { add($disabled{shared} ? () : @flags)->(); }
2978 }
2979
2980 our $add_called = 0;
2981 # Helper function to implement adding values to already existing configuration
2982 # values.  It handles elements that are ARRAYs, CODEs and scalars
2983 sub _add {
2984     my $separator = shift;
2985
2986     # If there's any ARRAY in the collection of values OR the separator
2987     # is undef, we will return an ARRAY of combined values, otherwise a
2988     # string of joined values with $separator as the separator.
2989     my $found_array = !defined($separator);
2990
2991     my @values =
2992         map {
2993             my $res = $_;
2994             while (ref($res) eq "CODE") {
2995                 $res = $res->();
2996             }
2997             if (defined($res)) {
2998                 if (ref($res) eq "ARRAY") {
2999                     $found_array = 1;
3000                     @$res;
3001                 } else {
3002                     $res;
3003                 }
3004             } else {
3005                 ();
3006             }
3007     } (@_);
3008
3009     $add_called = 1;
3010
3011     if ($found_array) {
3012         [ @values ];
3013     } else {
3014         join($separator, grep { defined($_) && $_ ne "" } @values);
3015     }
3016 }
3017 sub add_before {
3018     my $separator = " ";
3019     if (ref($_[$#_]) eq "HASH") {
3020         my $opts = pop;
3021         $separator = $opts->{separator};
3022     }
3023     my @x = @_;
3024     sub { _add($separator, @x, @_) };
3025 }
3026 sub add {
3027     my $separator = " ";
3028     if (ref($_[$#_]) eq "HASH") {
3029         my $opts = pop;
3030         $separator = $opts->{separator};
3031     }
3032     my @x = @_;
3033     sub { _add($separator, @_, @x) };
3034 }
3035
3036 sub read_eval_file {
3037     my $fname = shift;
3038     my $content;
3039     my @result;
3040
3041     open F, "< $fname" or die "Can't open '$fname': $!\n";
3042     {
3043         undef local $/;
3044         $content = <F>;
3045     }
3046     close F;
3047     {
3048         local $@;
3049
3050         @result = ( eval $content );
3051         warn $@ if $@;
3052     }
3053     return wantarray ? @result : $result[0];
3054 }
3055
3056 # configuration reader, evaluates the input file as a perl script and expects
3057 # it to fill %targets with target configurations.  Those are then added to
3058 # %table.
3059 sub read_config {
3060     my $fname = shift;
3061     my %targets;
3062
3063     {
3064         # Protect certain tables from tampering
3065         local %table = ();
3066
3067         %targets = read_eval_file($fname);
3068     }
3069     my %preexisting = ();
3070     foreach (sort keys %targets) {
3071         $preexisting{$_} = 1 if $table{$_};
3072     }
3073     die <<"EOF",
3074 The following config targets from $fname
3075 shadow pre-existing config targets with the same name:
3076 EOF
3077         map { "  $_\n" } sort keys %preexisting
3078         if %preexisting;
3079
3080
3081     # For each target, check that it's configured with a hash table.
3082     foreach (keys %targets) {
3083         if (ref($targets{$_}) ne "HASH") {
3084             if (ref($targets{$_}) eq "") {
3085                 warn "Deprecated target configuration for $_, ignoring...\n";
3086             } else {
3087                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
3088             }
3089             delete $targets{$_};
3090         } else {
3091             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
3092         }
3093     }
3094
3095     %table = (%table, %targets);
3096
3097 }
3098
3099 # configuration resolver.  Will only resolve all the lazy evaluation
3100 # codeblocks for the chosen target and all those it inherits from,
3101 # recursively
3102 sub resolve_config {
3103     my $target = shift;
3104     my @breadcrumbs = @_;
3105
3106 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
3107
3108     if (grep { $_ eq $target } @breadcrumbs) {
3109         die "inherit_from loop!  target backtrace:\n  "
3110             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
3111     }
3112
3113     if (!defined($table{$target})) {
3114         warn "Warning! target $target doesn't exist!\n";
3115         return ();
3116     }
3117     # Recurse through all inheritances.  They will be resolved on the
3118     # fly, so when this operation is done, they will all just be a
3119     # bunch of attributes with string values.
3120     # What we get here, though, are keys with references to lists of
3121     # the combined values of them all.  We will deal with lists after
3122     # this stage is done.
3123     my %combined_inheritance = ();
3124     if ($table{$target}->{inherit_from}) {
3125         my @inherit_from =
3126             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
3127         foreach (@inherit_from) {
3128             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
3129
3130             # 'template' is a marker that's considered private to
3131             # the config that had it.
3132             delete $inherited_config{template};
3133
3134             foreach (keys %inherited_config) {
3135                 if (!$combined_inheritance{$_}) {
3136                     $combined_inheritance{$_} = [];
3137                 }
3138                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
3139             }
3140         }
3141     }
3142
3143     # We won't need inherit_from in this target any more, since we've
3144     # resolved all the inheritances that lead to this
3145     delete $table{$target}->{inherit_from};
3146
3147     # Now is the time to deal with those lists.  Here's the place to
3148     # decide what shall be done with those lists, all based on the
3149     # values of the target we're currently dealing with.
3150     # - If a value is a coderef, it will be executed with the list of
3151     #   inherited values as arguments.
3152     # - If the corresponding key doesn't have a value at all or is the
3153     #   empty string, the inherited value list will be run through the
3154     #   default combiner (below), and the result becomes this target's
3155     #   value.
3156     # - Otherwise, this target's value is assumed to be a string that
3157     #   will simply override the inherited list of values.
3158     my $default_combiner = add();
3159
3160     my %all_keys =
3161         map { $_ => 1 } (keys %combined_inheritance,
3162                          keys %{$table{$target}});
3163
3164     sub process_values {
3165         my $object    = shift;
3166         my $inherited = shift;  # Always a [ list ]
3167         my $target    = shift;
3168         my $entry     = shift;
3169
3170         $add_called = 0;
3171
3172         while(ref($object) eq "CODE") {
3173             $object = $object->(@$inherited);
3174         }
3175         if (!defined($object)) {
3176             return ();
3177         }
3178         elsif (ref($object) eq "ARRAY") {
3179             local $add_called;  # To make sure recursive calls don't affect it
3180             return [ map { process_values($_, $inherited, $target, $entry) }
3181                      @$object ];
3182         } elsif (ref($object) eq "") {
3183             return $object;
3184         } else {
3185             die "cannot handle reference type ",ref($object)
3186                 ," found in target ",$target," -> ",$entry,"\n";
3187         }
3188     }
3189
3190     foreach (sort keys %all_keys) {
3191         my $previous = $combined_inheritance{$_};
3192
3193         # Current target doesn't have a value for the current key?
3194         # Assign it the default combiner, the rest of this loop body
3195         # will handle it just like any other coderef.
3196         if (!exists $table{$target}->{$_}) {
3197             $table{$target}->{$_} = $default_combiner;
3198         }
3199
3200         $table{$target}->{$_} = process_values($table{$target}->{$_},
3201                                                $combined_inheritance{$_},
3202                                                $target, $_);
3203         unless(defined($table{$target}->{$_})) {
3204             delete $table{$target}->{$_};
3205         }
3206 #        if ($extra_checks &&
3207 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
3208 #            warn "$_ got replaced in $target\n";
3209 #        }
3210     }
3211
3212     # Finally done, return the result.
3213     return %{$table{$target}};
3214 }
3215
3216 sub usage
3217         {
3218         print STDERR $usage;
3219         print STDERR "\npick os/compiler from:\n";
3220         my $j=0;
3221         my $i;
3222         my $k=0;
3223         foreach $i (sort keys %table)
3224                 {
3225                 next if $table{$i}->{template};
3226                 next if $i =~ /^debug/;
3227                 $k += length($i) + 1;
3228                 if ($k > 78)
3229                         {
3230                         print STDERR "\n";
3231                         $k=length($i);
3232                         }
3233                 print STDERR $i . " ";
3234                 }
3235         foreach $i (sort keys %table)
3236                 {
3237                 next if $table{$i}->{template};
3238                 next if $i !~ /^debug/;
3239                 $k += length($i) + 1;
3240                 if ($k > 78)
3241                         {
3242                         print STDERR "\n";
3243                         $k=length($i);
3244                         }
3245                 print STDERR $i . " ";
3246                 }
3247         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
3248         exit(1);
3249         }
3250
3251 sub run_dofile
3252 {
3253     my $out = shift;
3254     my @templates = @_;
3255
3256     unlink $out || warn "Can't remove $out, $!"
3257         if -f $out;
3258     foreach (@templates) {
3259         die "Can't open $_, $!" unless -f $_;
3260     }
3261     my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
3262     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
3263     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
3264     system($cmd);
3265     exit 1 if $? != 0;
3266     rename("$out.new", $out) || die "Can't rename $out.new, $!";
3267 }
3268
3269 sub compiler_predefined {
3270     state %predefined;
3271     my $cc = shift;
3272
3273     return () if $^O eq 'VMS';
3274
3275     die 'compiler_predefined called without a compiler command'
3276         unless $cc;
3277
3278     if (! $predefined{$cc}) {
3279
3280         $predefined{$cc} = {};
3281
3282         # collect compiler pre-defines from gcc or gcc-alike...
3283         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3284         while (my $l = <PIPE>) {
3285             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3286             $predefined{$cc}->{$1} = $2 // '';
3287         }
3288         close(PIPE);
3289     }
3290
3291     return %{$predefined{$cc}};
3292 }
3293
3294 sub which
3295 {
3296     my ($name)=@_;
3297
3298     if (eval { require IPC::Cmd; 1; }) {
3299         IPC::Cmd->import();
3300         return scalar IPC::Cmd::can_run($name);
3301     } else {
3302         # if there is $directories component in splitpath,
3303         # then it's not something to test with $PATH...
3304         return $name if (File::Spec->splitpath($name))[1];
3305
3306         foreach (File::Spec->path()) {
3307             my $fullpath = catfile($_, "$name$target{exe_extension}");
3308             if (-f $fullpath and -x $fullpath) {
3309                 return $fullpath;
3310             }
3311         }
3312     }
3313 }
3314
3315 sub env
3316 {
3317     my $name = shift;
3318     my %opts = @_;
3319
3320     unless ($opts{cacheonly}) {
3321         # Note that if $ENV{$name} doesn't exist or is undefined,
3322         # $config{perlenv}->{$name} will be created with the value
3323         # undef.  This is intentional.
3324
3325         $config{perlenv}->{$name} = $ENV{$name}
3326             if ! exists $config{perlenv}->{$name};
3327     }
3328     return $config{perlenv}->{$name};
3329 }
3330
3331 # Configuration printer ##############################################
3332
3333 sub print_table_entry
3334 {
3335     local $now_printing = shift;
3336     my %target = resolve_config($now_printing);
3337     my $type = shift;
3338
3339     # Don't print the templates
3340     return if $target{template};
3341
3342     my @sequence = (
3343         "sys_id",
3344         "cpp",
3345         "cppflags",
3346         "defines",
3347         "includes",
3348         "cc",
3349         "cflags",
3350         "unistd",
3351         "ld",
3352         "lflags",
3353         "loutflag",
3354         "ex_libs",
3355         "bn_ops",
3356         "apps_aux_src",
3357         "cpuid_asm_src",
3358         "uplink_aux_src",
3359         "bn_asm_src",
3360         "ec_asm_src",
3361         "des_asm_src",
3362         "aes_asm_src",
3363         "bf_asm_src",
3364         "md5_asm_src",
3365         "cast_asm_src",
3366         "sha1_asm_src",
3367         "rc4_asm_src",
3368         "rmd160_asm_src",
3369         "rc5_asm_src",
3370         "wp_asm_src",
3371         "cmll_asm_src",
3372         "modes_asm_src",
3373         "padlock_asm_src",
3374         "chacha_asm_src",
3375         "poly1035_asm_src",
3376         "thread_scheme",
3377         "perlasm_scheme",
3378         "dso_scheme",
3379         "shared_target",
3380         "shared_cflag",
3381         "shared_defines",
3382         "shared_ldflag",
3383         "shared_rcflag",
3384         "shared_extension",
3385         "dso_extension",
3386         "obj_extension",
3387         "exe_extension",
3388         "ranlib",
3389         "ar",
3390         "arflags",
3391         "aroutflag",
3392         "rc",
3393         "rcflags",
3394         "rcoutflag",
3395         "mt",
3396         "mtflags",
3397         "mtinflag",
3398         "mtoutflag",
3399         "multilib",
3400         "build_scheme",
3401         );
3402
3403     if ($type eq "TABLE") {
3404         print "\n";
3405         print "*** $now_printing\n";
3406         foreach (@sequence) {
3407             if (ref($target{$_}) eq "ARRAY") {
3408                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
3409             } else {
3410                 printf "\$%-12s = %s\n", $_, $target{$_};
3411             }
3412         }
3413     } elsif ($type eq "HASH") {
3414         my $largest =
3415             length((sort { length($a) <=> length($b) } @sequence)[-1]);
3416         print "    '$now_printing' => {\n";
3417         foreach (@sequence) {
3418             if ($target{$_}) {
3419                 if (ref($target{$_}) eq "ARRAY") {
3420                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
3421                 } else {
3422                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
3423                 }
3424             }
3425         }
3426         print "    },\n";
3427     }
3428 }
3429
3430 # Utility routines ###################################################
3431
3432 # On VMS, if the given file is a logical name, File::Spec::Functions
3433 # will consider it an absolute path.  There are cases when we want a
3434 # purely syntactic check without checking the environment.
3435 sub isabsolute {
3436     my $file = shift;
3437
3438     # On non-platforms, we just use file_name_is_absolute().
3439     return file_name_is_absolute($file) unless $^O eq "VMS";
3440
3441     # If the file spec includes a device or a directory spec,
3442     # file_name_is_absolute() is perfectly safe.
3443     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
3444
3445     # Here, we know the given file spec isn't absolute
3446     return 0;
3447 }
3448
3449 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
3450 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
3451 # realpath() requires that at least all path components except the last is an
3452 # existing directory.  On VMS, the last component of the directory spec must
3453 # exist.
3454 sub absolutedir {
3455     my $dir = shift;
3456
3457     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
3458     # will return the volume name for the device, no matter what.  Also,
3459     # it will return an incorrect directory spec if the argument is a
3460     # directory that doesn't exist.
3461     if ($^O eq "VMS") {
3462         return rel2abs($dir);
3463     }
3464
3465     # We use realpath() on Unix, since no other will properly clean out
3466     # a directory spec.
3467     use Cwd qw/realpath/;
3468
3469     return realpath($dir);
3470 }
3471
3472 # Check if all paths are one and the same, using stat.  They must both exist
3473 # We need this for the cases when File::Spec doesn't detect case insensitivity
3474 # (File::Spec::Unix assumes case sensitivity)
3475 sub samedir {
3476     die "samedir expects two arguments\n" unless scalar @_ == 2;
3477
3478     my @stat0 = stat($_[0]);    # First argument
3479     my @stat1 = stat($_[1]);    # Second argument
3480
3481     die "Couldn't stat $_[0]" unless @stat0;
3482     die "Couldn't stat $_[1]" unless @stat1;
3483
3484     # Compare device number
3485     return 0 unless ($stat0[0] == $stat1[0]);
3486     # Compare "inode".  The perl manual recommends comparing as
3487     # string rather than as number.
3488     return 0 unless ($stat0[1] eq $stat1[1]);
3489
3490     return 1;                   # All the same
3491 }
3492
3493 sub quotify {
3494     my %processors = (
3495         perl    => sub { my $x = shift;
3496                          $x =~ s/([\\\$\@"])/\\$1/g;
3497                          return '"'.$x.'"'; },
3498         maybeshell => sub { my $x = shift;
3499                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
3500                             if ($x ne $y || $x =~ m|\s|) {
3501                                 return '"'.$y.'"';
3502                             } else {
3503                                 return $x;
3504                             }
3505                         },
3506         );
3507     my $for = shift;
3508     my $processor =
3509         defined($processors{$for}) ? $processors{$for} : sub { shift; };
3510
3511     return map { $processor->($_); } @_;
3512 }
3513
3514 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
3515 # $filename is a file name to read from
3516 # $line_concat_cond_re is a regexp detecting a line continuation ending
3517 # $line_concat is a CODEref that takes care of concatenating two lines
3518 sub collect_from_file {
3519     my $filename = shift;
3520     my $line_concat_cond_re = shift;
3521     my $line_concat = shift;
3522
3523     open my $fh, $filename || die "unable to read $filename: $!\n";
3524     return sub {
3525         my $saved_line = "";
3526         $_ = "";
3527         while (<$fh>) {
3528             s|\R$||;
3529             if (defined $line_concat) {
3530                 $_ = $line_concat->($saved_line, $_);
3531                 $saved_line = "";
3532             }
3533             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3534                 $saved_line = $_;
3535                 next;
3536             }
3537             return $_;
3538         }
3539         die "$filename ending with continuation line\n" if $_;
3540         close $fh;
3541         return undef;
3542     }
3543 }
3544
3545 # collect_from_array($array, $line_concat_cond_re, $line_concat)
3546 # $array is an ARRAYref of lines
3547 # $line_concat_cond_re is a regexp detecting a line continuation ending
3548 # $line_concat is a CODEref that takes care of concatenating two lines
3549 sub collect_from_array {
3550     my $array = shift;
3551     my $line_concat_cond_re = shift;
3552     my $line_concat = shift;
3553     my @array = (@$array);
3554
3555     return sub {
3556         my $saved_line = "";
3557         $_ = "";
3558         while (defined($_ = shift @array)) {
3559             s|\R$||;
3560             if (defined $line_concat) {
3561                 $_ = $line_concat->($saved_line, $_);
3562                 $saved_line = "";
3563             }
3564             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3565                 $saved_line = $_;
3566                 next;
3567             }
3568             return $_;
3569         }
3570         die "input text ending with continuation line\n" if $_;
3571         return undef;
3572     }
3573 }
3574
3575 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
3576 # $lineiterator is a CODEref that delivers one line at a time.
3577 # All following arguments are regex/CODEref pairs, where the regexp detects a
3578 # line and the CODEref does something with the result of the regexp.
3579 sub collect_information {
3580     my $lineiterator = shift;
3581     my %collectors = @_;
3582
3583     while(defined($_ = $lineiterator->())) {
3584         s|\R$||;
3585         my $found = 0;
3586         if ($collectors{"BEFORE"}) {
3587             $collectors{"BEFORE"}->($_);
3588         }
3589         foreach my $re (keys %collectors) {
3590             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
3591                 $collectors{$re}->($lineiterator);
3592                 $found = 1;
3593             };
3594         }
3595         if ($collectors{"OTHERWISE"}) {
3596             $collectors{"OTHERWISE"}->($lineiterator, $_)
3597                 unless $found || !defined $collectors{"OTHERWISE"};
3598         }
3599         if ($collectors{"AFTER"}) {
3600             $collectors{"AFTER"}->($_);
3601         }
3602     }
3603 }
3604
3605 # tokenize($line)
3606 # $line is a line of text to split up into tokens
3607 # returns a list of tokens
3608 #
3609 # Tokens are divided by spaces.  If the tokens include spaces, they
3610 # have to be quoted with single or double quotes.  Double quotes
3611 # inside a double quoted token must be escaped.  Escaping is done
3612 # with backslash.
3613 # Basically, the same quoting rules apply for " and ' as in any
3614 # Unix shell.
3615 sub tokenize {
3616     my $line = my $debug_line = shift;
3617     my @result = ();
3618
3619     while ($line =~ s|^\s+||, $line ne "") {
3620         my $token = "";
3621         while ($line ne "" && $line !~ m|^\s|) {
3622             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
3623                 $token .= $1;
3624                 $line = $';
3625             } elsif ($line =~ m/^'([^']*)'/) {
3626                 $token .= $1;
3627                 $line = $';
3628             } elsif ($line =~ m/^(\S+)/) {
3629                 $token .= $1;
3630                 $line = $';
3631             }
3632         }
3633         push @result, $token;
3634     }
3635
3636     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3637         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
3638         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
3639     }
3640     return @result;
3641 }