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