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