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