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