Configure: process shared-info.pl later
[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                         }
864                 elsif (/^-D(.*)$/)
865                         {
866                         push @{$useradd{CPPDEFINES}}, $1;
867                         }
868                 elsif (/^-I(.*)$/)
869                         {
870                         push @{$useradd{CPPINCLUDES}}, $1;
871                         }
872                 elsif (/^-Wp,$/)
873                         {
874                         push @{$useradd{CPPFLAGS}}, $1;
875                         }
876                 else    # common if (/^[-+]/), just pass down...
877                         {
878                         $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
879                         push @{$useradd{CFLAGS}}, $_;
880                         push @{$useradd{CXXFLAGS}}, $_;
881                         }
882                 }
883         else
884                 {
885                 die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
886                 $target=$_;
887                 }
888         unless ($_ eq $target || /^no-/ || /^disable-/)
889                 {
890                 # "no-..." follows later after implied deactivations
891                 # have been derived.  (Don't take this too seriously,
892                 # we really only write OPTIONS to the Makefile out of
893                 # nostalgia.)
894
895                 if ($config{options} eq "")
896                         { $config{options} = $_; }
897                 else
898                         { $config{options} .= " ".$_; }
899                 }
900         }
901
902 if (defined($config{api}) && !exists $apitable->{$config{api}}) {
903         die "***** Unsupported api compatibility level: $config{api}\n",
904 }
905
906 if (keys %deprecated_options)
907         {
908         warn "***** Deprecated options: ",
909                 join(", ", keys %deprecated_options), "\n";
910         }
911 if (keys %unsupported_options)
912         {
913         die "***** Unsupported options: ",
914                 join(", ", keys %unsupported_options), "\n";
915         }
916
917 # If any %useradd entry has been set, we must check that the "make
918 # variables" haven't been set.  We start by checking of any %useradd entry
919 # is set.
920 if (grep { scalar @$_ > 0 } values %useradd) {
921     # Hash of env / make variables names.  The possible values are:
922     # 1 - "make vars"
923     # 2 - %useradd entry set
924     # 3 - both set
925     my %detected_vars =
926         map { my $v = 0;
927               $v += 1 if $cmdvars{$_};
928               $v += 2 if @{$useradd{$_}};
929               $_ => $v }
930         keys %useradd;
931
932     # If any of the corresponding "make variables" is set, we error
933     if (grep { $_ & 1 } values %detected_vars) {
934         my $names = join(', ', grep { $detected_vars{$_} > 0 }
935                                sort keys %detected_vars);
936         die <<"_____";
937 ***** Mixing make variables and additional compiler/linker flags as
938 ***** configure command line option is not permitted.
939 ***** Affected make variables: $names
940 _____
941     }
942 }
943
944 # Check through all supported command line variables to see if any of them
945 # were set, and canonicalise the values we got.  If no compiler or linker
946 # flag or anything else that affects %useradd was set, we also check the
947 # environment for values.
948 my $anyuseradd =
949     grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
950 foreach (keys %user) {
951     my $value = $cmdvars{$_};
952     $value //= env($_) unless $anyuseradd;
953     $value //=
954         defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
955     $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
956         unless $anyuseradd;
957
958     if (defined $value) {
959         if (ref $user{$_} eq 'ARRAY') {
960             $user{$_} = [ split /$list_separator_re/, $value ];
961         } elsif (!defined $user{$_}) {
962             $user{$_} = $value;
963         }
964     }
965 }
966
967 if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
968     && !$disabled{shared}
969     && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
970     die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
971         "***** any of asan, msan or ubsan\n";
972 }
973
974 sub disable {
975     my $disable_type = shift;
976
977     for (@_) {
978         $disabled{$_} = $disable_type;
979     }
980
981     my @tocheckfor = (@_ ? @_ : keys %disabled);
982     while (@tocheckfor) {
983         my %new_tocheckfor = ();
984         my @cascade_copy = (@disable_cascades);
985         while (@cascade_copy) {
986             my ($test, $descendents) =
987                 (shift @cascade_copy, shift @cascade_copy);
988             if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
989                 foreach (grep { !defined($disabled{$_}) } @$descendents) {
990                     $new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
991                 }
992             }
993         }
994         @tocheckfor = (keys %new_tocheckfor);
995     }
996 }
997 disable();                     # First cascade run
998
999 our $die = sub { die @_; };
1000 if ($target eq "TABLE") {
1001     local $die = sub { warn @_; };
1002     foreach (sort keys %table) {
1003         print_table_entry($_, "TABLE");
1004     }
1005     exit 0;
1006 }
1007
1008 if ($target eq "LIST") {
1009     foreach (sort keys %table) {
1010         print $_,"\n" unless $table{$_}->{template};
1011     }
1012     exit 0;
1013 }
1014
1015 if ($target eq "HASH") {
1016     local $die = sub { warn @_; };
1017     print "%table = (\n";
1018     foreach (sort keys %table) {
1019         print_table_entry($_, "HASH");
1020     }
1021     exit 0;
1022 }
1023
1024 print "Configuring OpenSSL version $config{version} ($config{version_num}) ";
1025 print "for $target\n";
1026
1027 if (scalar(@seed_sources) == 0) {
1028     print "Using os-specific seed configuration\n";
1029     push @seed_sources, 'os';
1030 }
1031 if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
1032     die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
1033     warn <<_____ if scalar(@seed_sources) == 1;
1034
1035 ============================== WARNING ===============================
1036 You have selected the --with-rand-seed=none option, which effectively
1037 disables automatic reseeding of the OpenSSL random generator.
1038 All operations depending on the random generator such as creating keys
1039 will not work unless the random generator is seeded manually by the
1040 application.
1041
1042 Please read the 'Note on random number generation' section in the
1043 INSTALL instructions and the RAND_DRBG(7) manual page for more details.
1044 ============================== WARNING ===============================
1045
1046 _____
1047 }
1048 push @{$config{openssl_other_defines}},
1049      map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
1050         @seed_sources;
1051
1052 # Backward compatibility?
1053 if ($target =~ m/^CygWin32(-.*)$/) {
1054     $target = "Cygwin".$1;
1055 }
1056
1057 # Support for legacy targets having a name starting with 'debug-'
1058 my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
1059 if ($d) {
1060     $config{build_type} = "debug";
1061
1062     # If we do not find debug-foo in the table, the target is set to foo.
1063     if (!$table{$target}) {
1064         $target = $t;
1065     }
1066 }
1067
1068 &usage if !$table{$target} || $table{$target}->{template};
1069
1070 $config{target} = $target;
1071 my %target = resolve_config($target);
1072
1073 foreach (keys %target_attr_translate) {
1074     $target{$target_attr_translate{$_}} = $target{$_}
1075         if $target{$_};
1076     delete $target{$_};
1077 }
1078
1079 %target = ( %{$table{DEFAULTS}}, %target );
1080
1081 my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
1082 $config{conf_files} = [ sort keys %conf_files ];
1083
1084 # Using sub disable within these loops may prove fragile, so we run
1085 # a cascade afterwards
1086 foreach my $feature (@{$target{disable}}) {
1087     if (exists $deprecated_disablables{$feature}) {
1088         warn "***** config $target disables deprecated feature $feature\n";
1089     } elsif (!grep { $feature eq $_ } @disablables) {
1090         die "***** config $target disables unknown feature $feature\n";
1091     }
1092     $disabled{$feature} = 'config';
1093 }
1094 foreach my $feature (@{$target{enable}}) {
1095     if ("default" eq ($disabled{$feature} // "")) {
1096         if (exists $deprecated_disablables{$feature}) {
1097             warn "***** config $target enables deprecated feature $feature\n";
1098         } elsif (!grep { $feature eq $_ } @disablables) {
1099             die "***** config $target enables unknown feature $feature\n";
1100         }
1101         delete $disabled{$feature};
1102     }
1103 }
1104 disable();                      # Run a cascade now
1105
1106 $target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
1107 $target{cxxflags}//=$target{cflags} if $target{CXX};
1108 $target{exe_extension}="";
1109 $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
1110                                   || $config{target} =~ /^(?:Cygwin|mingw)/);
1111 $target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
1112
1113 ($target{shared_extension_simple}=$target{shared_extension})
1114     =~ s|\.\$\(SHLIB_VERSION_NUMBER\)||
1115     unless defined($target{shared_extension_simple});
1116 $target{dso_extension}//=$target{shared_extension_simple};
1117 ($target{shared_import_extension}=$target{shared_extension_simple}.".a")
1118     if ($config{target} =~ /^(?:Cygwin|mingw)/);
1119
1120 # Fill %config with values from %user, and in case those are undefined or
1121 # empty, use values from %target (acting as a default).
1122 foreach (keys %user) {
1123     my $ref_type = ref $user{$_};
1124
1125     # Temporary function.  Takes an intended ref type (empty string or "ARRAY")
1126     # and a value that's to be coerced into that type.
1127     my $mkvalue = sub {
1128         my $type = shift;
1129         my $value = shift;
1130         my $undef_p = shift;
1131
1132         die "Too many arguments for \$mkvalue" if @_;
1133
1134         while (ref $value eq 'CODE') {
1135             $value = $value->();
1136         }
1137
1138         if ($type eq 'ARRAY') {
1139             return undef unless defined $value;
1140             return undef if ref $value ne 'ARRAY' && !$value;
1141             return undef if ref $value eq 'ARRAY' && !@$value;
1142             return [ $value ] unless ref $value eq 'ARRAY';
1143         }
1144         return undef unless $value;
1145         return $value;
1146     };
1147
1148     $config{$_} =
1149         $mkvalue->($ref_type, $user{$_})
1150         || $mkvalue->($ref_type, $target{$_});
1151     delete $config{$_} unless defined $config{$_};
1152 }
1153
1154 # Finish up %config by appending things the user gave us on the command line
1155 # apart from "make variables"
1156 foreach (keys %useradd) {
1157     # The must all be lists, so we assert that here
1158     die "internal error: \$useradd{$_} isn't an ARRAY\n"
1159         unless ref $useradd{$_} eq 'ARRAY';
1160
1161     if (defined $config{$_}) {
1162         push @{$config{$_}}, @{$useradd{$_}};
1163     } else {
1164         $config{$_} = [ @{$useradd{$_}} ];
1165     }
1166 }
1167 # At this point, we can forget everything about %user and %useradd,
1168 # because it's now all been merged into the corresponding $config entry
1169
1170 # Allow overriding the build file name
1171 $config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
1172
1173 my %disabled_info = ();         # For configdata.pm
1174 foreach my $what (sort keys %disabled) {
1175     $config{options} .= " no-$what";
1176
1177     if (!grep { $what eq $_ } ( 'threads', 'shared', 'pic',
1178                                 'dynamic-engine', 'makedepend',
1179                                 'zlib-dynamic', 'zlib', 'sse2' )) {
1180         (my $WHAT = uc $what) =~ s|-|_|g;
1181
1182         # Fix up C macro end names
1183         $WHAT = "RMD160" if $what eq "ripemd";
1184
1185         # fix-up crypto/directory name(s)
1186         $what = "ripemd" if $what eq "rmd160";
1187         $what = "whrlpool" if $what eq "whirlpool";
1188
1189         my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
1190
1191         if ((grep { $what eq $_ } @{$config{sdirs}})
1192                 && $what ne 'async' && $what ne 'err') {
1193             @{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}};
1194             $disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ];
1195
1196             if ($what ne 'engine') {
1197                 push @{$config{openssl_algorithm_defines}}, $macro;
1198             } else {
1199                 @{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
1200                 push @{$disabled_info{engine}->{skipped}}, catdir('engines');
1201                 push @{$config{openssl_other_defines}}, $macro;
1202             }
1203         } else {
1204             push @{$config{openssl_other_defines}}, $macro;
1205         }
1206
1207     }
1208 }
1209
1210 # Make sure build_scheme is consistent.
1211 $target{build_scheme} = [ $target{build_scheme} ]
1212     if ref($target{build_scheme}) ne "ARRAY";
1213
1214 my ($builder, $builder_platform, @builder_opts) =
1215     @{$target{build_scheme}};
1216
1217 foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
1218                       $builder_platform."-checker.pm")) {
1219     my $checker_path = catfile($srcdir, "Configurations", $checker);
1220     if (-f $checker_path) {
1221         my $fn = $ENV{CONFIGURE_CHECKER_WARN}
1222             ? sub { warn $@; } : sub { die $@; };
1223         if (! do $checker_path) {
1224             if ($@) {
1225                 $fn->($@);
1226             } elsif ($!) {
1227                 $fn->($!);
1228             } else {
1229                 $fn->("The detected tools didn't match the platform\n");
1230             }
1231         }
1232         last;
1233     }
1234 }
1235
1236 push @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
1237
1238 if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
1239         {
1240         push @{$config{cflags}}, "-mno-cygwin";
1241         push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
1242         push @{$config{shared_ldflag}}, "-mno-cygwin";
1243         }
1244
1245 if ($target =~ /linux.*-mips/ && !$disabled{asm}
1246         && !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
1247         # minimally required architecture flags for assembly modules
1248         my $value;
1249         $value = '-mips2' if ($target =~ /mips32/);
1250         $value = '-mips3' if ($target =~ /mips64/);
1251         unshift @{$config{cflags}}, $value;
1252         unshift @{$config{cxxflags}}, $value if $config{CXX};
1253 }
1254
1255 # If threads aren't disabled, check how possible they are
1256 unless ($disabled{threads}) {
1257     if ($auto_threads) {
1258         # Enabled by default, disable it forcibly if unavailable
1259         if ($target{thread_scheme} eq "(unknown)") {
1260             disable("unavailable", 'threads');
1261         }
1262     } else {
1263         # The user chose to enable threads explicitly, let's see
1264         # if there's a chance that's possible
1265         if ($target{thread_scheme} eq "(unknown)") {
1266             # If the user asked for "threads" and we don't have internal
1267             # knowledge how to do it, [s]he is expected to provide any
1268             # system-dependent compiler options that are necessary.  We
1269             # can't truly check that the given options are correct, but
1270             # we expect the user to know what [s]He is doing.
1271             if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
1272                 die "You asked for multi-threading support, but didn't\n"
1273                     ,"provide any system-specific compiler options\n";
1274             }
1275         }
1276     }
1277 }
1278
1279 # If threads still aren't disabled, add a C macro to ensure the source
1280 # code knows about it.  Any other flag is taken care of by the configs.
1281 unless($disabled{threads}) {
1282     push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS";
1283 }
1284
1285 # With "deprecated" disable all deprecated features.
1286 if (defined($disabled{"deprecated"})) {
1287         $config{api} = $maxapi;
1288 }
1289
1290 my $no_shared_warn=0;
1291 if ($target{shared_target} eq "")
1292         {
1293         $no_shared_warn = 1
1294             if (!$disabled{shared} || !$disabled{"dynamic-engine"});
1295         disable('no-shared-target', 'pic');
1296         }
1297
1298 if ($disabled{"dynamic-engine"}) {
1299         push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
1300         $config{dynamic_engines} = 0;
1301 } else {
1302         push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE";
1303         $config{dynamic_engines} = 1;
1304 }
1305
1306 unless ($disabled{asan}) {
1307     push @{$config{cflags}}, "-fsanitize=address";
1308     push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX};
1309 }
1310
1311 unless ($disabled{ubsan}) {
1312     # -DPEDANTIC or -fnosanitize=alignment may also be required on some
1313     # platforms.
1314     push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
1315     push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"
1316         if $config{CXX};
1317 }
1318
1319 unless ($disabled{msan}) {
1320   push @{$config{cflags}}, "-fsanitize=memory";
1321   push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX};
1322 }
1323
1324 unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
1325         && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
1326     push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
1327     push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
1328 }
1329 #
1330 # Platform fix-ups
1331 #
1332
1333 # This saves the build files from having to check
1334 if ($disabled{pic})
1335         {
1336         foreach (qw(shared_cflag shared_cxxflag shared_cppflag
1337                     shared_defines shared_includes shared_ldflag
1338                     module_cflags module_cxxflags module_cppflags
1339                     module_defines module_includes module_lflags))
1340                 {
1341                 delete $config{$_};
1342                 $target{$_} = "";
1343                 }
1344         }
1345 else
1346         {
1347         push @{$config{lib_defines}}, "OPENSSL_PIC";
1348         }
1349
1350 if ($target{sys_id} ne "")
1351         {
1352         push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1353         }
1354
1355 unless ($disabled{asm}) {
1356     $target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
1357     push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c");
1358
1359     $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
1360
1361     # bn-586 is the only one implementing bn_*_part_words
1362     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
1363     push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/);
1364
1365     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
1366     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
1367     push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
1368     push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/);
1369
1370     if ($target{sha1_asm_src}) {
1371         push @{$config{lib_defines}}, "SHA1_ASM"   if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
1372         push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
1373         push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
1374     }
1375     if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
1376         push @{$config{lib_defines}}, "KECCAK1600_ASM";
1377     }
1378     if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
1379         push @{$config{lib_defines}}, "RC4_ASM";
1380     }
1381     if ($target{md5_asm_src}) {
1382         push @{$config{lib_defines}}, "MD5_ASM";
1383     }
1384     $target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
1385     if ($target{rmd160_asm_src}) {
1386         push @{$config{lib_defines}}, "RMD160_ASM";
1387     }
1388     if ($target{aes_asm_src}) {
1389         push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
1390         # aes-ctr.fake is not a real file, only indication that assembler
1391         # module implements AES_ctr32_encrypt...
1392         push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
1393         # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
1394         push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
1395         $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
1396         push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
1397         push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
1398     }
1399     if ($target{wp_asm_src} =~ /mmx/) {
1400         if ($config{processor} eq "386") {
1401             $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
1402         } elsif (!$disabled{"whirlpool"}) {
1403             push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
1404         }
1405     }
1406     if ($target{modes_asm_src} =~ /ghash-/) {
1407         push @{$config{lib_defines}}, "GHASH_ASM";
1408     }
1409     if ($target{ec_asm_src} =~ /ecp_nistz256/) {
1410         push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
1411     }
1412     if ($target{ec_asm_src} =~ /x25519/) {
1413         push @{$config{lib_defines}}, "X25519_ASM";
1414     }
1415     if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
1416         push @{$config{dso_defines}}, "PADLOCK_ASM";
1417     }
1418     if ($target{poly1305_asm_src} ne "") {
1419         push @{$config{lib_defines}}, "POLY1305_ASM";
1420     }
1421 }
1422
1423 my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
1424 my %predefined_CXX = $config{CXX}
1425     ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
1426     : ();
1427
1428 # Check for makedepend capabilities.
1429 if (!$disabled{makedepend}) {
1430     if ($config{target} =~ /^(VC|vms)-/) {
1431         # For VC- and vms- targets, there's nothing more to do here.  The
1432         # functionality is hard coded in the corresponding build files for
1433         # cl (Windows) and CC/DECC (VMS).
1434     } elsif (($predefined_C{__GNUC__} // -1) >= 3
1435              && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
1436         # We know that GNU C version 3 and up as well as all clang
1437         # versions support dependency generation, but Xcode did not
1438         # handle $cc -M before clang support (but claims __GNUC__ = 3)
1439         $config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}";
1440     } else {
1441         # In all other cases, we look for 'makedepend', and disable the
1442         # capability if not found.
1443         $config{makedepprog} = which('makedepend');
1444         disable('unavailable', 'makedepend') unless $config{makedepprog};
1445     }
1446 }
1447
1448 if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
1449     # probe for -Wa,--noexecstack option...
1450     if ($predefined_C{__clang__}) {
1451         # clang has builtin assembler, which doesn't recognize --help,
1452         # but it apparently recognizes the option in question on all
1453         # supported platforms even when it's meaningless. In other words
1454         # probe would fail, but probed option always accepted...
1455         push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
1456     } else {
1457         my $cc = $config{CROSS_COMPILE}.$config{CC};
1458         open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
1459         while(<PIPE>) {
1460             if (m/--noexecstack/) {
1461                 push @{$config{cflags}}, "-Wa,--noexecstack";
1462                 last;
1463             }
1464         }
1465         close(PIPE);
1466         unlink("null.$$.o");
1467     }
1468 }
1469
1470 # Deal with bn_ops ###################################################
1471
1472 $config{bn_ll}                  =0;
1473 $config{export_var_as_fn}       =0;
1474 my $def_int="unsigned int";
1475 $config{rc4_int}                =$def_int;
1476 ($config{b64l},$config{b64},$config{b32})=(0,0,1);
1477
1478 my $count = 0;
1479 foreach (sort split(/\s+/,$target{bn_ops})) {
1480     $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
1481     $config{export_var_as_fn}=1                 if $_ eq 'EXPORT_VAR_AS_FN';
1482     $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
1483     $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
1484     ($config{b64l},$config{b64},$config{b32})
1485         =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
1486     ($config{b64l},$config{b64},$config{b32})
1487         =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
1488     ($config{b64l},$config{b64},$config{b32})
1489         =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
1490 }
1491 die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
1492     if $count > 1;
1493
1494
1495 # Hack cflags for better warnings (dev option) #######################
1496
1497 # "Stringify" the C and C++ flags string.  This permits it to be made part of
1498 # a string and works as well on command lines.
1499 $config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1500                         @{$config{cflags}} ];
1501 $config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1502                           @{$config{cxxflags}} ] if $config{CXX};
1503
1504 if (defined($config{api})) {
1505     $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
1506     my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
1507     push @{$config{defines}}, $apiflag;
1508 }
1509
1510 my %strict_warnings_collection=( CFLAGS => [], CXXFLAGS => []);
1511 if ($strict_warnings)
1512         {
1513         my $wopt;
1514         my $gccver = $predefined_C{__GNUC__} // -1;
1515         my $gxxver = $predefined_CXX{__GNUC__} // -1;
1516
1517         warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike"
1518             unless $gccver >= 4;
1519         warn "WARNING --strict-warnings requires g++[>=4] or g++-alike"
1520             unless $gxxver >= 4;
1521         foreach (qw(CFLAGS CXXFLAGS))
1522                 {
1523                 push @{$strict_warnings_collection{$_}},
1524                         @{$gcc_devteam_warn{$_}};
1525                 }
1526         push @{$strict_warnings_collection{CFLAGS}},
1527                 @{$clang_devteam_warn{CFLAGS}}
1528                         if (defined($predefined_C{__clang__}));
1529         push @{$strict_warnings_collection{CXXFLAGS}},
1530                 @{$clang_devteam_warn{CXXFLAGS}}
1531                         if (defined($predefined_CXX{__clang__}));
1532         }
1533
1534 if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
1535     disable('static', 'pic', 'threads');
1536 }
1537
1538 foreach my $idx (qw(CFLAGS CXXFLAGS))
1539         {
1540         $config{$idx} = [ map { $_ eq '--ossl-strict-warnings'
1541                                     ? @{$strict_warnings_collection{$idx}}
1542                                 : ( $_ ) }
1543                           @{$config{$idx}} ];
1544         }
1545
1546 unless ($disabled{"crypto-mdebug-backtrace"})
1547         {
1548         foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
1549                 {
1550                 push @{$config{cflags}}, $wopt
1551                         unless grep { $_ eq $wopt } @{$config{cflags}};
1552                 push @{$config{cxxflags}}, $wopt
1553                         if ($config{CXX}
1554                             && !grep { $_ eq $wopt } @{$config{cxxflags}});
1555                 }
1556         if ($target =~ /^BSD-/)
1557                 {
1558                 push @{$config{ex_libs}}, "-lexecinfo";
1559                 }
1560         }
1561
1562 unless ($disabled{afalgeng}) {
1563     $config{afalgeng}="";
1564     if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
1565         my $minver = 4*10000 + 1*100 + 0;
1566         if ($config{CROSS_COMPILE} eq "") {
1567             my $verstr = `uname -r`;
1568             my ($ma, $mi1, $mi2) = split("\\.", $verstr);
1569             ($mi2) = $mi2 =~ /(\d+)/;
1570             my $ver = $ma*10000 + $mi1*100 + $mi2;
1571             if ($ver < $minver) {
1572                 disable('too-old-kernel', 'afalgeng');
1573             } else {
1574                 push @{$config{engdirs}}, "afalg";
1575             }
1576         } else {
1577             disable('cross-compiling', 'afalgeng');
1578         }
1579     } else {
1580         disable('not-linux', 'afalgeng');
1581     }
1582 }
1583
1584 push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
1585
1586 # Get the extra flags used when building shared libraries and modules.  We
1587 # do this late because some of them depend on %disabled.
1588
1589 # Make the flags to build DSOs the same as for shared libraries unless they
1590 # are already defined
1591 $target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
1592 $target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
1593 $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
1594 {
1595     my $shared_info_pl =
1596         catfile(dirname($0), "Configurations", "shared-info.pl");
1597     my %shared_info = read_eval_file($shared_info_pl);
1598     push @{$target{_conf_fname_int}}, $shared_info_pl;
1599     my $si = $target{shared_target};
1600     while (ref $si ne "HASH") {
1601         last if ! defined $si;
1602         if (ref $si eq "CODE") {
1603             $si = $si->();
1604         } else {
1605             $si = $shared_info{$si};
1606         }
1607     }
1608
1609     # Some of the 'shared_target' values don't have any entries in
1610     # %shared_info.  That's perfectly fine, AS LONG AS the build file
1611     # template knows how to handle this.  That is currently the case for
1612     # Windows and VMS.
1613     if (defined $si) {
1614         # Just as above, copy certain shared_* attributes to the corresponding
1615         # module_ attribute unless the latter is already defined
1616         $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
1617         $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
1618         $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
1619         foreach (sort keys %$si) {
1620             $target{$_} = defined $target{$_}
1621                 ? add($si->{$_})->($target{$_})
1622                 : $si->{$_};
1623         }
1624     }
1625 }
1626
1627 # ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
1628
1629 # If we use the unified build, collect information from build.info files
1630 my %unified_info = ();
1631
1632 my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
1633 if ($builder eq "unified") {
1634     use with_fallback qw(Text::Template);
1635
1636     sub cleandir {
1637         my $base = shift;
1638         my $dir = shift;
1639         my $relativeto = shift || ".";
1640
1641         $dir = catdir($base,$dir) unless isabsolute($dir);
1642
1643         # Make sure the directories we're building in exists
1644         mkpath($dir);
1645
1646         my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
1647         #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
1648         return $res;
1649     }
1650
1651     sub cleanfile {
1652         my $base = shift;
1653         my $file = shift;
1654         my $relativeto = shift || ".";
1655
1656         $file = catfile($base,$file) unless isabsolute($file);
1657
1658         my $d = dirname($file);
1659         my $f = basename($file);
1660
1661         # Make sure the directories we're building in exists
1662         mkpath($d);
1663
1664         my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
1665         #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
1666         return $res;
1667     }
1668
1669     # Store the name of the template file we will build the build file from
1670     # in %config.  This may be useful for the build file itself.
1671     my @build_file_template_names =
1672         ( $builder_platform."-".$target{build_file}.".tmpl",
1673           $target{build_file}.".tmpl" );
1674     my @build_file_templates = ();
1675
1676     # First, look in the user provided directory, if given
1677     if (defined env($local_config_envname)) {
1678         @build_file_templates =
1679             map {
1680                 if ($^O eq 'VMS') {
1681                     # VMS environment variables are logical names,
1682                     # which can be used as is
1683                     $local_config_envname . ':' . $_;
1684                 } else {
1685                     catfile(env($local_config_envname), $_);
1686                 }
1687             }
1688             @build_file_template_names;
1689     }
1690     # Then, look in our standard directory
1691     push @build_file_templates,
1692         ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
1693           @build_file_template_names );
1694
1695     my $build_file_template;
1696     for $_ (@build_file_templates) {
1697         $build_file_template = $_;
1698         last if -f $build_file_template;
1699
1700         $build_file_template = undef;
1701     }
1702     if (!defined $build_file_template) {
1703         die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
1704     }
1705     $config{build_file_templates}
1706       = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
1707                     $blddir),
1708           $build_file_template,
1709           cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
1710                     $blddir) ];
1711
1712     my @build_infos = ( [ ".", "build.info" ] );
1713     foreach (@{$config{dirs}}) {
1714         push @build_infos, [ $_, "build.info" ]
1715             if (-f catfile($srcdir, $_, "build.info"));
1716     }
1717     foreach (@{$config{sdirs}}) {
1718         push @build_infos, [ catdir("crypto", $_), "build.info" ]
1719             if (-f catfile($srcdir, "crypto", $_, "build.info"));
1720     }
1721     foreach (@{$config{engdirs}}) {
1722         push @build_infos, [ catdir("engines", $_), "build.info" ]
1723             if (-f catfile($srcdir, "engines", $_, "build.info"));
1724     }
1725     foreach (@{$config{tdirs}}) {
1726         push @build_infos, [ catdir("test", $_), "build.info" ]
1727             if (-f catfile($srcdir, "test", $_, "build.info"));
1728     }
1729
1730     $config{build_infos} = [ ];
1731
1732     my %ordinals = ();
1733     foreach (@build_infos) {
1734         my $sourced = catdir($srcdir, $_->[0]);
1735         my $buildd = catdir($blddir, $_->[0]);
1736
1737         mkpath($buildd);
1738
1739         my $f = $_->[1];
1740         # The basic things we're trying to build
1741         my @programs = ();
1742         my @programs_install = ();
1743         my @libraries = ();
1744         my @libraries_install = ();
1745         my @engines = ();
1746         my @engines_install = ();
1747         my @scripts = ();
1748         my @scripts_install = ();
1749         my @extra = ();
1750         my @overrides = ();
1751         my @intermediates = ();
1752         my @rawlines = ();
1753
1754         my %sources = ();
1755         my %shared_sources = ();
1756         my %includes = ();
1757         my %depends = ();
1758         my %renames = ();
1759         my %sharednames = ();
1760         my %generate = ();
1761
1762         # We want to detect configdata.pm in the source tree, so we
1763         # don't use it if the build tree is different.
1764         my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
1765
1766         push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
1767         my $template =
1768             Text::Template->new(TYPE => 'FILE',
1769                                 SOURCE => catfile($sourced, $f),
1770                                 PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
1771         die "Something went wrong with $sourced/$f: $!\n" unless $template;
1772         my @text =
1773             split /^/m,
1774             $template->fill_in(HASH => { config => \%config,
1775                                          target => \%target,
1776                                          disabled => \%disabled,
1777                                          withargs => \%withargs,
1778                                          builddir => abs2rel($buildd, $blddir),
1779                                          sourcedir => abs2rel($sourced, $blddir),
1780                                          buildtop => abs2rel($blddir, $blddir),
1781                                          sourcetop => abs2rel($srcdir, $blddir) },
1782                                DELIMITERS => [ "{-", "-}" ]);
1783
1784         # The top item of this stack has the following values
1785         # -2 positive already run and we found ELSE (following ELSIF should fail)
1786         # -1 positive already run (skip until ENDIF)
1787         # 0 negatives so far (if we're at a condition, check it)
1788         # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
1789         # 2 positive ELSE (following ELSIF should fail)
1790         my @skip = ();
1791         collect_information(
1792             collect_from_array([ @text ],
1793                                qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
1794                                                 $l1 =~ s/\\$//; $l1.$l2 }),
1795             # Info we're looking for
1796             qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
1797             => sub {
1798                 if (! @skip || $skip[$#skip] > 0) {
1799                     push @skip, !! $1;
1800                 } else {
1801                     push @skip, -1;
1802                 }
1803             },
1804             qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
1805             => sub { die "ELSIF out of scope" if ! @skip;
1806                      die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
1807                      $skip[$#skip] = -1 if $skip[$#skip] != 0;
1808                      $skip[$#skip] = !! $1
1809                          if $skip[$#skip] == 0; },
1810             qr/^\s*ELSE\s*$/
1811             => sub { die "ELSE out of scope" if ! @skip;
1812                      $skip[$#skip] = -2 if $skip[$#skip] != 0;
1813                      $skip[$#skip] = 2 if $skip[$#skip] == 0; },
1814             qr/^\s*ENDIF\s*$/
1815             => sub { die "ENDIF out of scope" if ! @skip;
1816                      pop @skip; },
1817             qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
1818             => sub {
1819                 if (!@skip || $skip[$#skip] > 0) {
1820                     my $install = $1;
1821                     my @x = tokenize($2);
1822                     push @programs, @x;
1823                     push @programs_install, @x unless $install;
1824                 }
1825             },
1826             qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
1827             => sub {
1828                 if (!@skip || $skip[$#skip] > 0) {
1829                     my $install = $1;
1830                     my @x = tokenize($2);
1831                     push @libraries, @x;
1832                     push @libraries_install, @x unless $install;
1833                 }
1834             },
1835             qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
1836             => sub {
1837                 if (!@skip || $skip[$#skip] > 0) {
1838                     my $install = $1;
1839                     my @x = tokenize($2);
1840                     push @engines, @x;
1841                     push @engines_install, @x unless $install;
1842                 }
1843             },
1844             qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
1845             => sub {
1846                 if (!@skip || $skip[$#skip] > 0) {
1847                     my $install = $1;
1848                     my @x = tokenize($2);
1849                     push @scripts, @x;
1850                     push @scripts_install, @x unless $install;
1851                 }
1852             },
1853             qr/^\s*EXTRA\s*=\s*(.*)\s*$/
1854             => sub { push @extra, tokenize($1)
1855                          if !@skip || $skip[$#skip] > 0 },
1856             qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
1857             => sub { push @overrides, tokenize($1)
1858                          if !@skip || $skip[$#skip] > 0 },
1859
1860             qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
1861             => sub { push @{$ordinals{$1}}, tokenize($2)
1862                          if !@skip || $skip[$#skip] > 0 },
1863             qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1864             => sub { push @{$sources{$1}}, tokenize($2)
1865                          if !@skip || $skip[$#skip] > 0 },
1866             qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1867             => sub { push @{$shared_sources{$1}}, tokenize($2)
1868                          if !@skip || $skip[$#skip] > 0 },
1869             qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1870             => sub { push @{$includes{$1}}, tokenize($2)
1871                          if !@skip || $skip[$#skip] > 0 },
1872             qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
1873             => sub { push @{$depends{$1}}, tokenize($2)
1874                          if !@skip || $skip[$#skip] > 0 },
1875             qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1876             => sub { push @{$generate{$1}}, $2
1877                          if !@skip || $skip[$#skip] > 0 },
1878             qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1879             => sub { push @{$renames{$1}}, tokenize($2)
1880                          if !@skip || $skip[$#skip] > 0 },
1881             qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
1882             => sub { push @{$sharednames{$1}}, tokenize($2)
1883                          if !@skip || $skip[$#skip] > 0 },
1884             qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
1885             => sub {
1886                 my $lineiterator = shift;
1887                 my $target_kind = $1;
1888                 while (defined $lineiterator->()) {
1889                     s|\R$||;
1890                     if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
1891                         die "ENDRAW doesn't match BEGINRAW"
1892                             if $1 ne $target_kind;
1893                         last;
1894                     }
1895                     next if @skip && $skip[$#skip] <= 0;
1896                     push @rawlines,  $_
1897                         if ($target_kind eq $target{build_file}
1898                             || $target_kind eq $target{build_file}."(".$builder_platform.")");
1899                 }
1900             },
1901             qr/^\s*(?:#.*)?$/ => sub { },
1902             "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
1903             "BEFORE" => sub {
1904                 if ($buildinfo_debug) {
1905                     print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
1906                     print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1907                 }
1908             },
1909             "AFTER" => sub {
1910                 if ($buildinfo_debug) {
1911                     print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
1912                 }
1913             },
1914             );
1915         die "runaway IF?" if (@skip);
1916
1917         foreach (keys %renames) {
1918             die "$_ renamed to more than one thing: "
1919                 ,join(" ", @{$renames{$_}}),"\n"
1920                 if scalar @{$renames{$_}} > 1;
1921             my $dest = cleanfile($buildd, $_, $blddir);
1922             my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
1923             die "$dest renamed to more than one thing: "
1924                 ,$unified_info{rename}->{$dest}, $to
1925                 unless !defined($unified_info{rename}->{$dest})
1926                 or $unified_info{rename}->{$dest} eq $to;
1927             $unified_info{rename}->{$dest} = $to;
1928         }
1929
1930         foreach (@programs) {
1931             my $program = cleanfile($buildd, $_, $blddir);
1932             if ($unified_info{rename}->{$program}) {
1933                 $program = $unified_info{rename}->{$program};
1934             }
1935             $unified_info{programs}->{$program} = 1;
1936         }
1937
1938         foreach (@programs_install) {
1939             my $program = cleanfile($buildd, $_, $blddir);
1940             if ($unified_info{rename}->{$program}) {
1941                 $program = $unified_info{rename}->{$program};
1942             }
1943             $unified_info{install}->{programs}->{$program} = 1;
1944         }
1945
1946         foreach (@libraries) {
1947             my $library = cleanfile($buildd, $_, $blddir);
1948             if ($unified_info{rename}->{$library}) {
1949                 $library = $unified_info{rename}->{$library};
1950             }
1951             $unified_info{libraries}->{$library} = 1;
1952         }
1953
1954         foreach (@libraries_install) {
1955             my $library = cleanfile($buildd, $_, $blddir);
1956             if ($unified_info{rename}->{$library}) {
1957                 $library = $unified_info{rename}->{$library};
1958             }
1959             $unified_info{install}->{libraries}->{$library} = 1;
1960         }
1961
1962         die <<"EOF" if scalar @engines and !$config{dynamic_engines};
1963 ENGINES can only be used if configured with 'dynamic-engine'.
1964 This is usually a fault in a build.info file.
1965 EOF
1966         foreach (@engines) {
1967             my $library = cleanfile($buildd, $_, $blddir);
1968             if ($unified_info{rename}->{$library}) {
1969                 $library = $unified_info{rename}->{$library};
1970             }
1971             $unified_info{engines}->{$library} = 1;
1972         }
1973
1974         foreach (@engines_install) {
1975             my $library = cleanfile($buildd, $_, $blddir);
1976             if ($unified_info{rename}->{$library}) {
1977                 $library = $unified_info{rename}->{$library};
1978             }
1979             $unified_info{install}->{engines}->{$library} = 1;
1980         }
1981
1982         foreach (@scripts) {
1983             my $script = cleanfile($buildd, $_, $blddir);
1984             if ($unified_info{rename}->{$script}) {
1985                 $script = $unified_info{rename}->{$script};
1986             }
1987             $unified_info{scripts}->{$script} = 1;
1988         }
1989
1990         foreach (@scripts_install) {
1991             my $script = cleanfile($buildd, $_, $blddir);
1992             if ($unified_info{rename}->{$script}) {
1993                 $script = $unified_info{rename}->{$script};
1994             }
1995             $unified_info{install}->{scripts}->{$script} = 1;
1996         }
1997
1998         foreach (@extra) {
1999             my $extra = cleanfile($buildd, $_, $blddir);
2000             $unified_info{extra}->{$extra} = 1;
2001         }
2002
2003         foreach (@overrides) {
2004             my $override = cleanfile($buildd, $_, $blddir);
2005             $unified_info{overrides}->{$override} = 1;
2006         }
2007
2008         push @{$unified_info{rawlines}}, @rawlines;
2009
2010         unless ($disabled{shared}) {
2011             # Check sharednames.
2012             foreach (keys %sharednames) {
2013                 my $dest = cleanfile($buildd, $_, $blddir);
2014                 if ($unified_info{rename}->{$dest}) {
2015                     $dest = $unified_info{rename}->{$dest};
2016                 }
2017                 die "shared_name for $dest with multiple values: "
2018                     ,join(" ", @{$sharednames{$_}}),"\n"
2019                     if scalar @{$sharednames{$_}} > 1;
2020                 my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
2021                 die "shared_name found for a library $dest that isn't defined\n"
2022                     unless $unified_info{libraries}->{$dest};
2023                 die "shared_name for $dest with multiple values: "
2024                     ,$unified_info{sharednames}->{$dest}, ", ", $to
2025                     unless !defined($unified_info{sharednames}->{$dest})
2026                     or $unified_info{sharednames}->{$dest} eq $to;
2027                 $unified_info{sharednames}->{$dest} = $to;
2028             }
2029
2030             # Additionally, we set up sharednames for libraries that don't
2031             # have any, as themselves.  Only for libraries that aren't
2032             # explicitly static.
2033             foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
2034                 if (!defined $unified_info{sharednames}->{$_}) {
2035                     $unified_info{sharednames}->{$_} = $_
2036                 }
2037             }
2038
2039             # Check that we haven't defined any library as both shared and
2040             # explicitly static.  That is forbidden.
2041             my @doubles = ();
2042             foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
2043                 (my $l = $_) =~ s/\.a$//;
2044                 push @doubles, $l if defined $unified_info{sharednames}->{$l};
2045             }
2046             die "these libraries are both explicitly static and shared:\n  ",
2047                 join(" ", @doubles), "\n"
2048                 if @doubles;
2049         }
2050
2051         foreach (keys %sources) {
2052             my $dest = $_;
2053             my $ddest = cleanfile($buildd, $_, $blddir);
2054             if ($unified_info{rename}->{$ddest}) {
2055                 $ddest = $unified_info{rename}->{$ddest};
2056             }
2057             foreach (@{$sources{$dest}}) {
2058                 my $s = cleanfile($sourced, $_, $blddir);
2059
2060                 # If it isn't in the source tree, we assume it's generated
2061                 # in the build tree
2062                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
2063                     $s = cleanfile($buildd, $_, $blddir);
2064                 }
2065                 # We recognise C++, C and asm files
2066                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
2067                     my $o = $_;
2068                     $o =~ s/\.[csS]$/.o/; # C and assembler
2069                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
2070                     $o = cleanfile($buildd, $o, $blddir);
2071                     $unified_info{sources}->{$ddest}->{$o} = 1;
2072                     $unified_info{sources}->{$o}->{$s} = 1;
2073                 } elsif ($s =~ /\.rc$/) {
2074                     # We also recognise resource files
2075                     my $o = $_;
2076                     $o =~ s/\.rc$/.res/; # Resource configuration
2077                     my $o = cleanfile($buildd, $o, $blddir);
2078                     $unified_info{sources}->{$ddest}->{$o} = 1;
2079                     $unified_info{sources}->{$o}->{$s} = 1;
2080                 } else {
2081                     $unified_info{sources}->{$ddest}->{$s} = 1;
2082                 }
2083             }
2084         }
2085
2086         foreach (keys %shared_sources) {
2087             my $dest = $_;
2088             my $ddest = cleanfile($buildd, $_, $blddir);
2089             if ($unified_info{rename}->{$ddest}) {
2090                 $ddest = $unified_info{rename}->{$ddest};
2091             }
2092             foreach (@{$shared_sources{$dest}}) {
2093                 my $s = cleanfile($sourced, $_, $blddir);
2094
2095                 # If it isn't in the source tree, we assume it's generated
2096                 # in the build tree
2097                 if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
2098                     $s = cleanfile($buildd, $_, $blddir);
2099                 }
2100
2101                 if ($s =~ /\.(cc|cpp|c|s|S)$/) {
2102                     # We recognise C++, C and asm files
2103                     my $o = $_;
2104                     $o =~ s/\.[csS]$/.o/; # C and assembler
2105                     $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
2106                     $o = cleanfile($buildd, $o, $blddir);
2107                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
2108                     $unified_info{sources}->{$o}->{$s} = 1;
2109                 } elsif ($s =~ /\.rc$/) {
2110                     # We also recognise resource files
2111                     my $o = $_;
2112                     $o =~ s/\.rc$/.res/; # Resource configuration
2113                     my $o = cleanfile($buildd, $o, $blddir);
2114                     $unified_info{shared_sources}->{$ddest}->{$o} = 1;
2115                     $unified_info{sources}->{$o}->{$s} = 1;
2116                 } elsif ($s =~ /\.(def|map|opt)$/) {
2117                     # We also recognise .def / .map / .opt files
2118                     # We know they are generated files
2119                     my $def = cleanfile($buildd, $s, $blddir);
2120                     $unified_info{shared_sources}->{$ddest}->{$def} = 1;
2121                 } else {
2122                     die "unrecognised source file type for shared library: $s\n";
2123                 }
2124             }
2125         }
2126
2127         foreach (keys %generate) {
2128             my $dest = $_;
2129             my $ddest = cleanfile($buildd, $_, $blddir);
2130             if ($unified_info{rename}->{$ddest}) {
2131                 $ddest = $unified_info{rename}->{$ddest};
2132             }
2133             die "more than one generator for $dest: "
2134                     ,join(" ", @{$generate{$_}}),"\n"
2135                     if scalar @{$generate{$_}} > 1;
2136             my @generator = split /\s+/, $generate{$dest}->[0];
2137             $generator[0] = cleanfile($sourced, $generator[0], $blddir),
2138             $unified_info{generate}->{$ddest} = [ @generator ];
2139         }
2140
2141         foreach (keys %depends) {
2142             my $dest = $_;
2143             my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
2144
2145             # If the destination doesn't exist in source, it can only be
2146             # a generated file in the build tree.
2147             if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) {
2148                 $ddest = cleanfile($buildd, $_, $blddir);
2149                 if ($unified_info{rename}->{$ddest}) {
2150                     $ddest = $unified_info{rename}->{$ddest};
2151                 }
2152             }
2153             foreach (@{$depends{$dest}}) {
2154                 my $d = cleanfile($sourced, $_, $blddir);
2155
2156                 # If we know it's generated, or assume it is because we can't
2157                 # find it in the source tree, we set file we depend on to be
2158                 # in the build tree rather than the source tree, and assume
2159                 # and that there are lines to build it in a BEGINRAW..ENDRAW
2160                 # section or in the Makefile template.
2161                 if ($d eq $src_configdata
2162                     || ! -f $d
2163                     || (grep { $d eq $_ }
2164                         map { cleanfile($srcdir, $_, $blddir) }
2165                         grep { /\.h$/ } keys %{$unified_info{generate}})) {
2166                     $d = cleanfile($buildd, $_, $blddir);
2167                 }
2168                 # Take note if the file to depend on is being renamed
2169                 # Take extra care with files ending with .a, they should
2170                 # be treated without that extension, and the extension
2171                 # should be added back after treatment.
2172                 $d =~ /(\.a)?$/;
2173                 my $e = $1 // "";
2174                 $d = $`;
2175                 if ($unified_info{rename}->{$d}) {
2176                     $d = $unified_info{rename}->{$d};
2177                 }
2178                 $d .= $e;
2179                 $unified_info{depends}->{$ddest}->{$d} = 1;
2180             }
2181         }
2182
2183         foreach (keys %includes) {
2184             my $dest = $_;
2185             my $ddest = cleanfile($sourced, $_, $blddir);
2186
2187             # If the destination doesn't exist in source, it can only be
2188             # a generated file in the build tree.
2189             if ($ddest eq $src_configdata || ! -f $ddest) {
2190                 $ddest = cleanfile($buildd, $_, $blddir);
2191                 if ($unified_info{rename}->{$ddest}) {
2192                     $ddest = $unified_info{rename}->{$ddest};
2193                 }
2194             }
2195             foreach (@{$includes{$dest}}) {
2196                 my $is = cleandir($sourced, $_, $blddir);
2197                 my $ib = cleandir($buildd, $_, $blddir);
2198                 push @{$unified_info{includes}->{$ddest}->{source}}, $is
2199                     unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
2200                 push @{$unified_info{includes}->{$ddest}->{build}}, $ib
2201                     unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
2202             }
2203         }
2204     }
2205
2206     my $ordinals_text = join(', ', sort keys %ordinals);
2207     warn <<"EOF" if $ordinals_text;
2208
2209 WARNING: ORDINALS were specified for $ordinals_text
2210 They are ignored and should be replaced with a combination of GENERATE,
2211 DEPEND and SHARED_SOURCE.
2212 EOF
2213
2214     # Massage the result
2215
2216     # If the user configured no-shared, we allow no shared sources
2217     if ($disabled{shared}) {
2218         foreach (keys %{$unified_info{shared_sources}}) {
2219             foreach (keys %{$unified_info{shared_sources}->{$_}}) {
2220                 delete $unified_info{sources}->{$_};
2221             }
2222         }
2223         $unified_info{shared_sources} = {};
2224     }
2225
2226     # If we depend on a header file or a perl module, add an inclusion of
2227     # its directory to allow smoothe inclusion
2228     foreach my $dest (keys %{$unified_info{depends}}) {
2229         next if $dest eq "";
2230         foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
2231             next unless $d =~ /\.(h|pm)$/;
2232             my $i = dirname($d);
2233             my $spot =
2234                 $d eq "configdata.pm" || defined($unified_info{generate}->{$d})
2235                 ? 'build' : 'source';
2236             push @{$unified_info{includes}->{$dest}->{$spot}}, $i
2237                 unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
2238         }
2239     }
2240
2241     # Trickle down includes placed on libraries, engines and programs to
2242     # their sources (i.e. object files)
2243     foreach my $dest (keys %{$unified_info{engines}},
2244                       keys %{$unified_info{libraries}},
2245                       keys %{$unified_info{programs}}) {
2246         foreach my $k (("source", "build")) {
2247             next unless defined($unified_info{includes}->{$dest}->{$k});
2248             my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
2249             foreach my $obj (grep /\.o$/,
2250                              (keys %{$unified_info{sources}->{$dest} // {}},
2251                               keys %{$unified_info{shared_sources}->{$dest} // {}})) {
2252                 foreach my $inc (@incs) {
2253                     unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
2254                         unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
2255                 }
2256             }
2257         }
2258         delete $unified_info{includes}->{$dest};
2259     }
2260
2261     ### Make unified_info a bit more efficient
2262     # One level structures
2263     foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
2264         $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
2265     }
2266     # Two level structures
2267     foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
2268         foreach my $l2 (sort keys %{$unified_info{$l1}}) {
2269             $unified_info{$l1}->{$l2} =
2270                 [ sort keys %{$unified_info{$l1}->{$l2}} ];
2271         }
2272     }
2273     # Includes
2274     foreach my $dest (sort keys %{$unified_info{includes}}) {
2275         if (defined($unified_info{includes}->{$dest}->{build})) {
2276             my @source_includes = ();
2277             @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
2278                 if defined($unified_info{includes}->{$dest}->{source});
2279             $unified_info{includes}->{$dest} =
2280                 [ @{$unified_info{includes}->{$dest}->{build}} ];
2281             foreach my $inc (@source_includes) {
2282                 push @{$unified_info{includes}->{$dest}}, $inc
2283                     unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
2284             }
2285         } else {
2286             $unified_info{includes}->{$dest} =
2287                 [ @{$unified_info{includes}->{$dest}->{source}} ];
2288         }
2289     }
2290
2291     # For convenience collect information regarding directories where
2292     # files are generated, those generated files and the end product
2293     # they end up in where applicable.  Then, add build rules for those
2294     # directories
2295     my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
2296                      "dso" => [ @{$unified_info{engines}} ],
2297                      "bin" => [ @{$unified_info{programs}} ],
2298                      "script" => [ @{$unified_info{scripts}} ] );
2299     foreach my $type (keys %loopinfo) {
2300         foreach my $product (@{$loopinfo{$type}}) {
2301             my %dirs = ();
2302             my $pd = dirname($product);
2303
2304             foreach (@{$unified_info{sources}->{$product} // []},
2305                      @{$unified_info{shared_sources}->{$product} // []}) {
2306                 my $d = dirname($_);
2307
2308                 # We don't want to create targets for source directories
2309                 # when building out of source
2310                 next if ($config{sourcedir} ne $config{builddir}
2311                              && $d =~ m|^\Q$config{sourcedir}\E|);
2312                 # We already have a "test" target, and the current directory
2313                 # is just silly to make a target for
2314                 next if $d eq "test" || $d eq ".";
2315
2316                 $dirs{$d} = 1;
2317                 push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
2318                     if $d ne $pd;
2319             }
2320             foreach (keys %dirs) {
2321                 push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
2322                     $product;
2323             }
2324         }
2325     }
2326 }
2327
2328 # For the schemes that need it, we provide the old *_obj configs
2329 # from the *_asm_obj ones
2330 foreach (grep /_(asm|aux)_src$/, keys %target) {
2331     my $src = $_;
2332     (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
2333     $target{$obj} = $target{$src};
2334     $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
2335     $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
2336 }
2337
2338 # Write down our configuration where it fits #########################
2339
2340 print "Creating configdata.pm\n";
2341 open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
2342 print OUT <<"EOF";
2343 #! $config{HASHBANGPERL}
2344
2345 package configdata;
2346
2347 use strict;
2348 use warnings;
2349
2350 use Exporter;
2351 #use vars qw(\@ISA \@EXPORT);
2352 our \@ISA = qw(Exporter);
2353 our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
2354
2355 EOF
2356 print OUT "our %config = (\n";
2357 foreach (sort keys %config) {
2358     if (ref($config{$_}) eq "ARRAY") {
2359         print OUT "  ", $_, " => [ ", join(", ",
2360                                            map { quotify("perl", $_) }
2361                                            @{$config{$_}}), " ],\n";
2362     } elsif (ref($config{$_}) eq "HASH") {
2363         print OUT "  ", $_, " => {";
2364         if (scalar keys %{$config{$_}} > 0) {
2365             print OUT "\n";
2366             foreach my $key (sort keys %{$config{$_}}) {
2367                 print OUT "      ",
2368                     join(" => ",
2369                          quotify("perl", $key),
2370                          defined $config{$_}->{$key}
2371                              ? quotify("perl", $config{$_}->{$key})
2372                              : "undef");
2373                 print OUT ",\n";
2374             }
2375             print OUT "  ";
2376         }
2377         print OUT "},\n";
2378     } else {
2379         print OUT "  ", $_, " => ", quotify("perl", $config{$_}), ",\n"
2380     }
2381 }
2382 print OUT <<"EOF";
2383 );
2384
2385 EOF
2386 print OUT "our %target = (\n";
2387 foreach (sort keys %target) {
2388     if (ref($target{$_}) eq "ARRAY") {
2389         print OUT "  ", $_, " => [ ", join(", ",
2390                                            map { quotify("perl", $_) }
2391                                            @{$target{$_}}), " ],\n";
2392     } else {
2393         print OUT "  ", $_, " => ", quotify("perl", $target{$_}), ",\n"
2394     }
2395 }
2396 print OUT <<"EOF";
2397 );
2398
2399 EOF
2400 print OUT "our \%available_protocols = (\n";
2401 print OUT "  tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
2402 print OUT "  dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
2403 print OUT <<"EOF";
2404 );
2405
2406 EOF
2407 print OUT "our \@disablables = (\n";
2408 foreach (@disablables) {
2409     print OUT "  ", quotify("perl", $_), ",\n";
2410 }
2411 print OUT <<"EOF";
2412 );
2413
2414 EOF
2415 print OUT "our \%disabled = (\n";
2416 foreach (sort keys %disabled) {
2417     print OUT "  ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
2418 }
2419 print OUT <<"EOF";
2420 );
2421
2422 EOF
2423 print OUT "our %withargs = (\n";
2424 foreach (sort keys %withargs) {
2425     if (ref($withargs{$_}) eq "ARRAY") {
2426         print OUT "  ", $_, " => [ ", join(", ",
2427                                            map { quotify("perl", $_) }
2428                                            @{$withargs{$_}}), " ],\n";
2429     } else {
2430         print OUT "  ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
2431     }
2432 }
2433 print OUT <<"EOF";
2434 );
2435
2436 EOF
2437 if ($builder eq "unified") {
2438     my $recurse;
2439     $recurse = sub {
2440         my $indent = shift;
2441         foreach (@_) {
2442             if (ref $_ eq "ARRAY") {
2443                 print OUT " "x$indent, "[\n";
2444                 foreach (@$_) {
2445                     $recurse->($indent + 4, $_);
2446                 }
2447                 print OUT " "x$indent, "],\n";
2448             } elsif (ref $_ eq "HASH") {
2449                 my %h = %$_;
2450                 print OUT " "x$indent, "{\n";
2451                 foreach (sort keys %h) {
2452                     if (ref $h{$_} eq "") {
2453                         print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
2454                     } else {
2455                         print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
2456                         $recurse->($indent + 8, $h{$_});
2457                     }
2458                 }
2459                 print OUT " "x$indent, "},\n";
2460             } else {
2461                 print OUT " "x$indent, quotify("perl", $_), ",\n";
2462             }
2463         }
2464     };
2465     print OUT "our %unified_info = (\n";
2466     foreach (sort keys %unified_info) {
2467         if (ref $unified_info{$_} eq "") {
2468             print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
2469         } else {
2470             print OUT " "x4, quotify("perl", $_), " =>\n";
2471             $recurse->(8, $unified_info{$_});
2472         }
2473     }
2474     print OUT <<"EOF";
2475 );
2476
2477 EOF
2478 }
2479 print OUT
2480     "# The following data is only used when this files is use as a script\n";
2481 print OUT "my \@makevars = (\n";
2482 foreach (sort keys %user) {
2483     print OUT "    '",$_,"',\n";
2484 }
2485 print OUT ");\n";
2486 print OUT "my \%disabled_info = (\n";
2487 foreach my $what (sort keys %disabled_info) {
2488     print OUT "    '$what' => {\n";
2489     foreach my $info (sort keys %{$disabled_info{$what}}) {
2490         if (ref $disabled_info{$what}->{$info} eq 'ARRAY') {
2491             print OUT "        $info => [ ",
2492                 join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}),
2493                 " ],\n";
2494         } else {
2495             print OUT "        $info => '", $disabled_info{$what}->{$info},
2496                 "',\n";
2497         }
2498     }
2499     print OUT "    },\n";
2500 }
2501 print OUT ");\n";
2502 print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n";
2503 print OUT << 'EOF';
2504 # If run directly, we can give some answers, and even reconfigure
2505 unless (caller) {
2506     use Getopt::Long;
2507     use File::Spec::Functions;
2508     use File::Basename;
2509     use Pod::Usage;
2510
2511     my $here = dirname($0);
2512
2513     my $dump = undef;
2514     my $cmdline = undef;
2515     my $options = undef;
2516     my $target = undef;
2517     my $envvars = undef;
2518     my $makevars = undef;
2519     my $buildparams = undef;
2520     my $reconf = undef;
2521     my $verbose = undef;
2522     my $help = undef;
2523     my $man = undef;
2524     GetOptions('dump|d'                 => \$dump,
2525                'command-line|c'         => \$cmdline,
2526                'options|o'              => \$options,
2527                'target|t'               => \$target,
2528                'environment|e'          => \$envvars,
2529                'make-variables|m'       => \$makevars,
2530                'build-parameters|b'     => \$buildparams,
2531                'reconfigure|reconf|r'   => \$reconf,
2532                'verbose|v'              => \$verbose,
2533                'help'                   => \$help,
2534                'man'                    => \$man)
2535         or die "Errors in command line arguments\n";
2536
2537     unless ($dump || $cmdline || $options || $target || $envvars || $makevars
2538             || $buildparams || $reconf || $verbose || $help || $man) {
2539         print STDERR <<"_____";
2540 You must give at least one option.
2541 For more information, do '$0 --help'
2542 _____
2543         exit(2);
2544     }
2545
2546     if ($help) {
2547         pod2usage(-exitval => 0,
2548                   -verbose => 1);
2549     }
2550     if ($man) {
2551         pod2usage(-exitval => 0,
2552                   -verbose => 2);
2553     }
2554     if ($dump || $cmdline) {
2555         print "\nCommand line (with current working directory = $here):\n\n";
2556         print '    ',join(' ',
2557                           $config{PERL},
2558                           catfile($config{sourcedir}, 'Configure'),
2559                           @{$config{perlargv}}), "\n";
2560         print "\nPerl information:\n\n";
2561         print '    ',$config{perl_cmd},"\n";
2562         print '    ',$config{perl_version},' for ',$config{perl_archname},"\n";
2563     }
2564     if ($dump || $options) {
2565         my $longest = 0;
2566         my $longest2 = 0;
2567         foreach my $what (@disablables) {
2568             $longest = length($what) if $longest < length($what);
2569             $longest2 = length($disabled{$what})
2570                 if $disabled{$what} && $longest2 < length($disabled{$what});
2571         }
2572         print "\nEnabled features:\n\n";
2573         foreach my $what (@disablables) {
2574             print "    $what\n" unless $disabled{$what};
2575         }
2576         print "\nDisabled features:\n\n";
2577         foreach my $what (@disablables) {
2578             if ($disabled{$what}) {
2579                 print "    $what", ' ' x ($longest - length($what) + 1),
2580                     "[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1);
2581                 print $disabled_info{$what}->{macro}
2582                     if $disabled_info{$what}->{macro};
2583                 print ' (skip ',
2584                     join(', ', @{$disabled_info{$what}->{skipped}}),
2585                     ')'
2586                     if $disabled_info{$what}->{skipped};
2587                 print "\n";
2588             }
2589         }
2590     }
2591     if ($dump || $target) {
2592         print "\nConfig target attributes:\n\n";
2593         foreach (sort keys %target) {
2594             next if $_ =~ m|^_| || $_ eq 'template';
2595             my $quotify = sub {
2596                 map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
2597             };
2598             print '    ', $_, ' => ';
2599             if (ref($target{$_}) eq "ARRAY") {
2600                 print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
2601             } else {
2602                 print $quotify->($target{$_}), ",\n"
2603             }
2604         }
2605     }
2606     if ($dump || $envvars) {
2607         print "\nRecorded environment:\n\n";
2608         foreach (sort keys %{$config{perlenv}}) {
2609             print '    ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
2610         }
2611     }
2612     if ($dump || $makevars) {
2613         print "\nMakevars:\n\n";
2614         foreach my $var (@makevars) {
2615             my $prefix = '';
2616             $prefix = $config{CROSS_COMPILE}
2617                 if grep { $var eq $_ } @user_crossable;
2618             $prefix //= '';
2619             print '    ',$var,' ' x (16 - length $var),'= ',
2620                 (ref $config{$var} eq 'ARRAY'
2621                  ? join(' ', @{$config{$var}})
2622                  : $prefix.$config{$var}),
2623                 "\n"
2624                 if defined $config{$var};
2625         }
2626
2627         my @buildfile = ($config{builddir}, $config{build_file});
2628         unshift @buildfile, $here
2629             unless file_name_is_absolute($config{builddir});
2630         my $buildfile = canonpath(catdir(@buildfile));
2631         print <<"_____";
2632
2633 NOTE: These variables only represent the configuration view.  The build file
2634 template may have processed these variables further, please have a look at the
2635 build file for more exact data:
2636     $buildfile
2637 _____
2638     }
2639     if ($dump || $buildparams) {
2640         my @buildfile = ($config{builddir}, $config{build_file});
2641         unshift @buildfile, $here
2642             unless file_name_is_absolute($config{builddir});
2643         print "\nbuild file:\n\n";
2644         print "    ", canonpath(catfile(@buildfile)),"\n";
2645
2646         print "\nbuild file templates:\n\n";
2647         foreach (@{$config{build_file_templates}}) {
2648             my @tmpl = ($_);
2649             unshift @tmpl, $here
2650                 unless file_name_is_absolute($config{sourcedir});
2651             print '    ',canonpath(catfile(@tmpl)),"\n";
2652         }
2653     }
2654     if ($reconf) {
2655         if ($verbose) {
2656             print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
2657             foreach (sort keys %{$config{perlenv}}) {
2658                 print '    ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
2659             }
2660         }
2661
2662         chdir $here;
2663         exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
2664     }
2665 }
2666
2667 1;
2668
2669 __END__
2670
2671 =head1 NAME
2672
2673 configdata.pm - configuration data for OpenSSL builds
2674
2675 =head1 SYNOPSIS
2676
2677 Interactive:
2678
2679   perl configdata.pm [options]
2680
2681 As data bank module:
2682
2683   use configdata;
2684
2685 =head1 DESCRIPTION
2686
2687 This module can be used in two modes, interactively and as a module containing
2688 all the data recorded by OpenSSL's Configure script.
2689
2690 When used interactively, simply run it as any perl script, with at least one
2691 option, and you will get the information you ask for.  See L</OPTIONS> below.
2692
2693 When loaded as a module, you get a few databanks with useful information to
2694 perform build related tasks.  The databanks are:
2695
2696     %config             Configured things.
2697     %target             The OpenSSL config target with all inheritances
2698                         resolved.
2699     %disabled           The features that are disabled.
2700     @disablables        The list of features that can be disabled.
2701     %withargs           All data given through --with-THING options.
2702     %unified_info       All information that was computed from the build.info
2703                         files.
2704
2705 =head1 OPTIONS
2706
2707 =over 4
2708
2709 =item B<--help>
2710
2711 Print a brief help message and exit.
2712
2713 =item B<--man>
2714
2715 Print the manual page and exit.
2716
2717 =item B<--dump> | B<-d>
2718
2719 Print all relevant configuration data.  This is equivalent to B<--command-line>
2720 B<--options> B<--target> B<--environment> B<--make-variables>
2721 B<--build-parameters>.
2722
2723 =item B<--command-line> | B<-c>
2724
2725 Print the current configuration command line.
2726
2727 =item B<--options> | B<-o>
2728
2729 Print the features, both enabled and disabled, and display defined macro and
2730 skipped directories where applicable.
2731
2732 =item B<--target> | B<-t>
2733
2734 Print the config attributes for this config target.
2735
2736 =item B<--environment> | B<-e>
2737
2738 Print the environment variables and their values at the time of configuration.
2739
2740 =item B<--make-variables> | B<-m>
2741
2742 Print the main make variables generated in the current configuration
2743
2744 =item B<--build-parameters> | B<-b>
2745
2746 Print the build parameters, i.e. build file and build file templates.
2747
2748 =item B<--reconfigure> | B<--reconf> | B<-r>
2749
2750 Redo the configuration.
2751
2752 =item B<--verbose> | B<-v>
2753
2754 Verbose output.
2755
2756 =back
2757
2758 =cut
2759
2760 EOF
2761 close(OUT);
2762 if ($builder_platform eq 'unix') {
2763     my $mode = (0755 & ~umask);
2764     chmod $mode, 'configdata.pm'
2765         or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
2766 }
2767
2768 my %builders = (
2769     unified => sub {
2770         print 'Creating ',$target{build_file},"\n";
2771         run_dofile(catfile($blddir, $target{build_file}),
2772                    @{$config{build_file_templates}});
2773     },
2774     );
2775
2776 $builders{$builder}->($builder_platform, @builder_opts);
2777
2778 $SIG{__DIE__} = $orig_death_handler;
2779
2780 print <<"EOF" if ($disabled{threads} eq "unavailable");
2781
2782 The library could not be configured for supporting multi-threaded
2783 applications as the compiler options required on this system are not known.
2784 See file INSTALL for details if you need multi-threading.
2785 EOF
2786
2787 print <<"EOF" if ($no_shared_warn);
2788
2789 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2790 platform, so we will pretend you gave the option 'no-pic', which also disables
2791 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2792 or position independent code, please let us know (but please first make sure
2793 you have tried with a current version of OpenSSL).
2794 EOF
2795
2796 print <<"EOF";
2797
2798 **********************************************************************
2799 ***                                                                ***
2800 ***   OpenSSL has been successfully configured                     ***
2801 ***                                                                ***
2802 ***   If you encounter a problem while building, please open an    ***
2803 ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
2804 ***   and include the output from the following command:           ***
2805 ***                                                                ***
2806 ***       perl configdata.pm --dump                                ***
2807 ***                                                                ***
2808 ***   (If you are new to OpenSSL, you might want to consult the    ***
2809 ***   'Troubleshooting' section in the INSTALL file first)         ***
2810 ***                                                                ***
2811 **********************************************************************
2812 EOF
2813
2814 exit(0);
2815
2816 ######################################################################
2817 #
2818 # Helpers and utility functions
2819 #
2820
2821 # Death handler, to print a helpful message in case of failure #######
2822 #
2823 sub death_handler {
2824     die @_ if $^S;              # To prevent the added message in eval blocks
2825     my $build_file = $target{build_file} // "build file";
2826     my @message = ( <<"_____", @_ );
2827
2828 Failure!  $build_file wasn't produced.
2829 Please read INSTALL and associated NOTES files.  You may also have to look over
2830 your available compiler tool chain or change your configuration.
2831
2832 _____
2833
2834     # Dying is terminal, so it's ok to reset the signal handler here.
2835     $SIG{__DIE__} = $orig_death_handler;
2836     die @message;
2837 }
2838
2839 # Configuration file reading #########################################
2840
2841 # Note: All of the helper functions are for lazy evaluation.  They all
2842 # return a CODE ref, which will return the intended value when evaluated.
2843 # Thus, whenever there's mention of a returned value, it's about that
2844 # intended value.
2845
2846 # Helper function to implement conditional inheritance depending on the
2847 # value of $disabled{asm}.  Used in inherit_from values as follows:
2848 #
2849 #      inherit_from => [ "template", asm("asm_tmpl") ]
2850 #
2851 sub asm {
2852     my @x = @_;
2853     sub {
2854         $disabled{asm} ? () : @x;
2855     }
2856 }
2857
2858 # Helper function to implement conditional value variants, with a default
2859 # plus additional values based on the value of $config{build_type}.
2860 # Arguments are given in hash table form:
2861 #
2862 #       picker(default => "Basic string: ",
2863 #              debug   => "debug",
2864 #              release => "release")
2865 #
2866 # When configuring with --debug, the resulting string will be
2867 # "Basic string: debug", and when not, it will be "Basic string: release"
2868 #
2869 # This can be used to create variants of sets of flags according to the
2870 # build type:
2871 #
2872 #       cflags => picker(default => "-Wall",
2873 #                        debug   => "-g -O0",
2874 #                        release => "-O3")
2875 #
2876 sub picker {
2877     my %opts = @_;
2878     return sub { add($opts{default} || (),
2879                      $opts{$config{build_type}} || ())->(); }
2880 }
2881
2882 # Helper function to combine several values of different types into one.
2883 # This is useful if you want to combine a string with the result of a
2884 # lazy function, such as:
2885 #
2886 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2887 #
2888 sub combine {
2889     my @stuff = @_;
2890     return sub { add(@stuff)->(); }
2891 }
2892
2893 # Helper function to implement conditional values depending on the value
2894 # of $disabled{threads}.  Can be used as follows:
2895 #
2896 #       cflags => combine("-Wall", threads("-pthread"))
2897 #
2898 sub threads {
2899     my @flags = @_;
2900     return sub { add($disabled{threads} ? () : @flags)->(); }
2901 }
2902
2903 sub shared {
2904     my @flags = @_;
2905     return sub { add($disabled{shared} ? () : @flags)->(); }
2906 }
2907
2908 our $add_called = 0;
2909 # Helper function to implement adding values to already existing configuration
2910 # values.  It handles elements that are ARRAYs, CODEs and scalars
2911 sub _add {
2912     my $separator = shift;
2913
2914     # If there's any ARRAY in the collection of values OR the separator
2915     # is undef, we will return an ARRAY of combined values, otherwise a
2916     # string of joined values with $separator as the separator.
2917     my $found_array = !defined($separator);
2918
2919     my @values =
2920         map {
2921             my $res = $_;
2922             while (ref($res) eq "CODE") {
2923                 $res = $res->();
2924             }
2925             if (defined($res)) {
2926                 if (ref($res) eq "ARRAY") {
2927                     $found_array = 1;
2928                     @$res;
2929                 } else {
2930                     $res;
2931                 }
2932             } else {
2933                 ();
2934             }
2935     } (@_);
2936
2937     $add_called = 1;
2938
2939     if ($found_array) {
2940         [ @values ];
2941     } else {
2942         join($separator, grep { defined($_) && $_ ne "" } @values);
2943     }
2944 }
2945 sub add_before {
2946     my $separator = " ";
2947     if (ref($_[$#_]) eq "HASH") {
2948         my $opts = pop;
2949         $separator = $opts->{separator};
2950     }
2951     my @x = @_;
2952     sub { _add($separator, @x, @_) };
2953 }
2954 sub add {
2955     my $separator = " ";
2956     if (ref($_[$#_]) eq "HASH") {
2957         my $opts = pop;
2958         $separator = $opts->{separator};
2959     }
2960     my @x = @_;
2961     sub { _add($separator, @_, @x) };
2962 }
2963
2964 sub read_eval_file {
2965     my $fname = shift;
2966     my $content;
2967     my @result;
2968
2969     open F, "< $fname" or die "Can't open '$fname': $!\n";
2970     {
2971         undef local $/;
2972         $content = <F>;
2973     }
2974     close F;
2975     {
2976         local $@;
2977
2978         @result = ( eval $content );
2979         warn $@ if $@;
2980     }
2981     return wantarray ? @result : $result[0];
2982 }
2983
2984 # configuration reader, evaluates the input file as a perl script and expects
2985 # it to fill %targets with target configurations.  Those are then added to
2986 # %table.
2987 sub read_config {
2988     my $fname = shift;
2989     my %targets;
2990
2991     {
2992         # Protect certain tables from tampering
2993         local %table = ();
2994
2995         %targets = read_eval_file($fname);
2996     }
2997     my %preexisting = ();
2998     foreach (sort keys %targets) {
2999         $preexisting{$_} = 1 if $table{$_};
3000     }
3001     die <<"EOF",
3002 The following config targets from $fname
3003 shadow pre-existing config targets with the same name:
3004 EOF
3005         map { "  $_\n" } sort keys %preexisting
3006         if %preexisting;
3007
3008
3009     # For each target, check that it's configured with a hash table.
3010     foreach (keys %targets) {
3011         if (ref($targets{$_}) ne "HASH") {
3012             if (ref($targets{$_}) eq "") {
3013                 warn "Deprecated target configuration for $_, ignoring...\n";
3014             } else {
3015                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
3016             }
3017             delete $targets{$_};
3018         } else {
3019             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
3020         }
3021     }
3022
3023     %table = (%table, %targets);
3024
3025 }
3026
3027 # configuration resolver.  Will only resolve all the lazy evaluation
3028 # codeblocks for the chosen target and all those it inherits from,
3029 # recursively
3030 sub resolve_config {
3031     my $target = shift;
3032     my @breadcrumbs = @_;
3033
3034 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
3035
3036     if (grep { $_ eq $target } @breadcrumbs) {
3037         die "inherit_from loop!  target backtrace:\n  "
3038             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
3039     }
3040
3041     if (!defined($table{$target})) {
3042         warn "Warning! target $target doesn't exist!\n";
3043         return ();
3044     }
3045     # Recurse through all inheritances.  They will be resolved on the
3046     # fly, so when this operation is done, they will all just be a
3047     # bunch of attributes with string values.
3048     # What we get here, though, are keys with references to lists of
3049     # the combined values of them all.  We will deal with lists after
3050     # this stage is done.
3051     my %combined_inheritance = ();
3052     if ($table{$target}->{inherit_from}) {
3053         my @inherit_from =
3054             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
3055         foreach (@inherit_from) {
3056             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
3057
3058             # 'template' is a marker that's considered private to
3059             # the config that had it.
3060             delete $inherited_config{template};
3061
3062             foreach (keys %inherited_config) {
3063                 if (!$combined_inheritance{$_}) {
3064                     $combined_inheritance{$_} = [];
3065                 }
3066                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
3067             }
3068         }
3069     }
3070
3071     # We won't need inherit_from in this target any more, since we've
3072     # resolved all the inheritances that lead to this
3073     delete $table{$target}->{inherit_from};
3074
3075     # Now is the time to deal with those lists.  Here's the place to
3076     # decide what shall be done with those lists, all based on the
3077     # values of the target we're currently dealing with.
3078     # - If a value is a coderef, it will be executed with the list of
3079     #   inherited values as arguments.
3080     # - If the corresponding key doesn't have a value at all or is the
3081     #   empty string, the inherited value list will be run through the
3082     #   default combiner (below), and the result becomes this target's
3083     #   value.
3084     # - Otherwise, this target's value is assumed to be a string that
3085     #   will simply override the inherited list of values.
3086     my $default_combiner = add();
3087
3088     my %all_keys =
3089         map { $_ => 1 } (keys %combined_inheritance,
3090                          keys %{$table{$target}});
3091
3092     sub process_values {
3093         my $object    = shift;
3094         my $inherited = shift;  # Always a [ list ]
3095         my $target    = shift;
3096         my $entry     = shift;
3097
3098         $add_called = 0;
3099
3100         while(ref($object) eq "CODE") {
3101             $object = $object->(@$inherited);
3102         }
3103         if (!defined($object)) {
3104             return ();
3105         }
3106         elsif (ref($object) eq "ARRAY") {
3107             local $add_called;  # To make sure recursive calls don't affect it
3108             return [ map { process_values($_, $inherited, $target, $entry) }
3109                      @$object ];
3110         } elsif (ref($object) eq "") {
3111             return $object;
3112         } else {
3113             die "cannot handle reference type ",ref($object)
3114                 ," found in target ",$target," -> ",$entry,"\n";
3115         }
3116     }
3117
3118     foreach (sort keys %all_keys) {
3119         my $previous = $combined_inheritance{$_};
3120
3121         # Current target doesn't have a value for the current key?
3122         # Assign it the default combiner, the rest of this loop body
3123         # will handle it just like any other coderef.
3124         if (!exists $table{$target}->{$_}) {
3125             $table{$target}->{$_} = $default_combiner;
3126         }
3127
3128         $table{$target}->{$_} = process_values($table{$target}->{$_},
3129                                                $combined_inheritance{$_},
3130                                                $target, $_);
3131         unless(defined($table{$target}->{$_})) {
3132             delete $table{$target}->{$_};
3133         }
3134 #        if ($extra_checks &&
3135 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
3136 #            warn "$_ got replaced in $target\n";
3137 #        }
3138     }
3139
3140     # Finally done, return the result.
3141     return %{$table{$target}};
3142 }
3143
3144 sub usage
3145         {
3146         print STDERR $usage;
3147         print STDERR "\npick os/compiler from:\n";
3148         my $j=0;
3149         my $i;
3150         my $k=0;
3151         foreach $i (sort keys %table)
3152                 {
3153                 next if $table{$i}->{template};
3154                 next if $i =~ /^debug/;
3155                 $k += length($i) + 1;
3156                 if ($k > 78)
3157                         {
3158                         print STDERR "\n";
3159                         $k=length($i);
3160                         }
3161                 print STDERR $i . " ";
3162                 }
3163         foreach $i (sort keys %table)
3164                 {
3165                 next if $table{$i}->{template};
3166                 next if $i !~ /^debug/;
3167                 $k += length($i) + 1;
3168                 if ($k > 78)
3169                         {
3170                         print STDERR "\n";
3171                         $k=length($i);
3172                         }
3173                 print STDERR $i . " ";
3174                 }
3175         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
3176         exit(1);
3177         }
3178
3179 sub run_dofile
3180 {
3181     my $out = shift;
3182     my @templates = @_;
3183
3184     unlink $out || warn "Can't remove $out, $!"
3185         if -f $out;
3186     foreach (@templates) {
3187         die "Can't open $_, $!" unless -f $_;
3188     }
3189     my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
3190     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
3191     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
3192     system($cmd);
3193     exit 1 if $? != 0;
3194     rename("$out.new", $out) || die "Can't rename $out.new, $!";
3195 }
3196
3197 sub compiler_predefined {
3198     state %predefined;
3199     my $cc = shift;
3200
3201     return () if $^O eq 'VMS';
3202
3203     die 'compiler_predefined called without a compiler command'
3204         unless $cc;
3205
3206     if (! $predefined{$cc}) {
3207
3208         $predefined{$cc} = {};
3209
3210         # collect compiler pre-defines from gcc or gcc-alike...
3211         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3212         while (my $l = <PIPE>) {
3213             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3214             $predefined{$cc}->{$1} = $2 // '';
3215         }
3216         close(PIPE);
3217     }
3218
3219     return %{$predefined{$cc}};
3220 }
3221
3222 sub which
3223 {
3224     my ($name)=@_;
3225
3226     if (eval { require IPC::Cmd; 1; }) {
3227         IPC::Cmd->import();
3228         return scalar IPC::Cmd::can_run($name);
3229     } else {
3230         # if there is $directories component in splitpath,
3231         # then it's not something to test with $PATH...
3232         return $name if (File::Spec->splitpath($name))[1];
3233
3234         foreach (File::Spec->path()) {
3235             my $fullpath = catfile($_, "$name$target{exe_extension}");
3236             if (-f $fullpath and -x $fullpath) {
3237                 return $fullpath;
3238             }
3239         }
3240     }
3241 }
3242
3243 sub env
3244 {
3245     my $name = shift;
3246     my %opts = @_;
3247
3248     unless ($opts{cacheonly}) {
3249         # Note that if $ENV{$name} doesn't exist or is undefined,
3250         # $config{perlenv}->{$name} will be created with the value
3251         # undef.  This is intentional.
3252
3253         $config{perlenv}->{$name} = $ENV{$name}
3254             if ! exists $config{perlenv}->{$name};
3255     }
3256     return $config{perlenv}->{$name};
3257 }
3258
3259 # Configuration printer ##############################################
3260
3261 sub print_table_entry
3262 {
3263     local $now_printing = shift;
3264     my %target = resolve_config($now_printing);
3265     my $type = shift;
3266
3267     # Don't print the templates
3268     return if $target{template};
3269
3270     my @sequence = (
3271         "sys_id",
3272         "cpp",
3273         "cppflags",
3274         "defines",
3275         "includes",
3276         "cc",
3277         "cflags",
3278         "unistd",
3279         "ld",
3280         "lflags",
3281         "loutflag",
3282         "ex_libs",
3283         "bn_ops",
3284         "apps_aux_src",
3285         "cpuid_asm_src",
3286         "uplink_aux_src",
3287         "bn_asm_src",
3288         "ec_asm_src",
3289         "des_asm_src",
3290         "aes_asm_src",
3291         "bf_asm_src",
3292         "md5_asm_src",
3293         "cast_asm_src",
3294         "sha1_asm_src",
3295         "rc4_asm_src",
3296         "rmd160_asm_src",
3297         "rc5_asm_src",
3298         "wp_asm_src",
3299         "cmll_asm_src",
3300         "modes_asm_src",
3301         "padlock_asm_src",
3302         "chacha_asm_src",
3303         "poly1035_asm_src",
3304         "thread_scheme",
3305         "perlasm_scheme",
3306         "dso_scheme",
3307         "shared_target",
3308         "shared_cflag",
3309         "shared_defines",
3310         "shared_ldflag",
3311         "shared_rcflag",
3312         "shared_extension",
3313         "dso_extension",
3314         "obj_extension",
3315         "exe_extension",
3316         "ranlib",
3317         "ar",
3318         "arflags",
3319         "aroutflag",
3320         "rc",
3321         "rcflags",
3322         "rcoutflag",
3323         "mt",
3324         "mtflags",
3325         "mtinflag",
3326         "mtoutflag",
3327         "multilib",
3328         "build_scheme",
3329         );
3330
3331     if ($type eq "TABLE") {
3332         print "\n";
3333         print "*** $now_printing\n";
3334         foreach (@sequence) {
3335             if (ref($target{$_}) eq "ARRAY") {
3336                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
3337             } else {
3338                 printf "\$%-12s = %s\n", $_, $target{$_};
3339             }
3340         }
3341     } elsif ($type eq "HASH") {
3342         my $largest =
3343             length((sort { length($a) <=> length($b) } @sequence)[-1]);
3344         print "    '$now_printing' => {\n";
3345         foreach (@sequence) {
3346             if ($target{$_}) {
3347                 if (ref($target{$_}) eq "ARRAY") {
3348                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
3349                 } else {
3350                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
3351                 }
3352             }
3353         }
3354         print "    },\n";
3355     }
3356 }
3357
3358 # Utility routines ###################################################
3359
3360 # On VMS, if the given file is a logical name, File::Spec::Functions
3361 # will consider it an absolute path.  There are cases when we want a
3362 # purely syntactic check without checking the environment.
3363 sub isabsolute {
3364     my $file = shift;
3365
3366     # On non-platforms, we just use file_name_is_absolute().
3367     return file_name_is_absolute($file) unless $^O eq "VMS";
3368
3369     # If the file spec includes a device or a directory spec,
3370     # file_name_is_absolute() is perfectly safe.
3371     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
3372
3373     # Here, we know the given file spec isn't absolute
3374     return 0;
3375 }
3376
3377 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
3378 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
3379 # realpath() requires that at least all path components except the last is an
3380 # existing directory.  On VMS, the last component of the directory spec must
3381 # exist.
3382 sub absolutedir {
3383     my $dir = shift;
3384
3385     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
3386     # will return the volume name for the device, no matter what.  Also,
3387     # it will return an incorrect directory spec if the argument is a
3388     # directory that doesn't exist.
3389     if ($^O eq "VMS") {
3390         return rel2abs($dir);
3391     }
3392
3393     # We use realpath() on Unix, since no other will properly clean out
3394     # a directory spec.
3395     use Cwd qw/realpath/;
3396
3397     return realpath($dir);
3398 }
3399
3400 sub quotify {
3401     my %processors = (
3402         perl    => sub { my $x = shift;
3403                          $x =~ s/([\\\$\@"])/\\$1/g;
3404                          return '"'.$x.'"'; },
3405         maybeshell => sub { my $x = shift;
3406                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
3407                             if ($x ne $y || $x =~ m|\s|) {
3408                                 return '"'.$y.'"';
3409                             } else {
3410                                 return $x;
3411                             }
3412                         },
3413         );
3414     my $for = shift;
3415     my $processor =
3416         defined($processors{$for}) ? $processors{$for} : sub { shift; };
3417
3418     return map { $processor->($_); } @_;
3419 }
3420
3421 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
3422 # $filename is a file name to read from
3423 # $line_concat_cond_re is a regexp detecting a line continuation ending
3424 # $line_concat is a CODEref that takes care of concatenating two lines
3425 sub collect_from_file {
3426     my $filename = shift;
3427     my $line_concat_cond_re = shift;
3428     my $line_concat = shift;
3429
3430     open my $fh, $filename || die "unable to read $filename: $!\n";
3431     return sub {
3432         my $saved_line = "";
3433         $_ = "";
3434         while (<$fh>) {
3435             s|\R$||;
3436             if (defined $line_concat) {
3437                 $_ = $line_concat->($saved_line, $_);
3438                 $saved_line = "";
3439             }
3440             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3441                 $saved_line = $_;
3442                 next;
3443             }
3444             return $_;
3445         }
3446         die "$filename ending with continuation line\n" if $_;
3447         close $fh;
3448         return undef;
3449     }
3450 }
3451
3452 # collect_from_array($array, $line_concat_cond_re, $line_concat)
3453 # $array is an ARRAYref of lines
3454 # $line_concat_cond_re is a regexp detecting a line continuation ending
3455 # $line_concat is a CODEref that takes care of concatenating two lines
3456 sub collect_from_array {
3457     my $array = shift;
3458     my $line_concat_cond_re = shift;
3459     my $line_concat = shift;
3460     my @array = (@$array);
3461
3462     return sub {
3463         my $saved_line = "";
3464         $_ = "";
3465         while (defined($_ = shift @array)) {
3466             s|\R$||;
3467             if (defined $line_concat) {
3468                 $_ = $line_concat->($saved_line, $_);
3469                 $saved_line = "";
3470             }
3471             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3472                 $saved_line = $_;
3473                 next;
3474             }
3475             return $_;
3476         }
3477         die "input text ending with continuation line\n" if $_;
3478         return undef;
3479     }
3480 }
3481
3482 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
3483 # $lineiterator is a CODEref that delivers one line at a time.
3484 # All following arguments are regex/CODEref pairs, where the regexp detects a
3485 # line and the CODEref does something with the result of the regexp.
3486 sub collect_information {
3487     my $lineiterator = shift;
3488     my %collectors = @_;
3489
3490     while(defined($_ = $lineiterator->())) {
3491         s|\R$||;
3492         my $found = 0;
3493         if ($collectors{"BEFORE"}) {
3494             $collectors{"BEFORE"}->($_);
3495         }
3496         foreach my $re (keys %collectors) {
3497             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
3498                 $collectors{$re}->($lineiterator);
3499                 $found = 1;
3500             };
3501         }
3502         if ($collectors{"OTHERWISE"}) {
3503             $collectors{"OTHERWISE"}->($lineiterator, $_)
3504                 unless $found || !defined $collectors{"OTHERWISE"};
3505         }
3506         if ($collectors{"AFTER"}) {
3507             $collectors{"AFTER"}->($_);
3508         }
3509     }
3510 }
3511
3512 # tokenize($line)
3513 # $line is a line of text to split up into tokens
3514 # returns a list of tokens
3515 #
3516 # Tokens are divided by spaces.  If the tokens include spaces, they
3517 # have to be quoted with single or double quotes.  Double quotes
3518 # inside a double quoted token must be escaped.  Escaping is done
3519 # with backslash.
3520 # Basically, the same quoting rules apply for " and ' as in any
3521 # Unix shell.
3522 sub tokenize {
3523     my $line = my $debug_line = shift;
3524     my @result = ();
3525
3526     while ($line =~ s|^\s+||, $line ne "") {
3527         my $token = "";
3528         while ($line ne "" && $line !~ m|^\s|) {
3529             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
3530                 $token .= $1;
3531                 $line = $';
3532             } elsif ($line =~ m/^'([^']*)'/) {
3533                 $token .= $1;
3534                 $line = $';
3535             } elsif ($line =~ m/^(\S+)/) {
3536                 $token .= $1;
3537                 $line = $';
3538             }
3539         }
3540         push @result, $token;
3541     }
3542
3543     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3544         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
3545         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
3546     }
3547     return @result;
3548 }