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