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