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