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