Avoid duplicate default CApath lookups
[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} || ! -f $generator[0]) {
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;
2334
2335             if ($dest =~ /^\|(.*)\|$/) {
2336                 # Collect the raw target
2337                 $unified_info{targets}->{$1} = 1;
2338                 $ddest = $1;
2339             } elsif ($dest eq '') {
2340                 $ddest = '';
2341             } else {
2342                 $ddest = cleanfile($sourced, $_, $blddir);
2343
2344                 # If the destination doesn't exist in source, it can only be
2345                 # a generated file in the build tree.
2346                 if ($ddest eq $src_configdata || ! -f $ddest) {
2347                     $ddest = cleanfile($buildd, $_, $blddir);
2348                 }
2349             }
2350             foreach (@{$depends{$dest}}) {
2351                 my $d = cleanfile($sourced, $_, $blddir);
2352
2353                 # If we know it's generated, or assume it is because we can't
2354                 # find it in the source tree, we set file we depend on to be
2355                 # in the build tree rather than the source tree.
2356                 if ($d eq $src_configdata
2357                     || (grep { $d eq $_ }
2358                         map { cleanfile($srcdir, $_, $blddir) }
2359                         grep { /\.h$/ } keys %{$unified_info{generate}})
2360                     || ! -f $d) {
2361                     $d = cleanfile($buildd, $_, $blddir);
2362                 }
2363                 $unified_info{depends}->{$ddest}->{$d} = 1;
2364
2365                 # Fix up associated attributes
2366                 $unified_info{attributes}->{depends}->{$ddest}->{$d} =
2367                     $attributes{depends}->{$dest}->{$_}
2368                     if defined $attributes{depends}->{$dest}->{$_};
2369             }
2370         }
2371
2372         foreach (keys %includes) {
2373             my $dest = $_;
2374             my $ddest = cleanfile($sourced, $_, $blddir);
2375
2376             # If the destination doesn't exist in source, it can only be
2377             # a generated file in the build tree.
2378             if ($ddest eq $src_configdata || ! -f $ddest) {
2379                 $ddest = cleanfile($buildd, $_, $blddir);
2380             }
2381             foreach (@{$includes{$dest}}) {
2382                 my $is = cleandir($sourced, $_, $blddir);
2383                 my $ib = cleandir($buildd, $_, $blddir);
2384                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
2385                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
2386                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
2387                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
2388             }
2389         }
2390
2391         foreach my $dest (keys %defines) {
2392             my $ddest;
2393
2394             if ($dest ne "") {
2395                 $ddest = cleanfile($sourced, $dest, $blddir);
2396
2397                 # If the destination doesn't exist in source, it can only
2398                 # be a generated file in the build tree.
2399                 if (! -f $ddest) {
2400                     $ddest = cleanfile($buildd, $dest, $blddir);
2401                 }
2402             }
2403             foreach my $v (@{$defines{$dest}}) {
2404                 $v =~ m|^([^=]*)(=.*)?$|;
2405                 die "0 length macro name not permitted\n" if $1 eq "";
2406                 if ($dest ne "") {
2407                     die "$1 defined more than once\n"
2408                         if defined $unified_info{defines}->{$ddest}->{$1};
2409                     $unified_info{defines}->{$ddest}->{$1} = $2;
2410                 } else {
2411                     die "$1 defined more than once\n"
2412                         if grep { $v eq $_ } @{$config{defines}};
2413                     push @{$config{defines}}, $v;
2414                 }
2415             }
2416         }
2417
2418         foreach my $section (keys %htmldocs) {
2419             foreach (@{$htmldocs{$section}}) {
2420                 my $htmldocs = cleanfile($buildd, $_, $blddir);
2421                 $unified_info{htmldocs}->{$section}->{$htmldocs} = 1;
2422             }
2423         }
2424
2425         foreach my $section (keys %mandocs) {
2426             foreach (@{$mandocs{$section}}) {
2427                 my $mandocs = cleanfile($buildd, $_, $blddir);
2428                 $unified_info{mandocs}->{$section}->{$mandocs} = 1;
2429             }
2430         }
2431     }
2432
2433     my $ordinals_text = join(', ', sort keys %ordinals);
2434     warn <<"EOF" if $ordinals_text;
2435
2436 WARNING: ORDINALS were specified for $ordinals_text
2437 They are ignored and should be replaced with a combination of GENERATE,
2438 DEPEND and SHARED_SOURCE.
2439 EOF
2440
2441     # Check that each generated file is only generated once
2442     my $ambiguous_generation = 0;
2443     foreach (sort keys %check_generate) {
2444         my @generators = sort keys %{$check_generate{$_}};
2445         my $generators_txt = join(', ', @generators);
2446         if (scalar @generators > 1) {
2447             warn "$_ is GENERATEd by more than one generator ($generators_txt)\n";
2448             $ambiguous_generation++;
2449         }
2450         if ($check_generate{$_}->{$generators[0]} > 1) {
2451             warn "INFO: $_ has more than one GENERATE declaration (same generator)\n"
2452         }
2453     }
2454     die "There are ambiguous source file generations\n"
2455         if $ambiguous_generation > 0;
2456
2457     # All given source files should exist, or if generated, their
2458     # generator should exist.  This loop ensures this is true.
2459     my $missing = 0;
2460     foreach my $orig (sort keys %check_exist) {
2461         foreach my $dest (@{$check_exist{$orig}}) {
2462             if ($orig ne $src_configdata) {
2463                 if ($orig =~ /\.a$/) {
2464                     # Static library names may be used as sources, so we
2465                     # need to detect those and give them special treatment.
2466                     unless (grep { $_ eq $orig }
2467                             keys %{$unified_info{libraries}}) {
2468                         warn "$orig is given as source for $dest, but no such library is built\n";
2469                         $missing++;
2470                     }
2471                 } else {
2472                     # A source may be generated, and its generator may be
2473                     # generated as well.  We therefore loop to dig out the
2474                     # first generator.
2475                     my $gen = $orig;
2476
2477                     while (my @next = keys %{$check_generate{$gen}}) {
2478                         $gen = $next[0];
2479                     }
2480
2481                     if (! -f $gen) {
2482                         if ($gen ne $orig) {
2483                             $missing++;
2484                             warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n";
2485                         } else {
2486                             $missing++;
2487                             warn "$orig is given as source for $dest, but is missing\n";
2488                         }
2489                     }
2490                 }
2491             }
2492         }
2493     }
2494     die "There are files missing\n" if $missing > 0;
2495
2496     # Go through the sources of all libraries and check that the same basename
2497     # doesn't appear more than once.  Some static library archivers depend on
2498     # them being unique.
2499     {
2500         my $err = 0;
2501         foreach my $prod (keys %{$unified_info{libraries}}) {
2502             my @prod_sources =
2503                 map { keys %{$unified_info{sources}->{$_}} }
2504                 keys %{$unified_info{sources}->{$prod}};
2505             my %srccnt = ();
2506
2507             # Count how many times a given each source basename
2508             # appears for each product.
2509             foreach my $src (@prod_sources) {
2510                 $srccnt{basename $src}++;
2511             }
2512
2513             foreach my $src (keys %srccnt) {
2514                 if ((my $cnt = $srccnt{$src}) > 1) {
2515                     print STDERR "$src appears $cnt times for the product $prod\n";
2516                     $err++
2517                 }
2518             }
2519         }
2520         die if $err > 0;
2521     }
2522
2523     # Massage the result
2524
2525     # If we depend on a header file or a perl module, add an inclusion of
2526     # its directory to allow smoothe inclusion
2527     foreach my $dest (keys %{$unified_info{depends}}) {
2528         next if $dest eq "";
2529         foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
2530             next unless $d =~ /\.(h|pm)$/;
2531             my $i = dirname($d);
2532             my $spot =
2533                 $d eq "configdata.pm" || defined($unified_info{generate}->{$d})
2534                 ? 'build' : 'source';
2535             push @{$unified_info{includes}->{$dest}->{$spot}}, $i
2536                 unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
2537         }
2538     }
2539
2540     # Go through all intermediary files and change their names to something that
2541     # reflects what they will be built for.  Note that for some source files,
2542     # this leads to duplicate object files because they are used multiple times.
2543     # the goal is to rename all object files according to this scheme:
2544     #    {productname}-{midfix}-{origobjname}.[o|res]
2545     # the {midfix} is a keyword indicating the type of product, which is mostly
2546     # valuable for libraries since they come in two forms.
2547     #
2548     # This also reorganises the {sources} and {shared_sources} so that the
2549     # former only contains ALL object files that are supposed to end up in
2550     # static libraries and programs, while the latter contains ALL object files
2551     # that are supposed to end up in shared libraries and DSOs.
2552     # The main reason for having two different source structures is to allow
2553     # the same name to be used for the static and the shared variants of a
2554     # library.
2555     {
2556         # Take copies so we don't get interference from added stuff
2557         my %unified_copy = ();
2558         foreach (('sources', 'shared_sources')) {
2559             $unified_copy{$_} = { %{$unified_info{$_}} }
2560                 if defined($unified_info{$_});
2561             delete $unified_info{$_};
2562         }
2563         foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) {
2564             # $intent serves multi purposes:
2565             # - give a prefix for the new object files names
2566             # - in the case of libraries, rearrange the object files so static
2567             #   libraries use the 'sources' structure exclusively, while shared
2568             #   libraries use the 'shared_sources' structure exclusively.
2569             my $intent = {
2570                 programs  => { bin    => { src => [ 'sources' ],
2571                                            dst => 'sources' } },
2572                 libraries => { lib    => { src => [ 'sources' ],
2573                                            dst => 'sources' },
2574                                shlib  => { prodselect =>
2575                                                sub { grep !/\.a$/, @_ },
2576                                            src => [ 'sources',
2577                                                     'shared_sources' ],
2578                                            dst => 'shared_sources' } },
2579                 modules   => { dso    => { src => [ 'sources' ],
2580                                            dst => 'sources' } },
2581                 scripts   => { script => { src => [ 'sources' ],
2582                                            dst => 'sources' } }
2583                } -> {$prodtype};
2584             foreach my $kind (keys %$intent) {
2585                 next if ($intent->{$kind}->{dst} eq 'shared_sources'
2586                              && $disabled{shared});
2587
2588                 my @src = @{$intent->{$kind}->{src}};
2589                 my $dst = $intent->{$kind}->{dst};
2590                 my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ };
2591                 foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) {
2592                     # %prod_sources has all applicable objects as keys, and
2593                     # their corresponding sources as values
2594                     my %prod_sources =
2595                         map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] }
2596                         map { keys %{$unified_copy{$_}->{$prod}} }
2597                         @src;
2598                     foreach (keys %prod_sources) {
2599                         # Only affect object files and resource files,
2600                         # the others simply get a new value
2601                         # (+1 instead of -1)
2602                         if ($_ =~ /\.(o|res)$/) {
2603                             (my $prodname = $prod) =~ s|\.a$||;
2604                             my $newobj =
2605                                 catfile(dirname($_),
2606                                         basename($prodname)
2607                                             . '-' . $kind
2608                                             . '-' . basename($_));
2609                             $unified_info{$dst}->{$prod}->{$newobj} = 1;
2610                             foreach my $src (@{$prod_sources{$_}}) {
2611                                 $unified_info{sources}->{$newobj}->{$src} = 1;
2612                             }
2613                             # Adjust dependencies
2614                             foreach my $deps (keys %{$unified_info{depends}->{$_}}) {
2615                                 $unified_info{depends}->{$_}->{$deps} = -1;
2616                                 $unified_info{depends}->{$newobj}->{$deps} = 1;
2617                             }
2618                             # Adjust includes
2619                             foreach my $k (('source', 'build')) {
2620                                 next unless
2621                                     defined($unified_info{includes}->{$_}->{$k});
2622                                 my @incs = @{$unified_info{includes}->{$_}->{$k}};
2623                                 $unified_info{includes}->{$newobj}->{$k} = [ @incs ];
2624                             }
2625                         } else {
2626                             $unified_info{$dst}->{$prod}->{$_} = 1;
2627                         }
2628                     }
2629                 }
2630             }
2631         }
2632     }
2633
2634     # At this point, we have a number of sources with the value -1.  They
2635     # aren't part of the local build and are probably meant for a different
2636     # platform, and can therefore be cleaned away.  That happens when making
2637     # %unified_info more efficient below.
2638
2639     ### Make unified_info a bit more efficient
2640     # One level structures
2641     foreach (("programs", "libraries", "modules", "scripts", "targets")) {
2642         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
2643     }
2644     # Two level structures
2645     foreach my $l1 (("sources", "shared_sources", "ldadd", "depends",
2646                      "htmldocs", "mandocs")) {
2647         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
2648             my @items =
2649                 sort
2650                 grep { $unified_info{$l1}->{$l2}->{$_} > 0 }
2651                 keys %{$unified_info{$l1}->{$l2}};
2652             if (@items) {
2653                 $unified_info{$l1}->{$l2} = [ @items ];
2654             } else {
2655                 delete $unified_info{$l1}->{$l2};
2656             }
2657         }
2658     }
2659     # Defines
2660     foreach my $dest (sort keys %{$unified_info{defines}}) {
2661         $unified_info{defines}->{$dest}
2662             = [ map { $_.$unified_info{defines}->{$dest}->{$_} }
2663                 sort keys %{$unified_info{defines}->{$dest}} ];
2664     }
2665     # Includes
2666     foreach my $dest (sort keys %{$unified_info{includes}}) {
2667         if (defined($unified_info{includes}->{$dest}->{build})) {
2668             my @source_includes = ();
2669             @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
2670                 if defined($unified_info{includes}->{$dest}->{source});
2671             $unified_info{includes}->{$dest} =
2672                 [ @{$unified_info{includes}->{$dest}->{build}} ];
2673             foreach my $inc (@source_includes) {
2674                 push @{$unified_info{includes}->{$dest}}, $inc
2675                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
2676             }
2677         } elsif (defined($unified_info{includes}->{$dest}->{source})) {
2678             $unified_info{includes}->{$dest} =
2679                 [ @{$unified_info{includes}->{$dest}->{source}} ];
2680         } else {
2681             delete $unified_info{includes}->{$dest};
2682         }
2683     }
2684
2685     # For convenience collect information regarding directories where
2686     # files are generated, those generated files and the end product
2687     # they end up in where applicable.  Then, add build rules for those
2688     # directories
2689     my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
2690                      "dso" => [ @{$unified_info{modules}} ],
2691                      "bin" => [ @{$unified_info{programs}} ],
2692                      "script" => [ @{$unified_info{scripts}} ],
2693                      "docs" => [ (map { @{$unified_info{htmldocs}->{$_} // []} }
2694                                   keys %{$unified_info{htmldocs} // {}}),
2695                                  (map { @{$unified_info{mandocs}->{$_} // []} }
2696                                   keys %{$unified_info{mandocs} // {}}) ] );
2697     foreach my $type (keys %loopinfo) {
2698         foreach my $product (@{$loopinfo{$type}}) {
2699             my %dirs = ();
2700             my $pd = dirname($product);
2701
2702             foreach (@{$unified_info{sources}->{$product} // []},
2703                      @{$unified_info{shared_sources}->{$product} // []}) {
2704                 my $d = dirname($_);
2705
2706                 # We don't want to create targets for source directories
2707                 # when building out of source
2708                 next if ($config{sourcedir} ne $config{builddir}
2709                              && $d =~ m|^\Q$config{sourcedir}\E|);
2710                 # We already have a "test" target, and the current directory
2711                 # is just silly to make a target for
2712                 next if $d eq "test" || $d eq ".";
2713
2714                 $dirs{$d} = 1;
2715                 push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
2716                     if $d ne $pd;
2717             }
2718             foreach (keys %dirs) {
2719                 push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
2720                     $product;
2721             }
2722         }
2723     }
2724 }
2725
2726 # For the schemes that need it, we provide the old *_obj configs
2727 # from the *_asm_obj ones
2728 foreach (grep /_(asm|aux)_src$/, keys %target) {
2729     my $src = $_;
2730     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
2731     $target{$obj} = $target{$src};
2732     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
2733     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
2734 }
2735
2736 # Write down our configuration where it fits #########################
2737
2738 my %template_vars = (
2739     config => \%config,
2740     target => \%target,
2741     disablables => \@disablables,
2742     disablables_int => \@disablables_int,
2743     disabled => \%disabled,
2744     withargs => \%withargs,
2745     unified_info => \%unified_info,
2746     tls => \@tls,
2747     dtls => \@dtls,
2748     makevars => [ sort keys %user ],
2749     disabled_info => \%disabled_info,
2750     user_crossable => \@user_crossable,
2751 );
2752 my $configdata_outname = 'configdata.pm';
2753 print "Creating $configdata_outname\n";
2754 open CONFIGDATA, ">$configdata_outname.new"
2755             or die "Trying to create $configdata_outname.new: $!";
2756 my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir);
2757 my $configdata_tmpl =
2758     OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname);
2759 $configdata_tmpl->fill_in(
2760     FILENAME => $configdata_tmplname,
2761     OUTPUT => \*CONFIGDATA,
2762     HASH => { %template_vars,
2763               autowarntext => [
2764                   'WARNING: do not edit!',
2765                   "Generated by Configure from $configdata_tmplname",
2766               ] }
2767 ) or die $Text::Template::ERROR;
2768 close CONFIGDATA;
2769 rename "$configdata_outname.new", $configdata_outname;
2770 if ($builder_platform eq 'unix') {
2771     my $mode = (0755 & ~umask);
2772     chmod $mode, 'configdata.pm'
2773         or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
2774 }
2775
2776 print "Running $configdata_outname\n";
2777 my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
2778 my $cmd = "$perlcmd $configdata_outname";
2779 #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
2780 system($cmd);
2781 exit 1 if $? != 0;
2782
2783 $SIG{__DIE__} = $orig_death_handler;
2784
2785 print <<"EOF" if ($disabled{threads} eq "unavailable");
2786
2787 The library could not be configured for supporting multi-threaded
2788 applications as the compiler options required on this system are not known.
2789 See file INSTALL.md for details if you need multi-threading.
2790 EOF
2791
2792 print <<"EOF" if ($no_shared_warn);
2793
2794 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2795 platform, so we will pretend you gave the option 'no-pic', which also disables
2796 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2797 or position independent code, please let us know (but please first make sure
2798 you have tried with a current version of OpenSSL).
2799 EOF
2800
2801 print <<"EOF";
2802
2803 **********************************************************************
2804 ***                                                                ***
2805 ***   OpenSSL has been successfully configured                     ***
2806 ***                                                                ***
2807 ***   If you encounter a problem while building, please open an    ***
2808 ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
2809 ***   and include the output from the following command:           ***
2810 ***                                                                ***
2811 ***       perl configdata.pm --dump                                ***
2812 ***                                                                ***
2813 ***   (If you are new to OpenSSL, you might want to consult the    ***
2814 ***   'Troubleshooting' section in the INSTALL.md file first)      ***
2815 ***                                                                ***
2816 **********************************************************************
2817 EOF
2818
2819 exit(0);
2820
2821 ######################################################################
2822 #
2823 # Helpers and utility functions
2824 #
2825
2826 # Death handler, to print a helpful message in case of failure #######
2827 #
2828 sub death_handler {
2829     die @_ if $^S;              # To prevent the added message in eval blocks
2830     my $build_file = $target{build_file} // "build file";
2831     my @message = ( <<"_____", @_ );
2832
2833 Failure!  $build_file wasn't produced.
2834 Please read INSTALL.md and associated NOTES-* files.  You may also have to
2835 look over your available compiler tool chain or change your configuration.
2836
2837 _____
2838
2839     # Dying is terminal, so it's ok to reset the signal handler here.
2840     $SIG{__DIE__} = $orig_death_handler;
2841     die @message;
2842 }
2843
2844 # Configuration file reading #########################################
2845
2846 # Note: All of the helper functions are for lazy evaluation.  They all
2847 # return a CODE ref, which will return the intended value when evaluated.
2848 # Thus, whenever there's mention of a returned value, it's about that
2849 # intended value.
2850
2851 # Helper function to implement conditional value variants, with a default
2852 # plus additional values based on the value of $config{build_type}.
2853 # Arguments are given in hash table form:
2854 #
2855 #       picker(default => "Basic string: ",
2856 #              debug   => "debug",
2857 #              release => "release")
2858 #
2859 # When configuring with --debug, the resulting string will be
2860 # "Basic string: debug", and when not, it will be "Basic string: release"
2861 #
2862 # This can be used to create variants of sets of flags according to the
2863 # build type:
2864 #
2865 #       cflags => picker(default => "-Wall",
2866 #                        debug   => "-g -O0",
2867 #                        release => "-O3")
2868 #
2869 sub picker {
2870     my %opts = @_;
2871     return sub { add($opts{default} || (),
2872                      $opts{$config{build_type}} || ())->(); }
2873 }
2874
2875 # Helper function to combine several values of different types into one.
2876 # This is useful if you want to combine a string with the result of a
2877 # lazy function, such as:
2878 #
2879 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2880 #
2881 sub combine {
2882     my @stuff = @_;
2883     return sub { add(@stuff)->(); }
2884 }
2885
2886 # Helper function to implement conditional values depending on the value
2887 # of $disabled{threads}.  Can be used as follows:
2888 #
2889 #       cflags => combine("-Wall", threads("-pthread"))
2890 #
2891 sub threads {
2892     my @flags = @_;
2893     return sub { add($disabled{threads} ? () : @flags)->(); }
2894 }
2895
2896 sub shared {
2897     my @flags = @_;
2898     return sub { add($disabled{shared} ? () : @flags)->(); }
2899 }
2900
2901 our $add_called = 0;
2902 # Helper function to implement adding values to already existing configuration
2903 # values.  It handles elements that are ARRAYs, CODEs and scalars
2904 sub _add {
2905     my $separator = shift;
2906
2907     # If there's any ARRAY in the collection of values OR the separator
2908     # is undef, we will return an ARRAY of combined values, otherwise a
2909     # string of joined values with $separator as the separator.
2910     my $found_array = !defined($separator);
2911
2912     my @values =
2913         map {
2914             my $res = $_;
2915             while (ref($res) eq "CODE") {
2916                 $res = $res->();
2917             }
2918             if (defined($res)) {
2919                 if (ref($res) eq "ARRAY") {
2920                     $found_array = 1;
2921                     @$res;
2922                 } else {
2923                     $res;
2924                 }
2925             } else {
2926                 ();
2927             }
2928     } (@_);
2929
2930     $add_called = 1;
2931
2932     if ($found_array) {
2933         [ @values ];
2934     } else {
2935         join($separator, grep { defined($_) && $_ ne "" } @values);
2936     }
2937 }
2938 sub add_before {
2939     my $separator = " ";
2940     if (ref($_[$#_]) eq "HASH") {
2941         my $opts = pop;
2942         $separator = $opts->{separator};
2943     }
2944     my @x = @_;
2945     sub { _add($separator, @x, @_) };
2946 }
2947 sub add {
2948     my $separator = " ";
2949     if (ref($_[$#_]) eq "HASH") {
2950         my $opts = pop;
2951         $separator = $opts->{separator};
2952     }
2953     my @x = @_;
2954     sub { _add($separator, @_, @x) };
2955 }
2956
2957 sub read_eval_file {
2958     my $fname = shift;
2959     my $content;
2960     my @result;
2961
2962     open F, "< $fname" or die "Can't open '$fname': $!\n";
2963     {
2964         undef local $/;
2965         $content = <F>;
2966     }
2967     close F;
2968     {
2969         local $@;
2970
2971         @result = ( eval $content );
2972         warn $@ if $@;
2973     }
2974     return wantarray ? @result : $result[0];
2975 }
2976
2977 # configuration reader, evaluates the input file as a perl script and expects
2978 # it to fill %targets with target configurations.  Those are then added to
2979 # %table.
2980 sub read_config {
2981     my $fname = shift;
2982     my %targets;
2983
2984     {
2985         # Protect certain tables from tampering
2986         local %table = ();
2987
2988         %targets = read_eval_file($fname);
2989     }
2990     my %preexisting = ();
2991     foreach (sort keys %targets) {
2992         $preexisting{$_} = 1 if $table{$_};
2993     }
2994     die <<"EOF",
2995 The following config targets from $fname
2996 shadow pre-existing config targets with the same name:
2997 EOF
2998         map { "  $_\n" } sort keys %preexisting
2999         if %preexisting;
3000
3001
3002     # For each target, check that it's configured with a hash table.
3003     foreach (keys %targets) {
3004         if (ref($targets{$_}) ne "HASH") {
3005             if (ref($targets{$_}) eq "") {
3006                 warn "Deprecated target configuration for $_, ignoring...\n";
3007             } else {
3008                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
3009             }
3010             delete $targets{$_};
3011         } else {
3012             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
3013         }
3014     }
3015
3016     %table = (%table, %targets);
3017
3018 }
3019
3020 # configuration resolver.  Will only resolve all the lazy evaluation
3021 # codeblocks for the chosen target and all those it inherits from,
3022 # recursively
3023 sub resolve_config {
3024     my $target = shift;
3025     my @breadcrumbs = @_;
3026
3027 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
3028
3029     if (grep { $_ eq $target } @breadcrumbs) {
3030         die "inherit_from loop!  target backtrace:\n  "
3031             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
3032     }
3033
3034     if (!defined($table{$target})) {
3035         warn "Warning! target $target doesn't exist!\n";
3036         return ();
3037     }
3038     # Recurse through all inheritances.  They will be resolved on the
3039     # fly, so when this operation is done, they will all just be a
3040     # bunch of attributes with string values.
3041     # What we get here, though, are keys with references to lists of
3042     # the combined values of them all.  We will deal with lists after
3043     # this stage is done.
3044     my %combined_inheritance = ();
3045     if ($table{$target}->{inherit_from}) {
3046         my @inherit_from =
3047             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
3048         foreach (@inherit_from) {
3049             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
3050
3051             # 'template' is a marker that's considered private to
3052             # the config that had it.
3053             delete $inherited_config{template};
3054
3055             foreach (keys %inherited_config) {
3056                 if (!$combined_inheritance{$_}) {
3057                     $combined_inheritance{$_} = [];
3058                 }
3059                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
3060             }
3061         }
3062     }
3063
3064     # We won't need inherit_from in this target any more, since we've
3065     # resolved all the inheritances that lead to this
3066     delete $table{$target}->{inherit_from};
3067
3068     # Now is the time to deal with those lists.  Here's the place to
3069     # decide what shall be done with those lists, all based on the
3070     # values of the target we're currently dealing with.
3071     # - If a value is a coderef, it will be executed with the list of
3072     #   inherited values as arguments.
3073     # - If the corresponding key doesn't have a value at all or is the
3074     #   empty string, the inherited value list will be run through the
3075     #   default combiner (below), and the result becomes this target's
3076     #   value.
3077     # - Otherwise, this target's value is assumed to be a string that
3078     #   will simply override the inherited list of values.
3079     my $default_combiner = add();
3080
3081     my %all_keys =
3082         map { $_ => 1 } (keys %combined_inheritance,
3083                          keys %{$table{$target}});
3084
3085     sub process_values {
3086         my $object    = shift;
3087         my $inherited = shift;  # Always a [ list ]
3088         my $target    = shift;
3089         my $entry     = shift;
3090
3091         $add_called = 0;
3092
3093         while(ref($object) eq "CODE") {
3094             $object = $object->(@$inherited);
3095         }
3096         if (!defined($object)) {
3097             return ();
3098         }
3099         elsif (ref($object) eq "ARRAY") {
3100             local $add_called;  # To make sure recursive calls don't affect it
3101             return [ map { process_values($_, $inherited, $target, $entry) }
3102                      @$object ];
3103         } elsif (ref($object) eq "") {
3104             return $object;
3105         } else {
3106             die "cannot handle reference type ",ref($object)
3107                 ," found in target ",$target," -> ",$entry,"\n";
3108         }
3109     }
3110
3111     foreach (sort keys %all_keys) {
3112         my $previous = $combined_inheritance{$_};
3113
3114         # Current target doesn't have a value for the current key?
3115         # Assign it the default combiner, the rest of this loop body
3116         # will handle it just like any other coderef.
3117         if (!exists $table{$target}->{$_}) {
3118             $table{$target}->{$_} = $default_combiner;
3119         }
3120
3121         $table{$target}->{$_} = process_values($table{$target}->{$_},
3122                                                $combined_inheritance{$_},
3123                                                $target, $_);
3124         unless(defined($table{$target}->{$_})) {
3125             delete $table{$target}->{$_};
3126         }
3127 #        if ($extra_checks &&
3128 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
3129 #            warn "$_ got replaced in $target\n";
3130 #        }
3131     }
3132
3133     # Finally done, return the result.
3134     return %{$table{$target}};
3135 }
3136
3137 sub usage
3138         {
3139         print STDERR $usage;
3140         print STDERR "\npick os/compiler from:\n";
3141         my $j=0;
3142         my $i;
3143         my $k=0;
3144         foreach $i (sort keys %table)
3145                 {
3146                 next if $table{$i}->{template};
3147                 next if $i =~ /^debug/;
3148                 $k += length($i) + 1;
3149                 if ($k > 78)
3150                         {
3151                         print STDERR "\n";
3152                         $k=length($i);
3153                         }
3154                 print STDERR $i . " ";
3155                 }
3156         foreach $i (sort keys %table)
3157                 {
3158                 next if $table{$i}->{template};
3159                 next if $i !~ /^debug/;
3160                 $k += length($i) + 1;
3161                 if ($k > 78)
3162                         {
3163                         print STDERR "\n";
3164                         $k=length($i);
3165                         }
3166                 print STDERR $i . " ";
3167                 }
3168         exit(1);
3169         }
3170
3171 sub compiler_predefined {
3172     state %predefined;
3173     my $cc = shift;
3174
3175     return () if $^O eq 'VMS';
3176
3177     die 'compiler_predefined called without a compiler command'
3178         unless $cc;
3179
3180     if (! $predefined{$cc}) {
3181
3182         $predefined{$cc} = {};
3183
3184         # collect compiler pre-defines from gcc or gcc-alike...
3185         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3186         while (my $l = <PIPE>) {
3187             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3188             $predefined{$cc}->{$1} = $2 // '';
3189         }
3190         close(PIPE);
3191     }
3192
3193     return %{$predefined{$cc}};
3194 }
3195
3196 sub which
3197 {
3198     my ($name)=@_;
3199
3200     if (eval { require IPC::Cmd; 1; }) {
3201         IPC::Cmd->import();
3202         return scalar IPC::Cmd::can_run($name);
3203     } else {
3204         # if there is $directories component in splitpath,
3205         # then it's not something to test with $PATH...
3206         return $name if (File::Spec->splitpath($name))[1];
3207
3208         foreach (File::Spec->path()) {
3209             my $fullpath = catfile($_, "$name$target{exe_extension}");
3210             if (-f $fullpath and -x $fullpath) {
3211                 return $fullpath;
3212             }
3213         }
3214     }
3215 }
3216
3217 sub env
3218 {
3219     my $name = shift;
3220     my %opts = @_;
3221
3222     unless ($opts{cacheonly}) {
3223         # Note that if $ENV{$name} doesn't exist or is undefined,
3224         # $config{perlenv}->{$name} will be created with the value
3225         # undef.  This is intentional.
3226
3227         $config{perlenv}->{$name} = $ENV{$name}
3228             if ! exists $config{perlenv}->{$name};
3229     }
3230     return $config{perlenv}->{$name};
3231 }
3232
3233 # Configuration printer ##############################################
3234
3235 sub print_table_entry
3236 {
3237     local $now_printing = shift;
3238     my %target = resolve_config($now_printing);
3239     my $type = shift;
3240
3241     # Don't print the templates
3242     return if $target{template};
3243
3244     my @sequence = (
3245         "sys_id",
3246         "cpp",
3247         "cppflags",
3248         "defines",
3249         "includes",
3250         "cc",
3251         "cflags",
3252         "ld",
3253         "lflags",
3254         "loutflag",
3255         "ex_libs",
3256         "bn_ops",
3257         "enable",
3258         "disable",
3259         "poly1035_asm_src",
3260         "thread_scheme",
3261         "perlasm_scheme",
3262         "dso_scheme",
3263         "shared_target",
3264         "shared_cflag",
3265         "shared_defines",
3266         "shared_ldflag",
3267         "shared_rcflag",
3268         "shared_extension",
3269         "dso_extension",
3270         "obj_extension",
3271         "exe_extension",
3272         "ranlib",
3273         "ar",
3274         "arflags",
3275         "aroutflag",
3276         "rc",
3277         "rcflags",
3278         "rcoutflag",
3279         "mt",
3280         "mtflags",
3281         "mtinflag",
3282         "mtoutflag",
3283         "multilib",
3284         "build_scheme",
3285         );
3286
3287     if ($type eq "TABLE") {
3288         print "\n";
3289         print "*** $now_printing\n";
3290         foreach (@sequence) {
3291             if (ref($target{$_}) eq "ARRAY") {
3292                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
3293             } else {
3294                 printf "\$%-12s = %s\n", $_, $target{$_};
3295             }
3296         }
3297     } elsif ($type eq "HASH") {
3298         my $largest =
3299             length((sort { length($a) <=> length($b) } @sequence)[-1]);
3300         print "    '$now_printing' => {\n";
3301         foreach (@sequence) {
3302             if ($target{$_}) {
3303                 if (ref($target{$_}) eq "ARRAY") {
3304                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
3305                 } else {
3306                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
3307                 }
3308             }
3309         }
3310         print "    },\n";
3311     }
3312 }
3313
3314 # Utility routines ###################################################
3315
3316 # On VMS, if the given file is a logical name, File::Spec::Functions
3317 # will consider it an absolute path.  There are cases when we want a
3318 # purely syntactic check without checking the environment.
3319 sub isabsolute {
3320     my $file = shift;
3321
3322     # On non-platforms, we just use file_name_is_absolute().
3323     return file_name_is_absolute($file) unless $^O eq "VMS";
3324
3325     # If the file spec includes a device or a directory spec,
3326     # file_name_is_absolute() is perfectly safe.
3327     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
3328
3329     # Here, we know the given file spec isn't absolute
3330     return 0;
3331 }
3332
3333 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
3334 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
3335 # realpath() requires that at least all path components except the last is an
3336 # existing directory.  On VMS, the last component of the directory spec must
3337 # exist.
3338 sub absolutedir {
3339     my $dir = shift;
3340
3341     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
3342     # will return the volume name for the device, no matter what.  Also,
3343     # it will return an incorrect directory spec if the argument is a
3344     # directory that doesn't exist.
3345     if ($^O eq "VMS") {
3346         return rel2abs($dir);
3347     }
3348
3349     # We use realpath() on Unix, since no other will properly clean out
3350     # a directory spec.
3351     use Cwd qw/realpath/;
3352
3353     return realpath($dir);
3354 }
3355
3356 # Check if all paths are one and the same, using stat.  They must both exist
3357 # We need this for the cases when File::Spec doesn't detect case insensitivity
3358 # (File::Spec::Unix assumes case sensitivity)
3359 sub samedir {
3360     die "samedir expects two arguments\n" unless scalar @_ == 2;
3361
3362     my @stat0 = stat($_[0]);    # First argument
3363     my @stat1 = stat($_[1]);    # Second argument
3364
3365     die "Couldn't stat $_[0]" unless @stat0;
3366     die "Couldn't stat $_[1]" unless @stat1;
3367
3368     # Compare device number
3369     return 0 unless ($stat0[0] == $stat1[0]);
3370     # Compare "inode".  The perl manual recommends comparing as
3371     # string rather than as number.
3372     return 0 unless ($stat0[1] eq $stat1[1]);
3373
3374     return 1;                   # All the same
3375 }
3376
3377 sub quotify {
3378     my %processors = (
3379         perl    => sub { my $x = shift;
3380                          $x =~ s/([\\\$\@"])/\\$1/g;
3381                          return '"'.$x.'"'; },
3382         maybeshell => sub { my $x = shift;
3383                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
3384                             if ($x ne $y || $x =~ m|\s|) {
3385                                 return '"'.$y.'"';
3386                             } else {
3387                                 return $x;
3388                             }
3389                         },
3390         );
3391     my $for = shift;
3392     my $processor =
3393         defined($processors{$for}) ? $processors{$for} : sub { shift; };
3394
3395     return map { $processor->($_); } @_;
3396 }
3397
3398 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
3399 # $filename is a file name to read from
3400 # $line_concat_cond_re is a regexp detecting a line continuation ending
3401 # $line_concat is a CODEref that takes care of concatenating two lines
3402 sub collect_from_file {
3403     my $filename = shift;
3404     my $line_concat_cond_re = shift;
3405     my $line_concat = shift;
3406
3407     open my $fh, $filename || die "unable to read $filename: $!\n";
3408     return sub {
3409         my $saved_line = "";
3410         $_ = "";
3411         while (<$fh>) {
3412             s|\R$||;
3413             if (defined $line_concat) {
3414                 $_ = $line_concat->($saved_line, $_);
3415                 $saved_line = "";
3416             }
3417             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3418                 $saved_line = $_;
3419                 next;
3420             }
3421             return $_;
3422         }
3423         die "$filename ending with continuation line\n" if $_;
3424         close $fh;
3425         return undef;
3426     }
3427 }
3428
3429 # collect_from_array($array, $line_concat_cond_re, $line_concat)
3430 # $array is an ARRAYref of lines
3431 # $line_concat_cond_re is a regexp detecting a line continuation ending
3432 # $line_concat is a CODEref that takes care of concatenating two lines
3433 sub collect_from_array {
3434     my $array = shift;
3435     my $line_concat_cond_re = shift;
3436     my $line_concat = shift;
3437     my @array = (@$array);
3438
3439     return sub {
3440         my $saved_line = "";
3441         $_ = "";
3442         while (defined($_ = shift @array)) {
3443             s|\R$||;
3444             if (defined $line_concat) {
3445                 $_ = $line_concat->($saved_line, $_);
3446                 $saved_line = "";
3447             }
3448             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3449                 $saved_line = $_;
3450                 next;
3451             }
3452             return $_;
3453         }
3454         die "input text ending with continuation line\n" if $_;
3455         return undef;
3456     }
3457 }
3458
3459 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
3460 # $lineiterator is a CODEref that delivers one line at a time.
3461 # All following arguments are regex/CODEref pairs, where the regexp detects a
3462 # line and the CODEref does something with the result of the regexp.
3463 sub collect_information {
3464     my $lineiterator = shift;
3465     my %collectors = @_;
3466
3467     while(defined($_ = $lineiterator->())) {
3468         s|\R$||;
3469         my $found = 0;
3470         if ($collectors{"BEFORE"}) {
3471             $collectors{"BEFORE"}->($_);
3472         }
3473         foreach my $re (keys %collectors) {
3474             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
3475                 $collectors{$re}->($lineiterator);
3476                 $found = 1;
3477             };
3478         }
3479         if ($collectors{"OTHERWISE"}) {
3480             $collectors{"OTHERWISE"}->($lineiterator, $_)
3481                 unless $found || !defined $collectors{"OTHERWISE"};
3482         }
3483         if ($collectors{"AFTER"}) {
3484             $collectors{"AFTER"}->($_);
3485         }
3486     }
3487 }
3488
3489 # tokenize($line)
3490 # tokenize($line,$separator)
3491 # $line is a line of text to split up into tokens
3492 # $separator [optional] is a regular expression that separates the tokens,
3493 # the default being spaces.  Do not use quotes of any kind as separators,
3494 # that will give undefined results.
3495 # Returns a list of tokens.
3496 #
3497 # Tokens are divided by separator (spaces by default).  If the tokens include
3498 # the separators, they have to be quoted with single or double quotes.
3499 # Double quotes inside a double quoted token must be escaped.  Escaping is done
3500 # with backslash.
3501 # Basically, the same quoting rules apply for " and ' as in any
3502 # Unix shell.
3503 sub tokenize {
3504     my $line = my $debug_line = shift;
3505     my $separator = shift // qr|\s+|;
3506     my @result = ();
3507
3508     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3509         print STDERR "DEBUG[tokenize]: \$separator = $separator\n";
3510     }
3511
3512     while ($line =~ s|^${separator}||, $line ne "") {
3513         my $token = "";
3514     again:
3515         $line =~ m/^(.*?)(${separator}|"|'|$)/;
3516         $token .= $1;
3517         $line = $2.$';
3518
3519         if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
3520             $token .= $1;
3521             $line = $';
3522             goto again;
3523         } elsif ($line =~ m/^'([^']*)'/) {
3524             $token .= $1;
3525             $line = $';
3526             goto again;
3527         }
3528         push @result, $token;
3529     }
3530
3531     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3532         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
3533         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
3534     }
3535     return @result;
3536 }