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