Don't remove $(TARFILE) when cleaning
[openssl.git] / Configure
1 #! /usr/bin/env perl
2 # -*- mode: perl; -*-
3 # Copyright 2016-2021 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"
2615                 unless grep { $_ =~ /^${what}$/ } keys %disabled;
2616         }
2617         print "\nDisabled features:\n\n";
2618         foreach my $what (@disablables) {
2619             my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled;
2620             my $what3 = $what2[0];
2621             if ($what3) {
2622                 print "    $what3", ' ' x ($longest - length($what3) + 1),
2623                     "[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1);
2624                 print $disabled_info{$what3}->{macro}
2625                     if $disabled_info{$what3}->{macro};
2626                 print ' (skip ',
2627                     join(', ', @{$disabled_info{$what3}->{skipped}}),
2628                     ')'
2629                     if $disabled_info{$what3}->{skipped};
2630                 print "\n";
2631             }
2632         }
2633     }
2634     if ($dump || $target) {
2635         print "\nConfig target attributes:\n\n";
2636         foreach (sort keys %target) {
2637             next if $_ =~ m|^_| || $_ eq 'template';
2638             my $quotify = sub {
2639                 map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
2640             };
2641             print '    ', $_, ' => ';
2642             if (ref($target{$_}) eq "ARRAY") {
2643                 print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
2644             } else {
2645                 print $quotify->($target{$_}), ",\n"
2646             }
2647         }
2648     }
2649     if ($dump || $envvars) {
2650         print "\nRecorded environment:\n\n";
2651         foreach (sort keys %{$config{perlenv}}) {
2652             print '    ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
2653         }
2654     }
2655     if ($dump || $makevars) {
2656         print "\nMakevars:\n\n";
2657         foreach my $var (@makevars) {
2658             my $prefix = '';
2659             $prefix = $config{CROSS_COMPILE}
2660                 if grep { $var eq $_ } @user_crossable;
2661             $prefix //= '';
2662             print '    ',$var,' ' x (16 - length $var),'= ',
2663                 (ref $config{$var} eq 'ARRAY'
2664                  ? join(' ', @{$config{$var}})
2665                  : $prefix.$config{$var}),
2666                 "\n"
2667                 if defined $config{$var};
2668         }
2669
2670         my @buildfile = ($config{builddir}, $config{build_file});
2671         unshift @buildfile, $here
2672             unless file_name_is_absolute($config{builddir});
2673         my $buildfile = canonpath(catdir(@buildfile));
2674         print <<"_____";
2675
2676 NOTE: These variables only represent the configuration view.  The build file
2677 template may have processed these variables further, please have a look at the
2678 build file for more exact data:
2679     $buildfile
2680 _____
2681     }
2682     if ($dump || $buildparams) {
2683         my @buildfile = ($config{builddir}, $config{build_file});
2684         unshift @buildfile, $here
2685             unless file_name_is_absolute($config{builddir});
2686         print "\nbuild file:\n\n";
2687         print "    ", canonpath(catfile(@buildfile)),"\n";
2688
2689         print "\nbuild file templates:\n\n";
2690         foreach (@{$config{build_file_templates}}) {
2691             my @tmpl = ($_);
2692             unshift @tmpl, $here
2693                 unless file_name_is_absolute($config{sourcedir});
2694             print '    ',canonpath(catfile(@tmpl)),"\n";
2695         }
2696     }
2697     if ($reconf) {
2698         if ($verbose) {
2699             print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
2700             foreach (sort keys %{$config{perlenv}}) {
2701                 print '    ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
2702             }
2703         }
2704
2705         chdir $here;
2706         exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
2707     }
2708 }
2709
2710 1;
2711
2712 __END__
2713
2714 =head1 NAME
2715
2716 configdata.pm - configuration data for OpenSSL builds
2717
2718 =head1 SYNOPSIS
2719
2720 Interactive:
2721
2722   perl configdata.pm [options]
2723
2724 As data bank module:
2725
2726   use configdata;
2727
2728 =head1 DESCRIPTION
2729
2730 This module can be used in two modes, interactively and as a module containing
2731 all the data recorded by OpenSSL's Configure script.
2732
2733 When used interactively, simply run it as any perl script, with at least one
2734 option, and you will get the information you ask for.  See L</OPTIONS> below.
2735
2736 When loaded as a module, you get a few databanks with useful information to
2737 perform build related tasks.  The databanks are:
2738
2739     %config             Configured things.
2740     %target             The OpenSSL config target with all inheritances
2741                         resolved.
2742     %disabled           The features that are disabled.
2743     @disablables        The list of features that can be disabled.
2744     %withargs           All data given through --with-THING options.
2745     %unified_info       All information that was computed from the build.info
2746                         files.
2747
2748 =head1 OPTIONS
2749
2750 =over 4
2751
2752 =item B<--help>
2753
2754 Print a brief help message and exit.
2755
2756 =item B<--man>
2757
2758 Print the manual page and exit.
2759
2760 =item B<--dump> | B<-d>
2761
2762 Print all relevant configuration data.  This is equivalent to B<--command-line>
2763 B<--options> B<--target> B<--environment> B<--make-variables>
2764 B<--build-parameters>.
2765
2766 =item B<--command-line> | B<-c>
2767
2768 Print the current configuration command line.
2769
2770 =item B<--options> | B<-o>
2771
2772 Print the features, both enabled and disabled, and display defined macro and
2773 skipped directories where applicable.
2774
2775 =item B<--target> | B<-t>
2776
2777 Print the config attributes for this config target.
2778
2779 =item B<--environment> | B<-e>
2780
2781 Print the environment variables and their values at the time of configuration.
2782
2783 =item B<--make-variables> | B<-m>
2784
2785 Print the main make variables generated in the current configuration
2786
2787 =item B<--build-parameters> | B<-b>
2788
2789 Print the build parameters, i.e. build file and build file templates.
2790
2791 =item B<--reconfigure> | B<--reconf> | B<-r>
2792
2793 Redo the configuration.
2794
2795 =item B<--verbose> | B<-v>
2796
2797 Verbose output.
2798
2799 =back
2800
2801 =cut
2802
2803 EOF
2804 close(OUT);
2805 if ($builder_platform eq 'unix') {
2806     my $mode = (0755 & ~umask);
2807     chmod $mode, 'configdata.pm'
2808         or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
2809 }
2810
2811 my %builders = (
2812     unified => sub {
2813         print 'Creating ',$target{build_file},"\n";
2814         run_dofile(catfile($blddir, $target{build_file}),
2815                    @{$config{build_file_templates}});
2816     },
2817     );
2818
2819 $builders{$builder}->($builder_platform, @builder_opts);
2820
2821 $SIG{__DIE__} = $orig_death_handler;
2822
2823 print <<"EOF" if ($disabled{threads} eq "unavailable");
2824
2825 The library could not be configured for supporting multi-threaded
2826 applications as the compiler options required on this system are not known.
2827 See file INSTALL for details if you need multi-threading.
2828 EOF
2829
2830 print <<"EOF" if ($no_shared_warn);
2831
2832 The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
2833 platform, so we will pretend you gave the option 'no-pic', which also disables
2834 'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
2835 or position independent code, please let us know (but please first make sure
2836 you have tried with a current version of OpenSSL).
2837 EOF
2838
2839 print <<"EOF";
2840
2841 **********************************************************************
2842 ***                                                                ***
2843 ***   OpenSSL has been successfully configured                     ***
2844 ***                                                                ***
2845 ***   If you encounter a problem while building, please open an    ***
2846 ***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
2847 ***   and include the output from the following command:           ***
2848 ***                                                                ***
2849 ***       perl configdata.pm --dump                                ***
2850 ***                                                                ***
2851 ***   (If you are new to OpenSSL, you might want to consult the    ***
2852 ***   'Troubleshooting' section in the INSTALL file first)         ***
2853 ***                                                                ***
2854 **********************************************************************
2855 EOF
2856
2857 exit(0);
2858
2859 ######################################################################
2860 #
2861 # Helpers and utility functions
2862 #
2863
2864 # Death handler, to print a helpful message in case of failure #######
2865 #
2866 sub death_handler {
2867     die @_ if $^S;              # To prevent the added message in eval blocks
2868     my $build_file = $target{build_file} // "build file";
2869     my @message = ( <<"_____", @_ );
2870
2871 Failure!  $build_file wasn't produced.
2872 Please read INSTALL and associated NOTES files.  You may also have to look over
2873 your available compiler tool chain or change your configuration.
2874
2875 _____
2876
2877     # Dying is terminal, so it's ok to reset the signal handler here.
2878     $SIG{__DIE__} = $orig_death_handler;
2879     die @message;
2880 }
2881
2882 # Configuration file reading #########################################
2883
2884 # Note: All of the helper functions are for lazy evaluation.  They all
2885 # return a CODE ref, which will return the intended value when evaluated.
2886 # Thus, whenever there's mention of a returned value, it's about that
2887 # intended value.
2888
2889 # Helper function to implement conditional inheritance depending on the
2890 # value of $disabled{asm}.  Used in inherit_from values as follows:
2891 #
2892 #      inherit_from => [ "template", asm("asm_tmpl") ]
2893 #
2894 sub asm {
2895     my @x = @_;
2896     sub {
2897         $disabled{asm} ? () : @x;
2898     }
2899 }
2900
2901 # Helper function to implement conditional value variants, with a default
2902 # plus additional values based on the value of $config{build_type}.
2903 # Arguments are given in hash table form:
2904 #
2905 #       picker(default => "Basic string: ",
2906 #              debug   => "debug",
2907 #              release => "release")
2908 #
2909 # When configuring with --debug, the resulting string will be
2910 # "Basic string: debug", and when not, it will be "Basic string: release"
2911 #
2912 # This can be used to create variants of sets of flags according to the
2913 # build type:
2914 #
2915 #       cflags => picker(default => "-Wall",
2916 #                        debug   => "-g -O0",
2917 #                        release => "-O3")
2918 #
2919 sub picker {
2920     my %opts = @_;
2921     return sub { add($opts{default} || (),
2922                      $opts{$config{build_type}} || ())->(); }
2923 }
2924
2925 # Helper function to combine several values of different types into one.
2926 # This is useful if you want to combine a string with the result of a
2927 # lazy function, such as:
2928 #
2929 #       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
2930 #
2931 sub combine {
2932     my @stuff = @_;
2933     return sub { add(@stuff)->(); }
2934 }
2935
2936 # Helper function to implement conditional values depending on the value
2937 # of $disabled{threads}.  Can be used as follows:
2938 #
2939 #       cflags => combine("-Wall", threads("-pthread"))
2940 #
2941 sub threads {
2942     my @flags = @_;
2943     return sub { add($disabled{threads} ? () : @flags)->(); }
2944 }
2945
2946 sub shared {
2947     my @flags = @_;
2948     return sub { add($disabled{shared} ? () : @flags)->(); }
2949 }
2950
2951 our $add_called = 0;
2952 # Helper function to implement adding values to already existing configuration
2953 # values.  It handles elements that are ARRAYs, CODEs and scalars
2954 sub _add {
2955     my $separator = shift;
2956
2957     # If there's any ARRAY in the collection of values OR the separator
2958     # is undef, we will return an ARRAY of combined values, otherwise a
2959     # string of joined values with $separator as the separator.
2960     my $found_array = !defined($separator);
2961
2962     my @values =
2963         map {
2964             my $res = $_;
2965             while (ref($res) eq "CODE") {
2966                 $res = $res->();
2967             }
2968             if (defined($res)) {
2969                 if (ref($res) eq "ARRAY") {
2970                     $found_array = 1;
2971                     @$res;
2972                 } else {
2973                     $res;
2974                 }
2975             } else {
2976                 ();
2977             }
2978     } (@_);
2979
2980     $add_called = 1;
2981
2982     if ($found_array) {
2983         [ @values ];
2984     } else {
2985         join($separator, grep { defined($_) && $_ ne "" } @values);
2986     }
2987 }
2988 sub add_before {
2989     my $separator = " ";
2990     if (ref($_[$#_]) eq "HASH") {
2991         my $opts = pop;
2992         $separator = $opts->{separator};
2993     }
2994     my @x = @_;
2995     sub { _add($separator, @x, @_) };
2996 }
2997 sub add {
2998     my $separator = " ";
2999     if (ref($_[$#_]) eq "HASH") {
3000         my $opts = pop;
3001         $separator = $opts->{separator};
3002     }
3003     my @x = @_;
3004     sub { _add($separator, @_, @x) };
3005 }
3006
3007 sub read_eval_file {
3008     my $fname = shift;
3009     my $content;
3010     my @result;
3011
3012     open F, "< $fname" or die "Can't open '$fname': $!\n";
3013     {
3014         undef local $/;
3015         $content = <F>;
3016     }
3017     close F;
3018     {
3019         local $@;
3020
3021         @result = ( eval $content );
3022         warn $@ if $@;
3023     }
3024     return wantarray ? @result : $result[0];
3025 }
3026
3027 # configuration reader, evaluates the input file as a perl script and expects
3028 # it to fill %targets with target configurations.  Those are then added to
3029 # %table.
3030 sub read_config {
3031     my $fname = shift;
3032     my %targets;
3033
3034     {
3035         # Protect certain tables from tampering
3036         local %table = ();
3037
3038         %targets = read_eval_file($fname);
3039     }
3040     my %preexisting = ();
3041     foreach (sort keys %targets) {
3042         $preexisting{$_} = 1 if $table{$_};
3043     }
3044     die <<"EOF",
3045 The following config targets from $fname
3046 shadow pre-existing config targets with the same name:
3047 EOF
3048         map { "  $_\n" } sort keys %preexisting
3049         if %preexisting;
3050
3051
3052     # For each target, check that it's configured with a hash table.
3053     foreach (keys %targets) {
3054         if (ref($targets{$_}) ne "HASH") {
3055             if (ref($targets{$_}) eq "") {
3056                 warn "Deprecated target configuration for $_, ignoring...\n";
3057             } else {
3058                 warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
3059             }
3060             delete $targets{$_};
3061         } else {
3062             $targets{$_}->{_conf_fname_int} = add([ $fname ]);
3063         }
3064     }
3065
3066     %table = (%table, %targets);
3067
3068 }
3069
3070 # configuration resolver.  Will only resolve all the lazy evaluation
3071 # codeblocks for the chosen target and all those it inherits from,
3072 # recursively
3073 sub resolve_config {
3074     my $target = shift;
3075     my @breadcrumbs = @_;
3076
3077 #    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
3078
3079     if (grep { $_ eq $target } @breadcrumbs) {
3080         die "inherit_from loop!  target backtrace:\n  "
3081             ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
3082     }
3083
3084     if (!defined($table{$target})) {
3085         warn "Warning! target $target doesn't exist!\n";
3086         return ();
3087     }
3088     # Recurse through all inheritances.  They will be resolved on the
3089     # fly, so when this operation is done, they will all just be a
3090     # bunch of attributes with string values.
3091     # What we get here, though, are keys with references to lists of
3092     # the combined values of them all.  We will deal with lists after
3093     # this stage is done.
3094     my %combined_inheritance = ();
3095     if ($table{$target}->{inherit_from}) {
3096         my @inherit_from =
3097             map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
3098         foreach (@inherit_from) {
3099             my %inherited_config = resolve_config($_, $target, @breadcrumbs);
3100
3101             # 'template' is a marker that's considered private to
3102             # the config that had it.
3103             delete $inherited_config{template};
3104
3105             foreach (keys %inherited_config) {
3106                 if (!$combined_inheritance{$_}) {
3107                     $combined_inheritance{$_} = [];
3108                 }
3109                 push @{$combined_inheritance{$_}}, $inherited_config{$_};
3110             }
3111         }
3112     }
3113
3114     # We won't need inherit_from in this target any more, since we've
3115     # resolved all the inheritances that lead to this
3116     delete $table{$target}->{inherit_from};
3117
3118     # Now is the time to deal with those lists.  Here's the place to
3119     # decide what shall be done with those lists, all based on the
3120     # values of the target we're currently dealing with.
3121     # - If a value is a coderef, it will be executed with the list of
3122     #   inherited values as arguments.
3123     # - If the corresponding key doesn't have a value at all or is the
3124     #   empty string, the inherited value list will be run through the
3125     #   default combiner (below), and the result becomes this target's
3126     #   value.
3127     # - Otherwise, this target's value is assumed to be a string that
3128     #   will simply override the inherited list of values.
3129     my $default_combiner = add();
3130
3131     my %all_keys =
3132         map { $_ => 1 } (keys %combined_inheritance,
3133                          keys %{$table{$target}});
3134
3135     sub process_values {
3136         my $object    = shift;
3137         my $inherited = shift;  # Always a [ list ]
3138         my $target    = shift;
3139         my $entry     = shift;
3140
3141         $add_called = 0;
3142
3143         while(ref($object) eq "CODE") {
3144             $object = $object->(@$inherited);
3145         }
3146         if (!defined($object)) {
3147             return ();
3148         }
3149         elsif (ref($object) eq "ARRAY") {
3150             local $add_called;  # To make sure recursive calls don't affect it
3151             return [ map { process_values($_, $inherited, $target, $entry) }
3152                      @$object ];
3153         } elsif (ref($object) eq "") {
3154             return $object;
3155         } else {
3156             die "cannot handle reference type ",ref($object)
3157                 ," found in target ",$target," -> ",$entry,"\n";
3158         }
3159     }
3160
3161     foreach (sort keys %all_keys) {
3162         my $previous = $combined_inheritance{$_};
3163
3164         # Current target doesn't have a value for the current key?
3165         # Assign it the default combiner, the rest of this loop body
3166         # will handle it just like any other coderef.
3167         if (!exists $table{$target}->{$_}) {
3168             $table{$target}->{$_} = $default_combiner;
3169         }
3170
3171         $table{$target}->{$_} = process_values($table{$target}->{$_},
3172                                                $combined_inheritance{$_},
3173                                                $target, $_);
3174         unless(defined($table{$target}->{$_})) {
3175             delete $table{$target}->{$_};
3176         }
3177 #        if ($extra_checks &&
3178 #            $previous && !($add_called ||  $previous ~~ $table{$target}->{$_})) {
3179 #            warn "$_ got replaced in $target\n";
3180 #        }
3181     }
3182
3183     # Finally done, return the result.
3184     return %{$table{$target}};
3185 }
3186
3187 sub usage
3188         {
3189         print STDERR $usage;
3190         print STDERR "\npick os/compiler from:\n";
3191         my $j=0;
3192         my $i;
3193         my $k=0;
3194         foreach $i (sort keys %table)
3195                 {
3196                 next if $table{$i}->{template};
3197                 next if $i =~ /^debug/;
3198                 $k += length($i) + 1;
3199                 if ($k > 78)
3200                         {
3201                         print STDERR "\n";
3202                         $k=length($i);
3203                         }
3204                 print STDERR $i . " ";
3205                 }
3206         foreach $i (sort keys %table)
3207                 {
3208                 next if $table{$i}->{template};
3209                 next if $i !~ /^debug/;
3210                 $k += length($i) + 1;
3211                 if ($k > 78)
3212                         {
3213                         print STDERR "\n";
3214                         $k=length($i);
3215                         }
3216                 print STDERR $i . " ";
3217                 }
3218         print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
3219         exit(1);
3220         }
3221
3222 sub run_dofile
3223 {
3224     my $out = shift;
3225     my @templates = @_;
3226
3227     unlink $out || warn "Can't remove $out, $!"
3228         if -f $out;
3229     foreach (@templates) {
3230         die "Can't open $_, $!" unless -f $_;
3231     }
3232     my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
3233     my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
3234     #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
3235     system($cmd);
3236     exit 1 if $? != 0;
3237     rename("$out.new", $out) || die "Can't rename $out.new, $!";
3238 }
3239
3240 sub compiler_predefined {
3241     state %predefined;
3242     my $cc = shift;
3243
3244     return () if $^O eq 'VMS';
3245
3246     die 'compiler_predefined called without a compiler command'
3247         unless $cc;
3248
3249     if (! $predefined{$cc}) {
3250
3251         $predefined{$cc} = {};
3252
3253         # collect compiler pre-defines from gcc or gcc-alike...
3254         open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3255         while (my $l = <PIPE>) {
3256             $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3257             $predefined{$cc}->{$1} = $2 // '';
3258         }
3259         close(PIPE);
3260     }
3261
3262     return %{$predefined{$cc}};
3263 }
3264
3265 sub which
3266 {
3267     my ($name)=@_;
3268
3269     if (eval { require IPC::Cmd; 1; }) {
3270         IPC::Cmd->import();
3271         return scalar IPC::Cmd::can_run($name);
3272     } else {
3273         # if there is $directories component in splitpath,
3274         # then it's not something to test with $PATH...
3275         return $name if (File::Spec->splitpath($name))[1];
3276
3277         foreach (File::Spec->path()) {
3278             my $fullpath = catfile($_, "$name$target{exe_extension}");
3279             if (-f $fullpath and -x $fullpath) {
3280                 return $fullpath;
3281             }
3282         }
3283     }
3284 }
3285
3286 sub env
3287 {
3288     my $name = shift;
3289     my %opts = @_;
3290
3291     unless ($opts{cacheonly}) {
3292         # Note that if $ENV{$name} doesn't exist or is undefined,
3293         # $config{perlenv}->{$name} will be created with the value
3294         # undef.  This is intentional.
3295
3296         $config{perlenv}->{$name} = $ENV{$name}
3297             if ! exists $config{perlenv}->{$name};
3298     }
3299     return $config{perlenv}->{$name};
3300 }
3301
3302 # Configuration printer ##############################################
3303
3304 sub print_table_entry
3305 {
3306     local $now_printing = shift;
3307     my %target = resolve_config($now_printing);
3308     my $type = shift;
3309
3310     # Don't print the templates
3311     return if $target{template};
3312
3313     my @sequence = (
3314         "sys_id",
3315         "cpp",
3316         "cppflags",
3317         "defines",
3318         "includes",
3319         "cc",
3320         "cflags",
3321         "unistd",
3322         "ld",
3323         "lflags",
3324         "loutflag",
3325         "ex_libs",
3326         "bn_ops",
3327         "apps_aux_src",
3328         "cpuid_asm_src",
3329         "uplink_aux_src",
3330         "bn_asm_src",
3331         "ec_asm_src",
3332         "des_asm_src",
3333         "aes_asm_src",
3334         "bf_asm_src",
3335         "md5_asm_src",
3336         "cast_asm_src",
3337         "sha1_asm_src",
3338         "rc4_asm_src",
3339         "rmd160_asm_src",
3340         "rc5_asm_src",
3341         "wp_asm_src",
3342         "cmll_asm_src",
3343         "modes_asm_src",
3344         "padlock_asm_src",
3345         "chacha_asm_src",
3346         "poly1035_asm_src",
3347         "thread_scheme",
3348         "perlasm_scheme",
3349         "dso_scheme",
3350         "shared_target",
3351         "shared_cflag",
3352         "shared_defines",
3353         "shared_ldflag",
3354         "shared_rcflag",
3355         "shared_extension",
3356         "dso_extension",
3357         "obj_extension",
3358         "exe_extension",
3359         "ranlib",
3360         "ar",
3361         "arflags",
3362         "aroutflag",
3363         "rc",
3364         "rcflags",
3365         "rcoutflag",
3366         "mt",
3367         "mtflags",
3368         "mtinflag",
3369         "mtoutflag",
3370         "multilib",
3371         "build_scheme",
3372         );
3373
3374     if ($type eq "TABLE") {
3375         print "\n";
3376         print "*** $now_printing\n";
3377         foreach (@sequence) {
3378             if (ref($target{$_}) eq "ARRAY") {
3379                 printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
3380             } else {
3381                 printf "\$%-12s = %s\n", $_, $target{$_};
3382             }
3383         }
3384     } elsif ($type eq "HASH") {
3385         my $largest =
3386             length((sort { length($a) <=> length($b) } @sequence)[-1]);
3387         print "    '$now_printing' => {\n";
3388         foreach (@sequence) {
3389             if ($target{$_}) {
3390                 if (ref($target{$_}) eq "ARRAY") {
3391                     print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
3392                 } else {
3393                     print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
3394                 }
3395             }
3396         }
3397         print "    },\n";
3398     }
3399 }
3400
3401 # Utility routines ###################################################
3402
3403 # On VMS, if the given file is a logical name, File::Spec::Functions
3404 # will consider it an absolute path.  There are cases when we want a
3405 # purely syntactic check without checking the environment.
3406 sub isabsolute {
3407     my $file = shift;
3408
3409     # On non-platforms, we just use file_name_is_absolute().
3410     return file_name_is_absolute($file) unless $^O eq "VMS";
3411
3412     # If the file spec includes a device or a directory spec,
3413     # file_name_is_absolute() is perfectly safe.
3414     return file_name_is_absolute($file) if $file =~ m|[:\[]|;
3415
3416     # Here, we know the given file spec isn't absolute
3417     return 0;
3418 }
3419
3420 # Makes a directory absolute and cleans out /../ in paths like foo/../bar
3421 # On some platforms, this uses rel2abs(), while on others, realpath() is used.
3422 # realpath() requires that at least all path components except the last is an
3423 # existing directory.  On VMS, the last component of the directory spec must
3424 # exist.
3425 sub absolutedir {
3426     my $dir = shift;
3427
3428     # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
3429     # will return the volume name for the device, no matter what.  Also,
3430     # it will return an incorrect directory spec if the argument is a
3431     # directory that doesn't exist.
3432     if ($^O eq "VMS") {
3433         return rel2abs($dir);
3434     }
3435
3436     # We use realpath() on Unix, since no other will properly clean out
3437     # a directory spec.
3438     use Cwd qw/realpath/;
3439
3440     return realpath($dir);
3441 }
3442
3443 # Check if all paths are one and the same, using stat.  They must both exist
3444 # We need this for the cases when File::Spec doesn't detect case insensitivity
3445 # (File::Spec::Unix assumes case sensitivity)
3446 sub samedir {
3447     die "samedir expects two arguments\n" unless scalar @_ == 2;
3448
3449     my @stat0 = stat($_[0]);    # First argument
3450     my @stat1 = stat($_[1]);    # Second argument
3451
3452     die "Couldn't stat $_[0]" unless @stat0;
3453     die "Couldn't stat $_[1]" unless @stat1;
3454
3455     # Compare device number
3456     return 0 unless ($stat0[0] == $stat1[0]);
3457     # Compare "inode".  The perl manual recommends comparing as
3458     # string rather than as number.
3459     return 0 unless ($stat0[1] eq $stat1[1]);
3460
3461     return 1;                   # All the same
3462 }
3463
3464 sub quotify {
3465     my %processors = (
3466         perl    => sub { my $x = shift;
3467                          $x =~ s/([\\\$\@"])/\\$1/g;
3468                          return '"'.$x.'"'; },
3469         maybeshell => sub { my $x = shift;
3470                             (my $y = $x) =~ s/([\\\"])/\\$1/g;
3471                             if ($x ne $y || $x =~ m|\s|) {
3472                                 return '"'.$y.'"';
3473                             } else {
3474                                 return $x;
3475                             }
3476                         },
3477         );
3478     my $for = shift;
3479     my $processor =
3480         defined($processors{$for}) ? $processors{$for} : sub { shift; };
3481
3482     return map { $processor->($_); } @_;
3483 }
3484
3485 # collect_from_file($filename, $line_concat_cond_re, $line_concat)
3486 # $filename is a file name to read from
3487 # $line_concat_cond_re is a regexp detecting a line continuation ending
3488 # $line_concat is a CODEref that takes care of concatenating two lines
3489 sub collect_from_file {
3490     my $filename = shift;
3491     my $line_concat_cond_re = shift;
3492     my $line_concat = shift;
3493
3494     open my $fh, $filename || die "unable to read $filename: $!\n";
3495     return sub {
3496         my $saved_line = "";
3497         $_ = "";
3498         while (<$fh>) {
3499             s|\R$||;
3500             if (defined $line_concat) {
3501                 $_ = $line_concat->($saved_line, $_);
3502                 $saved_line = "";
3503             }
3504             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3505                 $saved_line = $_;
3506                 next;
3507             }
3508             return $_;
3509         }
3510         die "$filename ending with continuation line\n" if $_;
3511         close $fh;
3512         return undef;
3513     }
3514 }
3515
3516 # collect_from_array($array, $line_concat_cond_re, $line_concat)
3517 # $array is an ARRAYref of lines
3518 # $line_concat_cond_re is a regexp detecting a line continuation ending
3519 # $line_concat is a CODEref that takes care of concatenating two lines
3520 sub collect_from_array {
3521     my $array = shift;
3522     my $line_concat_cond_re = shift;
3523     my $line_concat = shift;
3524     my @array = (@$array);
3525
3526     return sub {
3527         my $saved_line = "";
3528         $_ = "";
3529         while (defined($_ = shift @array)) {
3530             s|\R$||;
3531             if (defined $line_concat) {
3532                 $_ = $line_concat->($saved_line, $_);
3533                 $saved_line = "";
3534             }
3535             if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
3536                 $saved_line = $_;
3537                 next;
3538             }
3539             return $_;
3540         }
3541         die "input text ending with continuation line\n" if $_;
3542         return undef;
3543     }
3544 }
3545
3546 # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
3547 # $lineiterator is a CODEref that delivers one line at a time.
3548 # All following arguments are regex/CODEref pairs, where the regexp detects a
3549 # line and the CODEref does something with the result of the regexp.
3550 sub collect_information {
3551     my $lineiterator = shift;
3552     my %collectors = @_;
3553
3554     while(defined($_ = $lineiterator->())) {
3555         s|\R$||;
3556         my $found = 0;
3557         if ($collectors{"BEFORE"}) {
3558             $collectors{"BEFORE"}->($_);
3559         }
3560         foreach my $re (keys %collectors) {
3561             if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
3562                 $collectors{$re}->($lineiterator);
3563                 $found = 1;
3564             };
3565         }
3566         if ($collectors{"OTHERWISE"}) {
3567             $collectors{"OTHERWISE"}->($lineiterator, $_)
3568                 unless $found || !defined $collectors{"OTHERWISE"};
3569         }
3570         if ($collectors{"AFTER"}) {
3571             $collectors{"AFTER"}->($_);
3572         }
3573     }
3574 }
3575
3576 # tokenize($line)
3577 # $line is a line of text to split up into tokens
3578 # returns a list of tokens
3579 #
3580 # Tokens are divided by spaces.  If the tokens include spaces, they
3581 # have to be quoted with single or double quotes.  Double quotes
3582 # inside a double quoted token must be escaped.  Escaping is done
3583 # with backslash.
3584 # Basically, the same quoting rules apply for " and ' as in any
3585 # Unix shell.
3586 sub tokenize {
3587     my $line = my $debug_line = shift;
3588     my @result = ();
3589
3590     while ($line =~ s|^\s+||, $line ne "") {
3591         my $token = "";
3592         while ($line ne "" && $line !~ m|^\s|) {
3593             if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
3594                 $token .= $1;
3595                 $line = $';
3596             } elsif ($line =~ m/^'([^']*)'/) {
3597                 $token .= $1;
3598                 $line = $';
3599             } elsif ($line =~ m/^(\S+)/) {
3600                 $token .= $1;
3601                 $line = $';
3602             }
3603         }
3604         push @result, $token;
3605     }
3606
3607     if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
3608         print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
3609         print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
3610     }
3611     return @result;
3612 }