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