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