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