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