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