'openssl list': add option -objects to list built in objects
[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, $s, $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 ***   If you want to report a building issue, please include the   ***
2803 ***   output from this command:                                    ***
2804 ***                                                                ***
2805 ***     perl configdata.pm --dump                                  ***
2806 ***                                                                ***
2807 **********************************************************************
2808 EOF
2809
2810 exit(0);
2811
2812 ######################################################################
2813 #
2814 # Helpers and utility functions
2815 #
2816
2817 # Death handler, to print a helpful message in case of failure #######
2818 #
2819 sub death_handler {
2820     die @_ if $^S;              # To prevent the added message in eval blocks
2821     my $build_file = $target{build_file} // "build file";
2822     my @message = ( <<"_____", @_ );
2823
2824 Failure!  $build_file wasn't produced.
2825 Please read INSTALL and associated NOTES files.  You may also have to look over
2826 your available compiler tool chain or change your configuration.
2827
2828 _____
2829
2830     # Dying is terminal, so it's ok to reset the signal handler here.
2831     $SIG{__DIE__} = $orig_death_handler;
2832     die @message;
2833 }
2834
2835 # Configuration file reading #########################################
2836
2837 # Note: All of the helper functions are for lazy evaluation.  They all
2838 # return a CODE ref, which will return the intended value when evaluated.
2839 # Thus, whenever there's mention of a returned value, it's about that
2840 # intended value.
2841
2842 # Helper function to implement conditional inheritance depending on the
2843 # value of $disabled{asm}.  Used in inherit_from values as follows:
2844 #
2845 #      inherit_from => [ "template", asm("asm_tmpl") ]
2846 #
2847 sub asm {
2848     my @x = @_;
2849     sub {
2850         $disabled{asm} ? () : @x;
2851     }
2852 }
2853
2854 # Helper function to implement conditional value variants, with a default
2855 # plus additional values based on the value of $config{build_type}.
2856 # Arguments are given in hash table form:
2857 #
2858 #       picker(default => "Basic string: ",
2859 #              debug   => "debug",
2860 #              release => "release")
2861 #
2862 # When configuring with --debug, the resulting string will be
2863 # "Basic string: debug", and when not, it will be "Basic string: release"
2864 #
2865 # This can be used to create variants of sets of flags according to the
2866 # build type:
2867 #
2868 #       cflags => picker(default => "-Wall",
2869 #                        debug   => "-g -O0",
2870 #                        release => "-O3")
2871 #
2872 sub picker {
2873     my %opts = @_;
2874     return sub { add($opts{default} || (),
2875                      $opts{$config{build_type}} || ())->(); }
2876 }
2877
2878 # Helper function to combine several values of different types into one.
2879 # This is useful if you want to combine a string with the result of a
2880 # lazy function, such as:
2881 #
2882 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2883 #
2884 sub combine {
2885     my @stuff = @_;
2886     return sub { add(@stuff)->(); }
2887 }
2888
2889 # Helper function to implement conditional values depending on the value
2890 # of $disabled{threads}.  Can be used as follows:
2891 #
2892 #       cflags => combine("-Wall", threads("-pthread"))
2893 #
2894 sub threads {
2895     my @flags = @_;
2896     return sub { add($disabled{threads} ? () : @flags)->(); }
2897 }
2898
2899 sub shared {
2900     my @flags = @_;
2901     return sub { add($disabled{shared} ? () : @flags)->(); }
2902 }
2903
2904 our $add_called = 0;
2905 # Helper function to implement adding values to already existing configuration
2906 # values.  It handles elements that are ARRAYs, CODEs and scalars
2907 sub _add {
2908     my $separator = shift;
2909
2910     # If there's any ARRAY in the collection of values OR the separator
2911     # is undef, we will return an ARRAY of combined values, otherwise a
2912     # string of joined values with $separator as the separator.
2913     my $found_array = !defined($separator);
2914
2915     my @values =
2916         map {
2917             my $res = $_;
2918             while (ref($res) eq "CODE") {
2919                 $res = $res->();
2920             }
2921             if (defined($res)) {
2922                 if (ref($res) eq "ARRAY") {
2923                     $found_array = 1;
2924                     @$res;
2925                 } else {
2926                     $res;
2927                 }
2928             } else {
2929                 ();
2930             }
2931     } (@_);
2932
2933     $add_called = 1;
2934
2935     if ($found_array) {
2936         [ @values ];
2937     } else {
2938         join($separator, grep { defined($_) && $_ ne "" } @values);
2939     }
2940 }
2941 sub add_before {
2942     my $separator = " ";
2943     if (ref($_[$#_]) eq "HASH") {
2944         my $opts = pop;
2945         $separator = $opts->{separator};
2946     }
2947     my @x = @_;
2948     sub { _add($separator, @x, @_) };
2949 }
2950 sub add {
2951     my $separator = " ";
2952     if (ref($_[$#_]) eq "HASH") {
2953         my $opts = pop;
2954         $separator = $opts->{separator};
2955     }
2956     my @x = @_;
2957     sub { _add($separator, @_, @x) };
2958 }
2959
2960 sub read_eval_file {
2961     my $fname = shift;
2962     my $content;
2963     my @result;
2964
2965     open F, "< $fname" or die "Can't open '$fname': $!\n";
2966     {
2967         undef local $/;
2968         $content = <F>;
2969     }
2970     close F;
2971     {
2972         local $@;
2973
2974         @result = ( eval $content );
2975         warn $@ if $@;
2976     }
2977     return wantarray ? @result : $result[0];
2978 }
2979
2980 # configuration reader, evaluates the input file as a perl script and expects
2981 # it to fill %targets with target configurations.  Those are then added to
2982 # %table.
2983 sub read_config {
2984     my $fname = shift;
2985     my %targets;
2986
2987     {
2988         # Protect certain tables from tampering
2989         local %table = ();
2990
2991         %targets = read_eval_file($fname);
2992     }
2993     my %preexisting = ();
2994     foreach (sort keys %targets) {
2995         $preexisting{$_} = 1 if $table{$_};
2996     }
2997     die <<"EOF",
2998 The following config targets from $fname
2999 shadow pre-existing config targets with the same name:
3000 EOF
3001         map { "  $_\n" } sort keys %preexisting
3002         if %preexisting;
3003
3004
3005     # For each target, check that it's configured with a hash table.
3006     foreach (keys %targets) {
3007         if (ref($targets{$_}) ne "HASH") {
3008             if (ref($targets{$_}) eq "") {
3009                 warn "Deprecated target configuration for $_, ignoring...\n";
3010             } else {
3011                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
3012             }
3013             delete $targets{$_};
3014         } else {
3015             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
3016         }
3017     }
3018
3019     %table = (%table, %targets);
3020
3021 }
3022
3023 # configuration resolver.  Will only resolve all the lazy evaluation
3024 # codeblocks for the chosen target and all those it inherits from,
3025 # recursively
3026 sub resolve_config {
3027     my $target = shift;
3028     my @breadcrumbs = @_;
3029
3030 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
3031
3032     if (grep { $_ eq $target } @breadcrumbs) {
3033         die "inherit_from loop!  target backtrace:\n  "
3034             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
3035     }
3036
3037     if (!defined($table{$target})) {
3038         warn "Warning! target $target doesn't exist!\n";
3039         return ();
3040     }
3041     # Recurse through all inheritances.  They will be resolved on the
3042     # fly, so when this operation is done, they will all just be a
3043     # bunch of attributes with string values.
3044     # What we get here, though, are keys with references to lists of
3045     # the combined values of them all.  We will deal with lists after
3046     # this stage is done.
3047     my %combined_inheritance = ();
3048     if ($table{$target}->{inherit_from}) {
3049         my @inherit_from =
3050             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
3051         foreach (@inherit_from) {
3052             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
3053
3054             # 'template' is a marker that's considered private to
3055             # the config that had it.
3056             delete $inherited_config{template};
3057
3058             foreach (keys %inherited_config) {
3059                 if (!$combined_inheritance{$_}) {
3060                     $combined_inheritance{$_} = [];
3061                 }
3062                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
3063             }
3064         }
3065     }
3066
3067     # We won't need inherit_from in this target any more, since we've
3068     # resolved all the inheritances that lead to this
3069     delete $table{$target}->{inherit_from};
3070
3071     # Now is the time to deal with those lists.  Here's the place to
3072     # decide what shall be done with those lists, all based on the
3073     # values of the target we're currently dealing with.
3074     # - If a value is a coderef, it will be executed with the list of
3075     #   inherited values as arguments.
3076     # - If the corresponding key doesn't have a value at all or is the
3077     #   empty string, the inherited value list will be run through the
3078     #   default combiner (below), and the result becomes this target's
3079     #   value.
3080     # - Otherwise, this target's value is assumed to be a string that
3081     #   will simply override the inherited list of values.
3082     my $default_combiner = add();
3083
3084     my %all_keys =
3085         map { $_ => 1 } (keys %combined_inheritance,
3086                          keys %{$table{$target}});
3087
3088     sub process_values {
3089         my $object    = shift;
3090         my $inherited = shift;  # Always a [ list ]
3091         my $target    = shift;
3092         my $entry     = shift;
3093
3094         $add_called = 0;
3095
3096         while(ref($object) eq "CODE") {
3097             $object = $object->(@$inherited);
3098         }
3099         if (!defined($object)) {
3100             return ();
3101         }
3102         elsif (ref($object) eq "ARRAY") {
3103             local $add_called;  # To make sure recursive calls don't affect it
3104             return [ map { process_values($_, $inherited, $target, $entry) }
3105                      @$object ];
3106         } elsif (ref($object) eq "") {
3107             return $object;
3108         } else {
3109             die "cannot handle reference type ",ref($object)
3110                 ," found in target ",$target," -> ",$entry,"\n";
3111         }
3112     }
3113
3114     foreach (sort keys %all_keys) {
3115         my $previous = $combined_inheritance{$_};
3116
3117         # Current target doesn't have a value for the current key?
3118         # Assign it the default combiner, the rest of this loop body
3119         # will handle it just like any other coderef.
3120         if (!exists $table{$target}->{$_}) {
3121             $table{$target}->{$_} = $default_combiner;
3122         }
3123
3124         $table{$target}->{$_} = process_values($table{$target}->{$_},
3125                                                $combined_inheritance{$_},
3126                                                $target, $_);
3127         unless(defined($table{$target}->{$_})) {
3128             delete $table{$target}->{$_};
3129         }
3130 #        if ($extra_checks &&
3131 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
3132 #            warn "$_ got replaced in $target\n";
3133 #        }
3134     }
3135
3136     # Finally done, return the result.
3137     return %{$table{$target}};
3138 }
3139
3140 sub usage
3141         {
3142         print STDERR $usage;
3143         print STDERR "\npick os/compiler from:\n";
3144         my $j=0;
3145         my $i;
3146         my $k=0;
3147         foreach $i (sort keys %table)
3148                 {
3149                 next if $table{$i}->{template};
3150                 next if $i =~ /^debug/;
3151                 $k += length($i) + 1;
3152                 if ($k > 78)
3153                         {
3154                         print STDERR "\n";
3155                         $k=length($i);
3156                         }
3157                 print STDERR $i . " ";
3158                 }
3159         foreach $i (sort keys %table)
3160                 {
3161                 next if $table{$i}->{template};
3162                 next if $i !~ /^debug/;
3163                 $k += length($i) + 1;
3164                 if ($k > 78)
3165                         {
3166                         print STDERR "\n";
3167                         $k=length($i);
3168                         }
3169                 print STDERR $i . " ";
3170                 }
3171         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
3172         exit(1);
3173         }
3174
3175 sub run_dofile
3176 {
3177     my $out = shift;
3178     my @templates = @_;
3179
3180     unlink $out || warn "Can't remove $out, $!"
3181         if -f $out;
3182     foreach (@templates) {
3183         die "Can't open $_, $!" unless -f $_;
3184     }
3185     my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
3186     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
3187     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
3188     system($cmd);
3189     exit 1 if $? != 0;
3190     rename("$out.new", $out) || die "Can't rename $out.new, $!";
3191 }
3192
3193 sub compiler_predefined {
3194     state %predefined;
3195     my $cc = shift;
3196
3197     return () if $^O eq 'VMS';
3198
3199     die 'compiler_predefined called without a compiler command'
3200         unless $cc;
3201
3202     if (! $predefined{$cc}) {
3203
3204         $predefined{$cc} = {};
3205
3206         # collect compiler pre-defines from gcc or gcc-alike...
3207         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3208         while (my $l = <PIPE>) {
3209             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3210             $predefined{$cc}->{$1} = $2 // '';
3211         }
3212         close(PIPE);
3213     }
3214
3215     return %{$predefined{$cc}};
3216 }
3217
3218 sub which
3219 {
3220     my ($name)=@_;
3221
3222     if (eval { require IPC::Cmd; 1; }) {
3223         IPC::Cmd->import();
3224         return scalar IPC::Cmd::can_run($name);
3225     } else {
3226         # if there is $directories component in splitpath,
3227         # then it's not something to test with $PATH...
3228         return $name if (File::Spec->splitpath($name))[1];
3229
3230         foreach (File::Spec->path()) {
3231             my $fullpath = catfile($_, "$name$target{exe_extension}");
3232             if (-f $fullpath and -x $fullpath) {
3233                 return $fullpath;
3234             }
3235         }
3236     }
3237 }
3238
3239 sub env
3240 {
3241     my $name = shift;
3242     my %opts = @_;
3243
3244     unless ($opts{cacheonly}) {
3245         # Note that if $ENV{$name} doesn't exist or is undefined,
3246         # $config{perlenv}->{$name} will be created with the value
3247         # undef.  This is intentional.
3248
3249         $config{perlenv}->{$name} = $ENV{$name}
3250             if ! exists $config{perlenv}->{$name};
3251     }
3252     return $config{perlenv}->{$name};
3253 }
3254
3255 # Configuration printer ##############################################
3256
3257 sub print_table_entry
3258 {
3259     local $now_printing = shift;
3260     my %target = resolve_config($now_printing);
3261     my $type = shift;
3262
3263     # Don't print the templates
3264     return if $target{template};
3265
3266     my @sequence = (
3267         "sys_id",
3268         "cpp",
3269         "cppflags",
3270         "defines",
3271         "includes",
3272         "cc",
3273         "cflags",
3274         "unistd",
3275         "ld",
3276         "lflags",
3277         "loutflag",
3278         "ex_libs",
3279         "bn_ops",
3280         "apps_aux_src",
3281         "cpuid_asm_src",
3282         "uplink_aux_src",
3283         "bn_asm_src",
3284         "ec_asm_src",
3285         "des_asm_src",
3286         "aes_asm_src",
3287         "bf_asm_src",
3288         "md5_asm_src",
3289         "cast_asm_src",
3290         "sha1_asm_src",
3291         "rc4_asm_src",
3292         "rmd160_asm_src",
3293         "rc5_asm_src",
3294         "wp_asm_src",
3295         "cmll_asm_src",
3296         "modes_asm_src",
3297         "padlock_asm_src",
3298         "chacha_asm_src",
3299         "poly1035_asm_src",
3300         "thread_scheme",
3301         "perlasm_scheme",
3302         "dso_scheme",
3303         "shared_target",
3304         "shared_cflag",
3305         "shared_defines",
3306         "shared_ldflag",
3307         "shared_rcflag",
3308         "shared_extension",
3309         "dso_extension",
3310         "obj_extension",
3311         "exe_extension",
3312         "ranlib",
3313         "ar",
3314         "arflags",
3315         "aroutflag",
3316         "rc",
3317         "rcflags",
3318         "rcoutflag",
3319         "mt",
3320         "mtflags",
3321         "mtinflag",
3322         "mtoutflag",
3323         "multilib",
3324         "build_scheme",
3325         );
3326
3327     if ($type eq "TABLE") {
3328         print "\n";
3329         print "*** $now_printing\n";
3330         foreach (@sequence) {
3331             if (ref($target{$_}) eq "ARRAY") {
3332                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
3333             } else {
3334                 printf "\$%-12s = %s\n", $_, $target{$_};
3335             }
3336         }
3337     } elsif ($type eq "HASH") {
3338         my $largest =
3339             length((sort { length($a) <=> length($b) } @sequence)[-1]);
3340         print "    '$now_printing' => {\n";
3341         foreach (@sequence) {
3342             if ($target{$_}) {
3343                 if (ref($target{$_}) eq "ARRAY") {
3344                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
3345                 } else {
3346                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
3347                 }
3348             }
3349         }
3350         print "    },\n";
3351     }
3352 }
3353
3354 # Utility routines ###################################################
3355
3356 # On VMS, if the given file is a logical name, File::Spec::Functions
3357 # will consider it an absolute path.  There are cases when we want a
3358 # purely syntactic check without checking the environment.
3359 sub isabsolute {
3360     my $file = shift;
3361
3362     # On non-platforms, we just use file_name_is_absolute().
3363     return file_name_is_absolute($file) unless $^O eq "VMS";
3364
3365     # If the file spec includes a device or a directory spec,
3366     # file_name_is_absolute() is perfectly safe.
3367     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
3368
3369     # Here, we know the given file spec isn't absolute
3370     return 0;
3371 }
3372
3373 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
3374 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
3375 # realpath() requires that at least all path components except the last is an
3376 # existing directory.  On VMS, the last component of the directory spec must
3377 # exist.
3378 sub absolutedir {
3379     my $dir = shift;
3380
3381     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
3382     # will return the volume name for the device, no matter what.  Also,
3383     # it will return an incorrect directory spec if the argument is a
3384     # directory that doesn't exist.
3385     if ($^O eq "VMS") {
3386         return rel2abs($dir);
3387     }
3388
3389     # We use realpath() on Unix, since no other will properly clean out
3390     # a directory spec.
3391     use Cwd qw/realpath/;
3392
3393     return realpath($dir);
3394 }
3395
3396 sub quotify {
3397     my %processors = (
3398         perl    => sub { my $x = shift;
3399                          $x =~ s/([\\\$\@"])/\\$1/g;
3400                          return '"'.$x.'"'; },
3401         maybeshell => sub { my $x = shift;
3402                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
3403                             if ($x ne $y || $x =~ m|\s|) {
3404                                 return '"'.$y.'"';
3405                             } else {
3406                                 return $x;
3407                             }
3408                         },
3409         );
3410     my $for = shift;
3411     my $processor =
3412         defined($processors{$for}) ? $processors{$for} : sub { shift; };
3413
3414     return map { $processor->($_); } @_;
3415 }
3416
3417 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
3418 # $filename is a file name to read from
3419 # $line_concat_cond_re is a regexp detecting a line continuation ending
3420 # $line_concat is a CODEref that takes care of concatenating two lines
3421 sub collect_from_file {
3422     my $filename = shift;
3423     my $line_concat_cond_re = shift;
3424     my $line_concat = shift;
3425
3426     open my $fh, $filename || die "unable to read $filename: $!\n";
3427     return sub {
3428         my $saved_line = "";
3429         $_ = "";
3430         while (<$fh>) {
3431             s|\R$||;
3432             if (defined $line_concat) {
3433                 $_ = $line_concat->($saved_line, $_);
3434                 $saved_line = "";
3435             }
3436             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3437                 $saved_line = $_;
3438                 next;
3439             }
3440             return $_;
3441         }
3442         die "$filename ending with continuation line\n" if $_;
3443         close $fh;
3444         return undef;
3445     }
3446 }
3447
3448 # collect_from_array($array, $line_concat_cond_re, $line_concat)
3449 # $array is an ARRAYref of lines
3450 # $line_concat_cond_re is a regexp detecting a line continuation ending
3451 # $line_concat is a CODEref that takes care of concatenating two lines
3452 sub collect_from_array {
3453     my $array = shift;
3454     my $line_concat_cond_re = shift;
3455     my $line_concat = shift;
3456     my @array = (@$array);
3457
3458     return sub {
3459         my $saved_line = "";
3460         $_ = "";
3461         while (defined($_ = shift @array)) {
3462             s|\R$||;
3463             if (defined $line_concat) {
3464                 $_ = $line_concat->($saved_line, $_);
3465                 $saved_line = "";
3466             }
3467             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3468                 $saved_line = $_;
3469                 next;
3470             }
3471             return $_;
3472         }
3473         die "input text ending with continuation line\n" if $_;
3474         return undef;
3475     }
3476 }
3477
3478 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
3479 # $lineiterator is a CODEref that delivers one line at a time.
3480 # All following arguments are regex/CODEref pairs, where the regexp detects a
3481 # line and the CODEref does something with the result of the regexp.
3482 sub collect_information {
3483     my $lineiterator = shift;
3484     my %collectors = @_;
3485
3486     while(defined($_ = $lineiterator->())) {
3487         s|\R$||;
3488         my $found = 0;
3489         if ($collectors{"BEFORE"}) {
3490             $collectors{"BEFORE"}->($_);
3491         }
3492         foreach my $re (keys %collectors) {
3493             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
3494                 $collectors{$re}->($lineiterator);
3495                 $found = 1;
3496             };
3497         }
3498         if ($collectors{"OTHERWISE"}) {
3499             $collectors{"OTHERWISE"}->($lineiterator, $_)
3500                 unless $found || !defined $collectors{"OTHERWISE"};
3501         }
3502         if ($collectors{"AFTER"}) {
3503             $collectors{"AFTER"}->($_);
3504         }
3505     }
3506 }
3507
3508 # tokenize($line)
3509 # $line is a line of text to split up into tokens
3510 # returns a list of tokens
3511 #
3512 # Tokens are divided by spaces.  If the tokens include spaces, they
3513 # have to be quoted with single or double quotes.  Double quotes
3514 # inside a double quoted token must be escaped.  Escaping is done
3515 # with backslash.
3516 # Basically, the same quoting rules apply for " and ' as in any
3517 # Unix shell.
3518 sub tokenize {
3519     my $line = my $debug_line = shift;
3520     my @result = ();
3521
3522     while ($line =~ s|^\s+||, $line ne "") {
3523         my $token = "";
3524         while ($line ne "" && $line !~ m|^\s|) {
3525             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
3526                 $token .= $1;
3527                 $line = $';
3528             } elsif ($line =~ m/^'([^']*)'/) {
3529                 $token .= $1;
3530                 $line = $';
3531             } elsif ($line =~ m/^(\S+)/) {
3532                 $token .= $1;
3533                 $line = $';
3534             }
3535         }
3536         push @result, $token;
3537     }
3538
3539     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3540         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
3541         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
3542     }
3543     return @result;
3544 }