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