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