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