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