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