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