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