xref: /netbsd-src/crypto/external/bsd/openssl/dist/Configure (revision 7d9ffdb3e9da593a05c5e2169f72fc7bada08bc9)
15af53050Schristos#! /usr/bin/env perl
25af53050Schristos# -*- mode: perl; -*-
3b46c97feSchristos# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
45af53050Schristos#
58fbed61eSchristos# Licensed under the Apache License 2.0 (the "License").  You may not use
65af53050Schristos# this file except in compliance with the License.  You can obtain a copy
75af53050Schristos# in the file LICENSE in the source distribution or at
85af53050Schristos# https://www.openssl.org/source/license.html
9a89c9211Schristos
105af53050Schristos##  Configure -- OpenSSL source tree configuration script
115af53050Schristos
125af53050Schristosuse 5.10.0;
13a89c9211Schristosuse strict;
14e0ea3921Schristosuse Config;
1578327f04Schristosuse FindBin;
1678327f04Schristosuse lib "$FindBin::Bin/util/perl";
175af53050Schristosuse File::Basename;
188fbed61eSchristosuse File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/;
195af53050Schristosuse File::Path qw/mkpath/;
208fbed61eSchristosuse OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
2178327f04Schristosuse OpenSSL::Glob;
228fbed61eSchristosuse OpenSSL::Template;
238fbed61eSchristosuse OpenSSL::config;
24a89c9211Schristos
258fbed61eSchristos# see INSTALL.md for instructions.
26a89c9211Schristos
272500041cSchristosmy $orig_death_handler = $SIG{__DIE__};
282500041cSchristos$SIG{__DIE__} = \&death_handler;
292500041cSchristos
304261787cSchristosmy $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";
31a89c9211Schristos
328fbed61eSchristosmy $banner = <<"EOF";
338fbed61eSchristos
348fbed61eSchristos**********************************************************************
358fbed61eSchristos***                                                                ***
368fbed61eSchristos***   OpenSSL has been successfully configured                     ***
378fbed61eSchristos***                                                                ***
388fbed61eSchristos***   If you encounter a problem while building, please open an    ***
398fbed61eSchristos***   issue on GitHub <https://github.com/openssl/openssl/issues>  ***
408fbed61eSchristos***   and include the output from the following command:           ***
418fbed61eSchristos***                                                                ***
428fbed61eSchristos***       perl configdata.pm --dump                                ***
438fbed61eSchristos***                                                                ***
448fbed61eSchristos***   (If you are new to OpenSSL, you might want to consult the    ***
458fbed61eSchristos***   'Troubleshooting' section in the INSTALL.md file first)      ***
468fbed61eSchristos***                                                                ***
478fbed61eSchristos**********************************************************************
488fbed61eSchristosEOF
498fbed61eSchristos
50a89c9211Schristos# Options:
51a89c9211Schristos#
525af53050Schristos# --config      add the given configuration file, which will be read after
535af53050Schristos#               any "Configurations*" files that are found in the same
545af53050Schristos#               directory as this script.
555af53050Schristos# --prefix      prefix for the OpenSSL installation, which includes the
565af53050Schristos#               directories bin, lib, include, share/man, share/doc/openssl
575af53050Schristos#               This becomes the value of INSTALLTOP in Makefile
585af53050Schristos#               (Default: /usr/local)
595af53050Schristos# --openssldir  OpenSSL data area, such as openssl.cnf, certificates and keys.
605af53050Schristos#               If it's a relative directory, it will be added on the directory
615af53050Schristos#               given with --prefix.
625af53050Schristos#               This becomes the value of OPENSSLDIR in Makefile and in C.
635af53050Schristos#               (Default: PREFIX/ssl)
648fbed61eSchristos# --banner=".." Output specified text instead of default completion banner
658fbed61eSchristos#
668fbed61eSchristos# -w            Don't wait after showing a Configure warning
67a89c9211Schristos#
68a89c9211Schristos# --cross-compile-prefix Add specified prefix to binutils components.
69a89c9211Schristos#
708fbed61eSchristos# --api         One of 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, or 3.0
718fbed61eSchristos#               Define the public APIs as they were for that version
728fbed61eSchristos#               including patch releases.  If 'no-deprecated' is also
738fbed61eSchristos#               given, do not compile support for interfaces deprecated
748fbed61eSchristos#               up to and including the specified OpenSSL version.
755af53050Schristos#
76a89c9211Schristos# no-hw-xxx     do not compile support for specific crypto hardware.
77a89c9211Schristos#               Generic OpenSSL-style methods relating to this support
78a89c9211Schristos#               are always compiled but return NULL if the hardware
79a89c9211Schristos#               support isn't compiled.
80a89c9211Schristos# no-hw         do not compile support for any crypto hardware.
81a89c9211Schristos# [no-]threads  [don't] try to create a library that is suitable for
82a89c9211Schristos#               multithreaded applications (default is "threads" if we
83a89c9211Schristos#               know how to do it)
84a89c9211Schristos# [no-]shared   [don't] try to create shared libraries when supported.
855af53050Schristos# [no-]pic      [don't] try to build position independent code when supported.
865af53050Schristos#               If disabled, it also disables shared and dynamic-engine.
87a89c9211Schristos# no-asm        do not use assembler
885af53050Schristos# no-egd        do not compile support for the entropy-gathering daemon APIs
89a89c9211Schristos# [no-]zlib     [don't] compile support for zlib compression.
90a89c9211Schristos# zlib-dynamic  Like "zlib", but the zlib library is expected to be a shared
91a89c9211Schristos#               library and will be loaded in run-time by the OpenSSL library.
92e3d33c04Schristos# sctp          include SCTP support
938fbed61eSchristos# no-uplink     Don't build support for UPLINK interface.
94338c2544Schristos# enable-weak-ssl-ciphers
955af53050Schristos#               Enable weak ciphers that are disabled by default.
96b367ed38Sspz# 386           generate 80386 code in assembly modules
97b367ed38Sspz# no-sse2       disables IA-32 SSE2 code in assembly modules, the above
98b367ed38Sspz#               mentioned '386' option implies this one
998fbed61eSchristos# no-<cipher>   build without specified algorithm (dsa, idea, rc5, ...)
10052629741Schristos# -<xxx> +<xxx> All options which are unknown to the 'Configure' script are
10152629741Schristos# /<xxx>        passed through to the compiler. Unix-style options beginning
10252629741Schristos#               with a '-' or '+' are recognized, as well as Windows-style
10352629741Schristos#               options beginning with a '/'. If the option contains arguments
10452629741Schristos#               separated by spaces, then the URL-style notation %20 can be
10552629741Schristos#               used for the space character in order to avoid having to quote
10652629741Schristos#               the option. For example, -opt%20arg gets expanded to -opt arg.
10752629741Schristos#               In fact, any ASCII character can be encoded as %xx using its
10852629741Schristos#               hexadecimal encoding.
1095af53050Schristos# -static       while -static is also a pass-through compiler option (and
1105af53050Schristos#               as such is limited to environments where it's actually
1115af53050Schristos#               meaningful), it triggers a number configuration options,
1124261787cSchristos#               namely no-pic, no-shared and no-threads. It is
1135af53050Schristos#               argued that the only reason to produce statically linked
1145af53050Schristos#               binaries (and in context it means executables linked with
1155af53050Schristos#               -static flag, and not just executables linked with static
1165af53050Schristos#               libcrypto.a) is to eliminate dependency on specific run-time,
1175af53050Schristos#               a.k.a. libc version. The mentioned config options are meant
1185af53050Schristos#               to achieve just that. Unfortunately on Linux it's impossible
1195af53050Schristos#               to eliminate the dependency completely for openssl executable
1205af53050Schristos#               because of getaddrinfo and gethostbyname calls, which can
1215af53050Schristos#               invoke dynamically loadable library facility anyway to meet
1225af53050Schristos#               the lookup requests. For this reason on Linux statically
1235af53050Schristos#               linked openssl executable has rather debugging value than
1245af53050Schristos#               production quality.
125a89c9211Schristos#
126a89c9211Schristos# BN_LLONG      use the type 'long long' in crypto/bn/bn.h
127a89c9211Schristos# RC4_CHAR      use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
128a89c9211Schristos# Following are set automatically by this script
129a89c9211Schristos#
1305af53050Schristos# MD5_ASM       use some extra md5 assembler,
1315af53050Schristos# SHA1_ASM      use some extra sha1 assembler, must define L_ENDIAN for x86
1325af53050Schristos# RMD160_ASM    use some extra ripemd160 assembler,
133a89c9211Schristos# SHA256_ASM    sha256_block is implemented in assembler
134a89c9211Schristos# SHA512_ASM    sha512_block is implemented in assembler
1355af53050Schristos# AES_ASM       AES_[en|de]crypt is implemented in assembler
136a89c9211Schristos
1374261787cSchristos# Minimum warning options... any contributions to OpenSSL should at least
1384261787cSchristos# get past these.  Note that we only use these with C compilers, not with
1394261787cSchristos# C++ compilers.
140a89c9211Schristos
1415af53050Schristos# -DPEDANTIC complements -pedantic and is meant to mask code that
1425af53050Schristos# is not strictly standard-compliant and/or implementation-specific,
1435af53050Schristos# e.g. inline assembly, disregards to alignment requirements, such
1445af53050Schristos# that -pedantic would complain about. Incidentally -DPEDANTIC has
1455af53050Schristos# to be used even in sanitized builds, because sanitizer too is
1465af53050Schristos# supposed to and does take notice of non-standard behaviour. Then
1475af53050Schristos# -pedantic with pre-C9x compiler would also complain about 'long
1485af53050Schristos# long' not being supported. As 64-bit algorithms are common now,
1495af53050Schristos# it grew impossible to resolve this without sizeable additional
1505af53050Schristos# code, so we just tell compiler to be pedantic about everything
1515af53050Schristos# but 'long long' type.
152e0ea3921Schristos
1534261787cSchristosmy @gcc_devteam_warn = qw(
1548fbed61eSchristos    -DPEDANTIC -pedantic -Wno-long-long -DUNUSEDRESULT_DEBUG
1554261787cSchristos    -Wall
1568fbed61eSchristos    -Wmissing-declarations
1574261787cSchristos    -Wextra
1584261787cSchristos    -Wno-unused-parameter
1594261787cSchristos    -Wno-missing-field-initializers
1604261787cSchristos    -Wswitch
1614261787cSchristos    -Wsign-compare
1624261787cSchristos    -Wshadow
1634261787cSchristos    -Wformat
1644261787cSchristos    -Wtype-limits
1654261787cSchristos    -Wundef
1664261787cSchristos    -Werror
1674261787cSchristos    -Wmissing-prototypes
1684261787cSchristos    -Wstrict-prototypes
1694261787cSchristos);
17031b855a0Sspz
17131b855a0Sspz# These are used in addition to $gcc_devteam_warn when the compiler is clang.
17231b855a0Sspz# TODO(openssl-team): fix problems and investigate if (at least) the
1735af53050Schristos# following warnings can also be enabled:
1745af53050Schristos#       -Wcast-align
175e0ea3921Schristos#       -Wunreachable-code -- no, too ugly/compiler-specific
1765af53050Schristos#       -Wlanguage-extension-token -- no, we use asm()
1775af53050Schristos#       -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
1785af53050Schristos#       -Wextended-offsetof -- no, needed in CMS ASN1 code
1794261787cSchristosmy @clang_devteam_warn = qw(
180403eeac4Schristos    -Wno-unknown-warning-option
1814261787cSchristos    -Wno-parentheses-equality
1824261787cSchristos    -Wno-language-extension-token
1834261787cSchristos    -Wno-extended-offsetof
1844261787cSchristos    -Wconditional-uninitialized
1854261787cSchristos    -Wincompatible-pointer-types-discards-qualifiers
1864261787cSchristos    -Wmissing-variable-declarations
1874261787cSchristos);
18831b855a0Sspz
18952629741Schristosmy @cl_devteam_warn = qw(
19052629741Schristos    /WX
19152629741Schristos);
19252629741Schristos
193cef2ee70Schristosmy $strict_warnings = 0;
194cef2ee70Schristos
195a89c9211Schristos# As for $BSDthreads. Idea is to maintain "collective" set of flags,
196a89c9211Schristos# which would cover all BSD flavors. -pthread applies to them all,
197a89c9211Schristos# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
198a89c9211Schristos# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
199a89c9211Schristos# which has to be accompanied by explicit -D_THREAD_SAFE and
200a89c9211Schristos# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
201a89c9211Schristos# seems to be sufficient?
2025af53050Schristosour $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
203a89c9211Schristos
204a89c9211Schristos#
2055af53050Schristos# API compatibility name to version number mapping.
206a89c9211Schristos#
2075af53050Schristosmy $apitable = {
2088fbed61eSchristos    # This table expresses when API additions or changes can occur.
2098fbed61eSchristos    # The numbering used changes from 3.0 and on because we updated
2108fbed61eSchristos    # (solidified) our version numbering scheme at that point.
2118fbed61eSchristos
2128fbed61eSchristos    # From 3.0 and on, we internalise the given version number in decimal
2138fbed61eSchristos    # as MAJOR * 10000 + MINOR * 100 + 0
2148fbed61eSchristos    "3.0.0" => 30000,
2158fbed61eSchristos    "3.0"   => 30000,
2168fbed61eSchristos
2178fbed61eSchristos    # Note that before 3.0, we didn't have the same version number scheme.
2188fbed61eSchristos    # Still, the numbering we use here covers what we need.
2198fbed61eSchristos    "1.1.1" => 10101,
2208fbed61eSchristos    "1.1.0" => 10100,
2218fbed61eSchristos    "1.0.2" => 10002,
2228fbed61eSchristos    "1.0.1" => 10001,
2238fbed61eSchristos    "1.0.0" => 10000,
2248fbed61eSchristos    "0.9.8" =>   908,
2255af53050Schristos};
2265af53050Schristos
2278fbed61eSchristos# For OpenSSL::config::get_platform
2288fbed61eSchristosmy %guess_opts = ();
2298fbed61eSchristos
2308fbed61eSchristosmy $dryrun = 0;
2318fbed61eSchristos
2325af53050Schristosour %table = ();
2335af53050Schristosour %config = ();
2345af53050Schristosour %withargs = ();
235e0ea3921Schristosour $now_printing;      # set to current entry's name in print_table_entry
236e0ea3921Schristos                        # (todo: right thing would be to encapsulate name
237e0ea3921Schristos                        # into %target [class] and make print_table_entry
238e0ea3921Schristos                        # a method)
2395af53050Schristos
2405af53050Schristos# Forward declarations ###############################################
2415af53050Schristos
2425af53050Schristos# read_config(filename)
243a89c9211Schristos#
2445af53050Schristos# Reads a configuration file and populates %table with the contents
2455af53050Schristos# (which the configuration file places in %targets).
2465af53050Schristossub read_config;
247a89c9211Schristos
2485af53050Schristos# resolve_config(target)
249a89c9211Schristos#
2505af53050Schristos# Resolves all the late evaluations, inheritances and so on for the
2515af53050Schristos# chosen target and any target it inherits from.
2525af53050Schristossub resolve_config;
253a89c9211Schristos
254a89c9211Schristos
2555af53050Schristos# Information collection #############################################
256a89c9211Schristos
2575af53050Schristos# Unified build supports separate build dir
2585af53050Schristosmy $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
2595af53050Schristosmy $blddir = catdir(absolutedir("."));         # catdir ensures local syntax
2604a7cf967Schristos
2614a7cf967Schristos# File::Spec::Unix doesn't detect case insensitivity, so we make sure to
2624a7cf967Schristos# check if the source and build directory are really the same, and make
2634a7cf967Schristos# them so.  This avoids all kinds of confusion later on.
2644a7cf967Schristos# We must check @File::Spec::ISA rather than using File::Spec->isa() to
2654a7cf967Schristos# know if File::Spec ended up loading File::Spec::Unix.
2664a7cf967Schristos$srcdir = $blddir
2674a7cf967Schristos    if (grep(/::Unix$/, @File::Spec::ISA)
2684a7cf967Schristos        && samedir($srcdir, $blddir));
2694a7cf967Schristos
2705af53050Schristosmy $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
271a89c9211Schristos
2725af53050Schristosmy $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
273a89c9211Schristos
2744a7cf967Schristos$config{sourcedir} = abs2rel($srcdir, $blddir);
2754a7cf967Schristos$config{builddir} = abs2rel($blddir, $blddir);
2768fbed61eSchristos# echo -n 'holy hand grenade of antioch' | openssl sha256
2778fbed61eSchristos$config{FIPSKEY} =
2788fbed61eSchristos    'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813';
279a89c9211Schristos
2805af53050Schristos# Collect reconfiguration information if needed
2815af53050Schristosmy @argvcopy=@ARGV;
282a89c9211Schristos
2835af53050Schristosif (grep /^reconf(igure)?$/, @argvcopy) {
284e0ea3921Schristos    die "reconfiguring with other arguments present isn't supported"
285e0ea3921Schristos        if scalar @argvcopy > 1;
2865af53050Schristos    if (-f "./configdata.pm") {
2875af53050Schristos        my $file = "./configdata.pm";
2885af53050Schristos        unless (my $return = do $file) {
2895af53050Schristos            die "couldn't parse $file: $@" if $@;
2905af53050Schristos            die "couldn't do $file: $!"    unless defined $return;
2915af53050Schristos            die "couldn't run $file"       unless $return;
292e3d33c04Schristos        }
293a89c9211Schristos
2945af53050Schristos        @argvcopy = defined($configdata::config{perlargv}) ?
2955af53050Schristos            @{$configdata::config{perlargv}} : ();
2965af53050Schristos        die "Incorrect data to reconfigure, please do a normal configuration\n"
2975af53050Schristos            if (grep(/^reconf/,@argvcopy));
298e0ea3921Schristos        $config{perlenv} = $configdata::config{perlenv} // {};
2995af53050Schristos    } else {
3005af53050Schristos        die "Insufficient data to reconfigure, please do a normal configuration\n";
3015af53050Schristos    }
3025af53050Schristos}
3035af53050Schristos
3045af53050Schristos$config{perlargv} = [ @argvcopy ];
3055af53050Schristos
3068fbed61eSchristos# Historical: if known directories in crypto/ have been removed, it means
3078fbed61eSchristos# that those sub-systems are disabled.
3088fbed61eSchristos# (the other option would be to removed them from the SUBDIRS statement in
3098fbed61eSchristos# crypto/build.info)
3108fbed61eSchristos# We reverse the input list for cosmetic purely reasons, to compensate that
3118fbed61eSchristos# 'unshift' adds at the front of the list (i.e. in reverse input order).
3128fbed61eSchristosforeach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh',
3138fbed61eSchristos                        'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2',
3148fbed61eSchristos                        'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha',
3158fbed61eSchristos                        'sm2', 'sm3', 'sm4') ) {
3168fbed61eSchristos    unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_);
3178fbed61eSchristos}
3188fbed61eSchristos
3195af53050Schristos# Collect version numbers
3208fbed61eSchristosmy %version = ();
3215af53050Schristos
3225af53050Schristoscollect_information(
3238fbed61eSchristos    collect_from_file(catfile($srcdir,'VERSION.dat')),
3248fbed61eSchristos    qr/\s*(\w+)\s*=\s*(.*?)\s*$/ =>
3258fbed61eSchristos        sub {
3268fbed61eSchristos            # Only define it if there is a value at all
3278fbed61eSchristos            if ($2 ne '') {
3288fbed61eSchristos                my $k = $1;
3298fbed61eSchristos                my $v = $2;
3308fbed61eSchristos                # Some values are quoted.  Trim the quotes
3318fbed61eSchristos                $v = $1 if $v =~ /^"(.*)"$/;
3328fbed61eSchristos                $version{uc $k} = $v;
3338fbed61eSchristos            }
3348fbed61eSchristos        },
3358fbed61eSchristos    "OTHERWISE" =>
3368fbed61eSchristos        sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" },
3375af53050Schristos    );
3385af53050Schristos
3398fbed61eSchristos$config{major} = $version{MAJOR} // 'unknown';
3408fbed61eSchristos$config{minor} = $version{MINOR} // 'unknown';
3418fbed61eSchristos$config{patch} = $version{PATCH} // 'unknown';
3428fbed61eSchristos$config{prerelease} =
3438fbed61eSchristos    defined $version{PRE_RELEASE_TAG} ? "-$version{PRE_RELEASE_TAG}" : '';
3448fbed61eSchristos$config{build_metadata} =
3458fbed61eSchristos    defined $version{BUILD_METADATA} ? "+$version{BUILD_METADATA}" : '';
3468fbed61eSchristos$config{shlib_version} = $version{SHLIB_VERSION} // 'unknown';
3478fbed61eSchristos$config{release_date} = $version{RELEASE_DATE} // 'xx XXX xxxx';
3488fbed61eSchristos
3498fbed61eSchristos$config{version} = "$config{major}.$config{minor}.$config{patch}";
3508fbed61eSchristos$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}";
3518fbed61eSchristos
3528fbed61eSchristosdie "erroneous version information in VERSION.dat: ",
3538fbed61eSchristos    "$config{version}, $config{shlib_version}\n"
3548fbed61eSchristos    unless (defined $version{MAJOR}
3558fbed61eSchristos            && defined $version{MINOR}
3568fbed61eSchristos            && defined $version{PATCH}
3578fbed61eSchristos            && defined $version{SHLIB_VERSION});
3585af53050Schristos
3595af53050Schristos# Collect target configurations
3605af53050Schristos
3615af53050Schristosmy $pattern = catfile(dirname($0), "Configurations", "*.conf");
3625af53050Schristosforeach (sort glob($pattern)) {
3635af53050Schristos    &read_config($_);
3645af53050Schristos}
3655af53050Schristos
366e0ea3921Schristosif (defined env($local_config_envname)) {
3675af53050Schristos    if ($^O eq 'VMS') {
3685af53050Schristos        # VMS environment variables are logical names,
3695af53050Schristos        # which can be used as is
3705af53050Schristos        $pattern = $local_config_envname . ':' . '*.conf';
3715af53050Schristos    } else {
372e0ea3921Schristos        $pattern = catfile(env($local_config_envname), '*.conf');
3735af53050Schristos    }
3745af53050Schristos
3755af53050Schristos    foreach (sort glob($pattern)) {
3765af53050Schristos        &read_config($_);
3775af53050Schristos    }
3785af53050Schristos}
3795af53050Schristos
380e0ea3921Schristos# Save away perl command information
381e0ea3921Schristos$config{perl_cmd} = $^X;
382e0ea3921Schristos$config{perl_version} = $Config{version};
383e0ea3921Schristos$config{perl_archname} = $Config{archname};
3845af53050Schristos
3855af53050Schristos$config{prefix}="";
3865af53050Schristos$config{openssldir}="";
3875af53050Schristos$config{processor}="";
3885af53050Schristos$config{libdir}="";
3895af53050Schristosmy $auto_threads=1;    # enable threads automatically? true by default
3905af53050Schristosmy $default_ranlib;
3915af53050Schristos
3925af53050Schristos# Known TLS and DTLS protocols
393e0ea3921Schristosmy @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
3945af53050Schristosmy @dtls = qw(dtls1 dtls1_2);
3955af53050Schristos
3965af53050Schristos# Explicitly known options that are possible to disable.  They can
3975af53050Schristos# be regexps, and will be used like this: /^no-${option}$/
3985af53050Schristos# For developers: keep it sorted alphabetically
3995af53050Schristos
4005af53050Schristosmy @disablables = (
4018fbed61eSchristos    "acvp-tests",
4025af53050Schristos    "afalgeng",
403e0ea3921Schristos    "aria",
4045af53050Schristos    "asan",
4055af53050Schristos    "asm",
4065af53050Schristos    "async",
407b46c97feSchristos    "atexit",
4085af53050Schristos    "autoalginit",
4095af53050Schristos    "autoerrinit",
410e0ea3921Schristos    "autoload-config",
4115af53050Schristos    "bf",
4125af53050Schristos    "blake2",
4138fbed61eSchristos    "buildtest-c++",
4148fbed61eSchristos    "bulk",
4158fbed61eSchristos    "cached-fetch",
4165af53050Schristos    "camellia",
4175af53050Schristos    "capieng",
4185af53050Schristos    "cast",
4195af53050Schristos    "chacha",
4205af53050Schristos    "cmac",
4218fbed61eSchristos    "cmp",
4225af53050Schristos    "cms",
4235af53050Schristos    "comp",
4245af53050Schristos    "crypto-mdebug",
4255af53050Schristos    "ct",
4265af53050Schristos    "deprecated",
4275af53050Schristos    "des",
428e0ea3921Schristos    "devcryptoeng",
4295af53050Schristos    "dgram",
4305af53050Schristos    "dh",
4315af53050Schristos    "dsa",
43252629741Schristos    "dso",
4335af53050Schristos    "dtls",
4345af53050Schristos    "dynamic-engine",
4355af53050Schristos    "ec",
4365af53050Schristos    "ec2m",
4378fbed61eSchristos    "ec_nistp_64_gcc_128",
4385af53050Schristos    "ecdh",
4395af53050Schristos    "ecdsa",
4405af53050Schristos    "egd",
4415af53050Schristos    "engine",
4425af53050Schristos    "err",
443e0ea3921Schristos    "external-tests",
4445af53050Schristos    "filenames",
4458fbed61eSchristos    "fips",
4468fbed61eSchristos    "fips-securitychecks",
4475af53050Schristos    "fuzz-afl",
4488fbed61eSchristos    "fuzz-libfuzzer",
4495af53050Schristos    "gost",
4505af53050Schristos    "idea",
4518fbed61eSchristos    "ktls",
4528fbed61eSchristos    "legacy",
4538fbed61eSchristos    "loadereng",
4545af53050Schristos    "makedepend",
4555af53050Schristos    "md2",
4565af53050Schristos    "md4",
4575af53050Schristos    "mdc2",
4588fbed61eSchristos    "module",
4595af53050Schristos    "msan",
4605af53050Schristos    "multiblock",
4615af53050Schristos    "nextprotoneg",
4625af53050Schristos    "ocb",
4635af53050Schristos    "ocsp",
4648fbed61eSchristos    "padlockeng",
4655af53050Schristos    "pic",
4668fbed61eSchristos    "pinshared",
4675af53050Schristos    "poly1305",
4685af53050Schristos    "posix-io",
4695af53050Schristos    "psk",
4705af53050Schristos    "rc2",
4715af53050Schristos    "rc4",
4725af53050Schristos    "rc5",
4735af53050Schristos    "rdrand",
4745af53050Schristos    "rfc3779",
4755af53050Schristos    "rmd160",
4765af53050Schristos    "scrypt",
4775af53050Schristos    "sctp",
4788fbed61eSchristos    "secure-memory",
4795af53050Schristos    "seed",
4805af53050Schristos    "shared",
481e0ea3921Schristos    "siphash",
4828fbed61eSchristos    "siv",
483e0ea3921Schristos    "sm2",
484e0ea3921Schristos    "sm3",
485e0ea3921Schristos    "sm4",
4865af53050Schristos    "sock",
4875af53050Schristos    "srp",
4885af53050Schristos    "srtp",
4895af53050Schristos    "sse2",
4905af53050Schristos    "ssl",
4915af53050Schristos    "ssl-trace",
4925af53050Schristos    "static-engine",
4935af53050Schristos    "stdio",
494e0ea3921Schristos    "tests",
4955af53050Schristos    "threads",
4965af53050Schristos    "tls",
4978fbed61eSchristos    "trace",
4985af53050Schristos    "ts",
4995af53050Schristos    "ubsan",
500e0ea3921Schristos    "ui-console",
5015af53050Schristos    "unit-test",
5028fbed61eSchristos    "uplink",
5035af53050Schristos    "weak-ssl-ciphers",
5048fbed61eSchristos    "whirlpool",
5055af53050Schristos    "zlib",
5065af53050Schristos    "zlib-dynamic",
5075af53050Schristos    );
5085af53050Schristosforeach my $proto ((@tls, @dtls))
5095af53050Schristos        {
5105af53050Schristos        push(@disablables, $proto);
511e0ea3921Schristos        push(@disablables, "$proto-method") unless $proto eq "tls1_3";
5125af53050Schristos        }
5135af53050Schristos
5148fbed61eSchristos# Internal disablables, for aliasing purposes.  They serve no special
5158fbed61eSchristos# purpose here, but allow scripts to get to know them through configdata.pm,
5168fbed61eSchristos# where these are merged with @disablables.
5178fbed61eSchristos# The actual aliasing mechanism is done via %disable_cascades
5188fbed61eSchristosmy @disablables_int = qw(
5198fbed61eSchristos    crmf
5208fbed61eSchristos    );
5218fbed61eSchristos
5225af53050Schristosmy %deprecated_disablables = (
5235af53050Schristos    "ssl2" => undef,
5245af53050Schristos    "buf-freelists" => undef,
5258fbed61eSchristos    "crypto-mdebug-backtrace" => undef,
5268fbed61eSchristos    "hw" => "hw",               # causes cascade, but no macro
5278fbed61eSchristos    "hw-padlock" => "padlockeng",
528e0ea3921Schristos    "ripemd" => "rmd160",
529e0ea3921Schristos    "ui" => "ui-console",
5308fbed61eSchristos    "heartbeats" => undef,
5315af53050Schristos    );
5325af53050Schristos
533e0ea3921Schristos# All of the following are disabled by default:
534a89c9211Schristos
5355af53050Schristosour %disabled = ( # "what"         => "comment"
5368fbed61eSchristos                  "fips"                => "default",
5375af53050Schristos                  "asan"                => "default",
5384261787cSchristos                  "buildtest-c++"       => "default",
5395af53050Schristos                  "crypto-mdebug"       => "default",
5405af53050Schristos                  "crypto-mdebug-backtrace" => "default",
541e0ea3921Schristos                  "devcryptoeng"        => "default",
542e3d33c04Schristos                  "ec_nistp_64_gcc_128" => "default",
5435af53050Schristos                  "egd"                 => "default",
544e0ea3921Schristos                  "external-tests"      => "default",
5455af53050Schristos                  "fuzz-afl"            => "default",
5468fbed61eSchristos                  "fuzz-libfuzzer"      => "default",
5478fbed61eSchristos                  "ktls"                => "default",
548a89c9211Schristos                  "md2"                 => "default",
5495af53050Schristos                  "msan"                => "default",
550a89c9211Schristos                  "rc5"                 => "default",
551e3d33c04Schristos                  "sctp"                => "default",
5525af53050Schristos                  "ssl3"                => "default",
5535af53050Schristos                  "ssl3-method"         => "default",
5548fbed61eSchristos                  "trace"               => "default",
5555af53050Schristos                  "ubsan"               => "default",
5563beda010Sspz                  "unit-test"           => "default",
557338c2544Schristos                  "weak-ssl-ciphers"    => "default",
558a89c9211Schristos                  "zlib"                => "default",
5595af53050Schristos                  "zlib-dynamic"        => "default",
560a89c9211Schristos                );
561a89c9211Schristos
5625af53050Schristos# Note: => pair form used for aesthetics, not to truly make a hash table
5635af53050Schristosmy @disable_cascades = (
5645af53050Schristos    # "what"            => [ "cascade", ... ]
5658fbed61eSchristos    "bulk"              => [ "shared", "dso",
5668fbed61eSchristos                             "aria", "async", "autoload-config",
5678fbed61eSchristos                             "blake2", "bf", "camellia", "cast", "chacha",
5688fbed61eSchristos                             "cmac", "cms", "cmp", "comp", "ct",
5698fbed61eSchristos                             "des", "dgram", "dh", "dsa",
5708fbed61eSchristos                             "ec", "engine",
5718fbed61eSchristos                             "filenames",
5728fbed61eSchristos                             "idea", "ktls",
5738fbed61eSchristos                             "md4", "multiblock", "nextprotoneg",
5748fbed61eSchristos                             "ocsp", "ocb", "poly1305", "psk",
5758fbed61eSchristos                             "rc2", "rc4", "rmd160",
5768fbed61eSchristos                             "seed", "siphash", "siv",
5778fbed61eSchristos                             "sm3", "sm4", "srp",
5788fbed61eSchristos                             "srtp", "ssl3-method", "ssl-trace",
5798fbed61eSchristos                             "ts", "ui-console", "whirlpool",
5808fbed61eSchristos                             "fips-securitychecks" ],
5815af53050Schristos    sub { $config{processor} eq "386" }
5825af53050Schristos                        => [ "sse2" ],
5835af53050Schristos    "ssl"               => [ "ssl3" ],
5845af53050Schristos    "ssl3-method"       => [ "ssl3" ],
5855af53050Schristos    "zlib"              => [ "zlib-dynamic" ],
5865af53050Schristos    "des"               => [ "mdc2" ],
5878fbed61eSchristos    "ec"                => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ],
5885af53050Schristos    "dgram"             => [ "dtls", "sctp" ],
5895af53050Schristos    "sock"              => [ "dgram" ],
5905af53050Schristos    "dtls"              => [ @dtls ],
5915af53050Schristos    sub { 0 == scalar grep { !$disabled{$_} } @dtls }
5925af53050Schristos                        => [ "dtls" ],
5935af53050Schristos
5945af53050Schristos    "tls"               => [ @tls ],
5955af53050Schristos    sub { 0 == scalar grep { !$disabled{$_} } @tls }
5965af53050Schristos                        => [ "tls" ],
5975af53050Schristos
5985af53050Schristos    "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
5995af53050Schristos
6008dcce544Schristos    "module"            => [ "dynamic-engine", "fips" ],
6018fbed61eSchristos
6028fbed61eSchristos    # Without shared libraries, dynamic engines aren't possible.
6038fbed61eSchristos    # This is due to them having to link with libcrypto and register features
6048fbed61eSchristos    # using the ENGINE functionality, and since that relies on global tables,
6058fbed61eSchristos    # those *have* to be exacty the same as the ones accessed from the app,
6068fbed61eSchristos    # which cannot be guaranteed if shared libraries aren't present.
6078fbed61eSchristos    # (note that even with shared libraries, both the app and dynamic engines
6088fbed61eSchristos    # must be linked with the same library)
6098fbed61eSchristos    "shared"            => [ "dynamic-engine", "uplink" ],
6108fbed61eSchristos    "dso"               => [ "dynamic-engine", "module" ],
6118fbed61eSchristos    # Other modules don't necessarily have to link with libcrypto, so shared
6128fbed61eSchristos    # libraries do not have to be a condition to produce those.
6138fbed61eSchristos
6148fbed61eSchristos    # Without position independent code, there can be no shared libraries
6158fbed61eSchristos    # or modules.
6168fbed61eSchristos    "pic"               => [ "shared", "module" ],
6178fbed61eSchristos
6188fbed61eSchristos    "engine"            => [ "dynamic-engine", grep(/eng$/, @disablables) ],
6198fbed61eSchristos    "dynamic-engine"    => [ "loadereng" ],
6208fbed61eSchristos    "hw"                => [ "padlockeng" ],
6215af53050Schristos
6225af53050Schristos    # no-autoalginit is only useful when building non-shared
6238fbed61eSchristos    "autoalginit"       => [ "shared", "apps", "fips" ],
6245af53050Schristos
6255af53050Schristos    "stdio"             => [ "apps", "capieng", "egd" ],
6265af53050Schristos    "apps"              => [ "tests" ],
627e0ea3921Schristos    "tests"             => [ "external-tests" ],
6285af53050Schristos    "comp"              => [ "zlib" ],
629e0ea3921Schristos    "sm3"               => [ "sm2" ],
6305af53050Schristos    sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
6315af53050Schristos
6325af53050Schristos    sub { !$disabled{"msan"} } => [ "asm" ],
6338fbed61eSchristos
6348fbed61eSchristos    "cmac"              => [ "siv" ],
6358fbed61eSchristos    "legacy"            => [ "md2" ],
6368fbed61eSchristos
6378fbed61eSchristos    "cmp"               => [ "crmf" ],
6388fbed61eSchristos
6398fbed61eSchristos    "fips"              => [ "fips-securitychecks", "acvp-tests" ],
6408fbed61eSchristos
6418fbed61eSchristos    "deprecated-3.0"    => [ "engine", "srp" ]
6425af53050Schristos    );
6435af53050Schristos
6445af53050Schristos# Avoid protocol support holes.  Also disable all versions below N, if version
6455af53050Schristos# N is disabled while N+1 is enabled.
6465af53050Schristos#
6475af53050Schristosmy @list = (reverse @tls);
6485af53050Schristoswhile ((my $first, my $second) = (shift @list, shift @list)) {
6495af53050Schristos    last unless @list;
6505af53050Schristos    push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
6515af53050Schristos                              => [ @list ] );
6525af53050Schristos    unshift @list, $second;
6535af53050Schristos}
6545af53050Schristosmy @list = (reverse @dtls);
6555af53050Schristoswhile ((my $first, my $second) = (shift @list, shift @list)) {
6565af53050Schristos    last unless @list;
6575af53050Schristos    push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
6585af53050Schristos                              => [ @list ] );
6595af53050Schristos    unshift @list, $second;
6605af53050Schristos}
661a89c9211Schristos
662a89c9211Schristos# Explicit "no-..." options will be collected in %disabled along with the defaults.
6635af53050Schristos# To remove something from %disabled, use "enable-foo".
664a89c9211Schristos# For symmetry, "disable-foo" is a synonym for "no-foo".
665a89c9211Schristos
66652629741Schristos# For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with
667e0ea3921Schristos# platform specific list separators.  Users from those platforms should
668e0ea3921Schristos# recognise those separators from how you set up the PATH to find executables.
669e0ea3921Schristos# The default is the Unix like separator, :, but as an exception, we also
670e0ea3921Schristos# support the space as separator.
671e0ea3921Schristosmy $list_separator_re =
672e0ea3921Schristos    { VMS           => qr/(?<!\^),/,
673e0ea3921Schristos      MSWin32       => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/;
674e0ea3921Schristos# All the "make variables" we support
675e0ea3921Schristos# Some get pre-populated for the sake of backward compatibility
676e0ea3921Schristos# (we supported those before the change to "make variable" support.
677e0ea3921Schristosmy %user = (
678e0ea3921Schristos    AR          => env('AR'),
679e0ea3921Schristos    ARFLAGS     => [],
680e0ea3921Schristos    AS          => undef,
681e0ea3921Schristos    ASFLAGS     => [],
682e0ea3921Schristos    CC          => env('CC'),
6834261787cSchristos    CFLAGS      => [ env('CFLAGS') || () ],
684e0ea3921Schristos    CXX         => env('CXX'),
6854261787cSchristos    CXXFLAGS    => [ env('CXXFLAGS') || () ],
686e0ea3921Schristos    CPP         => undef,
6874261787cSchristos    CPPFLAGS    => [ env('CPPFLAGS') || () ],  # -D, -I, -Wp,
688e0ea3921Schristos    CPPDEFINES  => [],  # Alternative for -D
689e0ea3921Schristos    CPPINCLUDES => [],  # Alternative for -I
690e0ea3921Schristos    CROSS_COMPILE => env('CROSS_COMPILE'),
691e0ea3921Schristos    HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'),
692e0ea3921Schristos    LD          => undef,
6934261787cSchristos    LDFLAGS     => [ env('LDFLAGS') || () ],  # -L, -Wl,
6944261787cSchristos    LDLIBS      => [ env('LDLIBS') || () ],  # -l
695e0ea3921Schristos    MT          => undef,
696e0ea3921Schristos    MTFLAGS     => [],
697e0ea3921Schristos    PERL        => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
698e0ea3921Schristos    RANLIB      => env('RANLIB'),
699e0ea3921Schristos    RC          => env('RC') || env('WINDRES'),
7004261787cSchristos    RCFLAGS     => [ env('RCFLAGS') || () ],
701e0ea3921Schristos    RM          => undef,
702e0ea3921Schristos   );
703e0ea3921Schristos# Info about what "make variables" may be prefixed with the cross compiler
704e0ea3921Schristos# prefix.  This should NEVER mention any such variable with a list for value.
705e0ea3921Schristosmy @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC );
706e0ea3921Schristos# The same but for flags given as Configure options.  These are *additional*
707e0ea3921Schristos# input, as opposed to the VAR=string option that override the corresponding
708e0ea3921Schristos# config target attributes
709e0ea3921Schristosmy %useradd = (
710e0ea3921Schristos    CPPDEFINES  => [],
711e0ea3921Schristos    CPPINCLUDES => [],
712e0ea3921Schristos    CPPFLAGS    => [],
713e0ea3921Schristos    CFLAGS      => [],
714e0ea3921Schristos    CXXFLAGS    => [],
715e0ea3921Schristos    LDFLAGS     => [],
716e0ea3921Schristos    LDLIBS      => [],
7174261787cSchristos    RCFLAGS     => [],
718e0ea3921Schristos   );
719e0ea3921Schristos
720e0ea3921Schristosmy %user_synonyms = (
721e0ea3921Schristos    HASHBANGPERL=> 'PERL',
722e0ea3921Schristos    RC          => 'WINDRES',
723e0ea3921Schristos   );
724e0ea3921Schristos
725e0ea3921Schristos# Some target attributes have been renamed, this is the translation table
726e0ea3921Schristosmy %target_attr_translate =(
727e0ea3921Schristos    ar          => 'AR',
728e0ea3921Schristos    as          => 'AS',
729e0ea3921Schristos    cc          => 'CC',
730e0ea3921Schristos    cxx         => 'CXX',
731e0ea3921Schristos    cpp         => 'CPP',
732e0ea3921Schristos    hashbangperl => 'HASHBANGPERL',
733e0ea3921Schristos    ld          => 'LD',
734e0ea3921Schristos    mt          => 'MT',
735e0ea3921Schristos    ranlib      => 'RANLIB',
736e0ea3921Schristos    rc          => 'RC',
737e0ea3921Schristos    rm          => 'RM',
738e0ea3921Schristos   );
739e0ea3921Schristos
740e0ea3921Schristos# Initialisers coming from 'config' scripts
741e0ea3921Schristos$config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ];
742e0ea3921Schristos$config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ];
743e0ea3921Schristos$config{cppflags} = [ env('__CNF_CPPFLAGS') || () ];
744e0ea3921Schristos$config{cflags} = [ env('__CNF_CFLAGS') || () ];
745e0ea3921Schristos$config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ];
746e0ea3921Schristos$config{lflags} = [ env('__CNF_LDFLAGS') || () ];
747e0ea3921Schristos$config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
748e0ea3921Schristos
7495af53050Schristos$config{openssl_api_defines}=[];
7505af53050Schristos$config{openssl_sys_defines}=[];
7518fbed61eSchristos$config{openssl_feature_defines}=[];
7525af53050Schristos$config{options}="";
7535af53050Schristos$config{build_type} = "release";
754e0ea3921Schristosmy $target="";
755a89c9211Schristos
756e0ea3921Schristosmy %cmdvars = ();               # Stores FOO='blah' type arguments
7575af53050Schristosmy %unsupported_options = ();
7585af53050Schristosmy %deprecated_options = ();
759e0ea3921Schristos# If you change this, update apps/version.c
760e0ea3921Schristosmy @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
761e0ea3921Schristosmy @seed_sources = ();
7625af53050Schristoswhile (@argvcopy)
763a89c9211Schristos        {
7645af53050Schristos        $_ = shift @argvcopy;
765e0ea3921Schristos
766e0ea3921Schristos        # Support env variable assignments among the options
767e0ea3921Schristos        if (m|^(\w+)=(.+)?$|)
768e0ea3921Schristos                {
769e0ea3921Schristos                $cmdvars{$1} = $2;
770e0ea3921Schristos                # Every time a variable is given as a configuration argument,
771e0ea3921Schristos                # it acts as a reset if the variable.
772e0ea3921Schristos                if (exists $user{$1})
773e0ea3921Schristos                        {
774e0ea3921Schristos                        $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
775e0ea3921Schristos                        }
776e0ea3921Schristos                #if (exists $useradd{$1})
777e0ea3921Schristos                #       {
778e0ea3921Schristos                #       $useradd{$1} = [];
779e0ea3921Schristos                #       }
780e0ea3921Schristos                next;
781e0ea3921Schristos                }
782e0ea3921Schristos
7835af53050Schristos        # VMS is a case insensitive environment, and depending on settings
7845af53050Schristos        # out of our control, we may receive options uppercased.  Let's
7855af53050Schristos        # downcase at least the part before any equal sign.
7865af53050Schristos        if ($^O eq "VMS")
787a89c9211Schristos                {
7885af53050Schristos                s/^([^=]*)/lc($1)/e;
7895af53050Schristos                }
790e0ea3921Schristos
791e0ea3921Schristos        # some people just can't read the instructions, clang people have to...
792e0ea3921Schristos        s/^-no-(?!integrated-as)/no-/;
793a89c9211Schristos
794a89c9211Schristos        # rewrite some options in "enable-..." form
795a89c9211Schristos        s /^-?-?shared$/enable-shared/;
796e3d33c04Schristos        s /^sctp$/enable-sctp/;
797a89c9211Schristos        s /^threads$/enable-threads/;
798a89c9211Schristos        s /^zlib$/enable-zlib/;
799a89c9211Schristos        s /^zlib-dynamic$/enable-zlib-dynamic/;
8008fbed61eSchristos        s /^fips$/enable-fips/;
801a89c9211Schristos
8025af53050Schristos        if (/^(no|disable|enable)-(.+)$/)
8035af53050Schristos                {
8045af53050Schristos                my $word = $2;
8058fbed61eSchristos                if ($word !~ m|hw(?:-.+)| # special treatment for hw regexp opt
8068fbed61eSchristos                        && !exists $deprecated_disablables{$word}
8078fbed61eSchristos                        && !grep { $word eq $_ } @disablables)
8085af53050Schristos                        {
8095af53050Schristos                        $unsupported_options{$_} = 1;
8105af53050Schristos                        next;
8115af53050Schristos                        }
8125af53050Schristos                }
813a89c9211Schristos        if (/^no-(.+)$/ || /^disable-(.+)$/)
814a89c9211Schristos                {
8155af53050Schristos                foreach my $proto ((@tls, @dtls))
816a89c9211Schristos                        {
8175af53050Schristos                        if ($1 eq "$proto-method")
818a89c9211Schristos                                {
8195af53050Schristos                                $disabled{"$proto"} = "option($proto-method)";
8205af53050Schristos                                last;
8215af53050Schristos                                }
8225af53050Schristos                        }
8235af53050Schristos                if ($1 eq "dtls")
8245af53050Schristos                        {
8255af53050Schristos                        foreach my $proto (@dtls)
8265af53050Schristos                                {
8275af53050Schristos                                $disabled{$proto} = "option(dtls)";
8285af53050Schristos                                }
8295af53050Schristos                        $disabled{"dtls"} = "option(dtls)";
8305af53050Schristos                        }
8315af53050Schristos                elsif ($1 eq "ssl")
8325af53050Schristos                        {
8335af53050Schristos                        # Last one of its kind
834a89c9211Schristos                        $disabled{"ssl3"} = "option(ssl)";
835a89c9211Schristos                        }
836a89c9211Schristos                elsif ($1 eq "tls")
837a89c9211Schristos                        {
8385af53050Schristos                        # XXX: Tests will fail if all SSL/TLS
8395af53050Schristos                        # protocols are disabled.
8405af53050Schristos                        foreach my $proto (@tls)
841805debc4Sspz                                {
8425af53050Schristos                                $disabled{$proto} = "option(tls)";
8435af53050Schristos                                }
8445af53050Schristos                        }
8455af53050Schristos                elsif ($1 eq "static-engine")
8465af53050Schristos                        {
8475af53050Schristos                        delete $disabled{"dynamic-engine"};
8485af53050Schristos                        }
8495af53050Schristos                elsif ($1 eq "dynamic-engine")
8505af53050Schristos                        {
8515af53050Schristos                        $disabled{"dynamic-engine"} = "option";
8525af53050Schristos                        }
8535af53050Schristos                elsif (exists $deprecated_disablables{$1})
8545af53050Schristos                        {
8555af53050Schristos                        $deprecated_options{$_} = 1;
8565af53050Schristos                        if (defined $deprecated_disablables{$1})
8575af53050Schristos                                {
8585af53050Schristos                                $disabled{$deprecated_disablables{$1}} = "option";
8595af53050Schristos                                }
860805debc4Sspz                        }
8618fbed61eSchristos                elsif ($1 =~ m|hw(?:-.+)|) # deprecate hw options in regexp form
8628fbed61eSchristos                        {
8638fbed61eSchristos                        $deprecated_options{$_} = 1;
8644261787cSchristos                        }
865a89c9211Schristos                else
866a89c9211Schristos                        {
867a89c9211Schristos                        $disabled{$1} = "option";
868a89c9211Schristos                        }
8695af53050Schristos                # No longer an automatic choice
8705af53050Schristos                $auto_threads = 0 if ($1 eq "threads");
871a89c9211Schristos                }
8725af53050Schristos        elsif (/^enable-(.+)$/)
873a89c9211Schristos                {
8745af53050Schristos                if ($1 eq "static-engine")
8755af53050Schristos                        {
8765af53050Schristos                        $disabled{"dynamic-engine"} = "option";
8775af53050Schristos                        }
8785af53050Schristos                elsif ($1 eq "dynamic-engine")
8795af53050Schristos                        {
8805af53050Schristos                        delete $disabled{"dynamic-engine"};
8815af53050Schristos                        }
8825af53050Schristos                elsif ($1 eq "zlib-dynamic")
8835af53050Schristos                        {
8845af53050Schristos                        delete $disabled{"zlib"};
8855af53050Schristos                        }
886a89c9211Schristos                my $algo = $1;
887a89c9211Schristos                delete $disabled{$algo};
888a89c9211Schristos
8895af53050Schristos                # No longer an automatic choice
8905af53050Schristos                $auto_threads = 0 if ($1 eq "threads");
891a89c9211Schristos                }
8928fbed61eSchristos        elsif (/^-d$/)          # From older 'config'
8938fbed61eSchristos                {
8948fbed61eSchristos                $config{build_type} = "debug";
8958fbed61eSchristos                }
8968fbed61eSchristos        elsif (/^-v$/)          # From older 'config'
8978fbed61eSchristos                {
8988fbed61eSchristos                $guess_opts{verbose} = 1;
8998fbed61eSchristos                }
9008fbed61eSchristos        elsif (/^-w$/)
9018fbed61eSchristos                {
9028fbed61eSchristos                $guess_opts{nowait} = 1;
9038fbed61eSchristos                }
9048fbed61eSchristos        elsif (/^-t$/)          # From older 'config'
9058fbed61eSchristos                {
9068fbed61eSchristos                $dryrun = 1;
9078fbed61eSchristos                }
9085af53050Schristos        elsif (/^--strict-warnings$/)
909cef2ee70Schristos                {
9104261787cSchristos                # Pretend that our strict flags is a C flag, and replace it
9114261787cSchristos                # with the proper flags later on
9124261787cSchristos                push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
913cef2ee70Schristos                $strict_warnings=1;
914cef2ee70Schristos                }
9155af53050Schristos        elsif (/^--debug$/)
916a89c9211Schristos                {
9175af53050Schristos                $config{build_type} = "debug";
918a89c9211Schristos                }
9195af53050Schristos        elsif (/^--release$/)
9205af53050Schristos                {
9215af53050Schristos                $config{build_type} = "release";
922a89c9211Schristos                }
923a89c9211Schristos        elsif (/^386$/)
9245af53050Schristos                { $config{processor}=386; }
925a89c9211Schristos        elsif (/^rsaref$/)
926a89c9211Schristos                {
927a89c9211Schristos                # No RSAref support any more since it's not needed.
928a89c9211Schristos                # The check for the option is there so scripts aren't
929a89c9211Schristos                # broken
930a89c9211Schristos                }
93152629741Schristos        elsif (m|^[-+/]|)
932a89c9211Schristos                {
93331b855a0Sspz                if (/^--prefix=(.*)$/)
934a89c9211Schristos                        {
9355af53050Schristos                        $config{prefix}=$1;
9365af53050Schristos                        }
9375af53050Schristos                elsif (/^--api=(.*)$/)
9385af53050Schristos                        {
9398fbed61eSchristos                        my $api = $1;
9408fbed61eSchristos                        die "Unknown API compatibility level $api"
9418fbed61eSchristos                                unless defined $apitable->{$api};
9428fbed61eSchristos                        $config{api}=$apitable->{$api};
943a89c9211Schristos                        }
944cef2ee70Schristos                elsif (/^--libdir=(.*)$/)
945cef2ee70Schristos                        {
9465af53050Schristos                        $config{libdir}=$1;
947cef2ee70Schristos                        }
948a89c9211Schristos                elsif (/^--openssldir=(.*)$/)
949a89c9211Schristos                        {
9505af53050Schristos                        $config{openssldir}=$1;
951a89c9211Schristos                        }
952a89c9211Schristos                elsif (/^--with-zlib-lib=(.*)$/)
953a89c9211Schristos                        {
9545af53050Schristos                        $withargs{zlib_lib}=$1;
955a89c9211Schristos                        }
956a89c9211Schristos                elsif (/^--with-zlib-include=(.*)$/)
957a89c9211Schristos                        {
9585af53050Schristos                        $withargs{zlib_include}=$1;
959a89c9211Schristos                        }
9605af53050Schristos                elsif (/^--with-fuzzer-lib=(.*)$/)
9614e3dcb23Sspz                        {
9625af53050Schristos                        $withargs{fuzzer_lib}=$1;
9635af53050Schristos                        }
9645af53050Schristos                elsif (/^--with-fuzzer-include=(.*)$/)
9655af53050Schristos                        {
9665af53050Schristos                        $withargs{fuzzer_include}=$1;
9674e3dcb23Sspz                        }
968e0ea3921Schristos                elsif (/^--with-rand-seed=(.*)$/)
9694e3dcb23Sspz                        {
970e0ea3921Schristos                        foreach my $x (split(m|,|, $1))
971e0ea3921Schristos                            {
972e0ea3921Schristos                            die "Unknown --with-rand-seed choice $x\n"
973e0ea3921Schristos                                if ! grep { $x eq $_ } @known_seed_sources;
974e0ea3921Schristos                            push @seed_sources, $x;
9754e3dcb23Sspz                            }
9764e3dcb23Sspz                        }
9778fbed61eSchristos                elsif (/^--fips-key=(.*)$/)
9788fbed61eSchristos                        {
9798fbed61eSchristos                        $user{FIPSKEY}=lc($1);
9808fbed61eSchristos                        die "Non-hex character in FIPS key\n"
9818fbed61eSchristos                           if $user{FIPSKEY} =~ /[^a-f0-9]/;
9828fbed61eSchristos                        die "FIPS key must have even number of characters\n"
9838fbed61eSchristos                           if length $1 & 1;
9848fbed61eSchristos                        die "FIPS key too long (64 bytes max)\n"
9858fbed61eSchristos                           if length $1 > 64;
9868fbed61eSchristos                        }
9878fbed61eSchristos                elsif (/^--banner=(.*)$/)
9888fbed61eSchristos                        {
9898fbed61eSchristos                        $banner = $1 . "\n";
9908fbed61eSchristos                        }
991a89c9211Schristos                elsif (/^--cross-compile-prefix=(.*)$/)
992a89c9211Schristos                        {
993e0ea3921Schristos                        $user{CROSS_COMPILE}=$1;
9945af53050Schristos                        }
9955af53050Schristos                elsif (/^--config=(.*)$/)
9965af53050Schristos                        {
9975af53050Schristos                        read_config $1;
998a89c9211Schristos                        }
999e0ea3921Schristos                elsif (/^-l(.*)$/)
1000a89c9211Schristos                        {
1001e0ea3921Schristos                        push @{$useradd{LDLIBS}}, $_;
1002e0ea3921Schristos                        }
1003e0ea3921Schristos                elsif (/^-framework$/)
1004e0ea3921Schristos                        {
1005e0ea3921Schristos                        push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
1006e0ea3921Schristos                        }
1007e0ea3921Schristos                elsif (/^-L(.*)$/ or /^-Wl,/)
1008e0ea3921Schristos                        {
1009e0ea3921Schristos                        push @{$useradd{LDFLAGS}}, $_;
101031b855a0Sspz                        }
10115af53050Schristos                elsif (/^-rpath$/ or /^-R$/)
10125af53050Schristos                        # -rpath is the OSF1 rpath flag
10135af53050Schristos                        # -R is the old Solaris rpath flag
10145af53050Schristos                        {
10155af53050Schristos                        my $rpath = shift(@argvcopy) || "";
10165af53050Schristos                        $rpath .= " " if $rpath ne "";
1017e0ea3921Schristos                        push @{$useradd{LDFLAGS}}, $_, $rpath;
10185af53050Schristos                        }
10195af53050Schristos                elsif (/^-static$/)
10205af53050Schristos                        {
1021e0ea3921Schristos                        push @{$useradd{LDFLAGS}}, $_;
10225af53050Schristos                        }
102352629741Schristos                elsif (m|^[-/]D(.*)$|)
10245af53050Schristos                        {
1025e0ea3921Schristos                        push @{$useradd{CPPDEFINES}}, $1;
1026e0ea3921Schristos                        }
102752629741Schristos                elsif (m|^[-/]I(.*)$|)
1028e0ea3921Schristos                        {
1029e0ea3921Schristos                        push @{$useradd{CPPINCLUDES}}, $1;
1030e0ea3921Schristos                        }
1031e0ea3921Schristos                elsif (/^-Wp,$/)
1032e0ea3921Schristos                        {
1033e0ea3921Schristos                        push @{$useradd{CPPFLAGS}}, $1;
10345af53050Schristos                        }
103531b855a0Sspz                else    # common if (/^[-+]/), just pass down...
103631b855a0Sspz                        {
103752629741Schristos                        # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
103852629741Schristos                        # This provides a simple way to pass options with arguments separated
103952629741Schristos                        # by spaces without quoting (e.g. -opt%20arg translates to -opt arg).
104031b855a0Sspz                        $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
1041e0ea3921Schristos                        push @{$useradd{CFLAGS}}, $_;
1042e0ea3921Schristos                        push @{$useradd{CXXFLAGS}}, $_;
1043a89c9211Schristos                        }
1044a89c9211Schristos                }
104552629741Schristos        elsif (m|^/|)
104652629741Schristos                {
104752629741Schristos                # Treat %xx as an ASCII code (e.g. replace %20 by a space character).
104852629741Schristos                # This provides a simple way to pass options with arguments separated
104952629741Schristos                # by spaces without quoting (e.g. /opt%20arg translates to /opt arg).
105052629741Schristos                $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
105152629741Schristos                push @{$useradd{CFLAGS}}, $_;
105252629741Schristos                push @{$useradd{CXXFLAGS}}, $_;
105352629741Schristos                }
1054a89c9211Schristos        else
1055a89c9211Schristos                {
1056a89c9211Schristos                die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
1057a89c9211Schristos                $target=$_;
1058a89c9211Schristos                }
1059a89c9211Schristos        unless ($_ eq $target || /^no-/ || /^disable-/)
1060a89c9211Schristos                {
1061e0ea3921Schristos                # "no-..." follows later after implied deactivations
10625af53050Schristos                # have been derived.  (Don't take this too seriously,
1063a89c9211Schristos                # we really only write OPTIONS to the Makefile out of
1064a89c9211Schristos                # nostalgia.)
1065a89c9211Schristos
10665af53050Schristos                if ($config{options} eq "")
10675af53050Schristos                        { $config{options} = $_; }
1068a89c9211Schristos                else
10695af53050Schristos                        { $config{options} .= " ".$_; }
1070a89c9211Schristos                }
10712500041cSchristos        }
1072a89c9211Schristos
10735af53050Schristosif (keys %deprecated_options)
1074a89c9211Schristos        {
10755af53050Schristos        warn "***** Deprecated options: ",
10765af53050Schristos                join(", ", keys %deprecated_options), "\n";
10775af53050Schristos        }
10785af53050Schristosif (keys %unsupported_options)
10795af53050Schristos        {
10805af53050Schristos        die "***** Unsupported options: ",
10815af53050Schristos                join(", ", keys %unsupported_options), "\n";
10825af53050Schristos        }
1083a89c9211Schristos
1084e0ea3921Schristos# If any %useradd entry has been set, we must check that the "make
1085e0ea3921Schristos# variables" haven't been set.  We start by checking of any %useradd entry
1086e0ea3921Schristos# is set.
1087e0ea3921Schristosif (grep { scalar @$_ > 0 } values %useradd) {
1088e0ea3921Schristos    # Hash of env / make variables names.  The possible values are:
1089e0ea3921Schristos    # 1 - "make vars"
1090e0ea3921Schristos    # 2 - %useradd entry set
1091e0ea3921Schristos    # 3 - both set
1092e0ea3921Schristos    my %detected_vars =
1093e0ea3921Schristos        map { my $v = 0;
1094e0ea3921Schristos              $v += 1 if $cmdvars{$_};
1095e0ea3921Schristos              $v += 2 if @{$useradd{$_}};
1096e0ea3921Schristos              $_ => $v }
1097e0ea3921Schristos        keys %useradd;
1098e0ea3921Schristos
1099e0ea3921Schristos    # If any of the corresponding "make variables" is set, we error
1100e0ea3921Schristos    if (grep { $_ & 1 } values %detected_vars) {
1101e0ea3921Schristos        my $names = join(', ', grep { $detected_vars{$_} > 0 }
1102e0ea3921Schristos                               sort keys %detected_vars);
1103e0ea3921Schristos        die <<"_____";
1104e0ea3921Schristos***** Mixing make variables and additional compiler/linker flags as
1105e0ea3921Schristos***** configure command line option is not permitted.
1106e0ea3921Schristos***** Affected make variables: $names
1107e0ea3921Schristos_____
1108e0ea3921Schristos    }
1109e0ea3921Schristos}
1110e0ea3921Schristos
1111e0ea3921Schristos# Check through all supported command line variables to see if any of them
1112e0ea3921Schristos# were set, and canonicalise the values we got.  If no compiler or linker
1113e0ea3921Schristos# flag or anything else that affects %useradd was set, we also check the
1114e0ea3921Schristos# environment for values.
1115e0ea3921Schristosmy $anyuseradd =
1116e0ea3921Schristos    grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
1117e0ea3921Schristosforeach (keys %user) {
1118e0ea3921Schristos    my $value = $cmdvars{$_};
1119e0ea3921Schristos    $value //= env($_) unless $anyuseradd;
1120e0ea3921Schristos    $value //=
1121e0ea3921Schristos        defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
1122e0ea3921Schristos    $value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
1123e0ea3921Schristos        unless $anyuseradd;
1124e0ea3921Schristos
1125e0ea3921Schristos    if (defined $value) {
1126e0ea3921Schristos        if (ref $user{$_} eq 'ARRAY') {
112752629741Schristos            if ($_ eq 'CPPDEFINES' || $_ eq 'CPPINCLUDES') {
1128e0ea3921Schristos                $user{$_} = [ split /$list_separator_re/, $value ];
112952629741Schristos            } else {
113052629741Schristos                $user{$_} = [ $value ];
113152629741Schristos            }
1132e0ea3921Schristos        } elsif (!defined $user{$_}) {
1133e0ea3921Schristos            $user{$_} = $value;
1134e0ea3921Schristos        }
1135e0ea3921Schristos    }
1136e0ea3921Schristos}
1137e0ea3921Schristos
1138e0ea3921Schristosif (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
11395af53050Schristos    && !$disabled{shared}
11405af53050Schristos    && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
11415af53050Schristos    die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
11425af53050Schristos        "***** any of asan, msan or ubsan\n";
1143a89c9211Schristos}
1144a89c9211Schristos
11458fbed61eSchristos# If no target was given, try guessing.
11468fbed61eSchristosunless ($target) {
11478fbed61eSchristos    my %system_config = OpenSSL::config::get_platform(%guess_opts, %user);
11488fbed61eSchristos
11498fbed61eSchristos    # The $system_config{disable} is used to populate %disabled with
11508fbed61eSchristos    # entries that aren't already there.
11518fbed61eSchristos    foreach ( @{$system_config{disable} // []} ) {
11528fbed61eSchristos        $disabled{$_} = 'system' unless defined $disabled{$_};
11538fbed61eSchristos    }
11548fbed61eSchristos    delete $system_config{disable};
11558fbed61eSchristos
11568fbed61eSchristos    # Override config entries with stuff from the guesser.
11578fbed61eSchristos    # It's assumed that this really is nothing new.
11588fbed61eSchristos    %config = ( %config, %system_config );
11598fbed61eSchristos    $target = $system_config{target};
11608fbed61eSchristos}
11618fbed61eSchristos
11624261787cSchristossub disable {
11634261787cSchristos    my $disable_type = shift;
11644261787cSchristos
11654261787cSchristos    for (@_) {
11664261787cSchristos        $disabled{$_} = $disable_type;
11674261787cSchristos    }
11684261787cSchristos
11694261787cSchristos    my @tocheckfor = (@_ ? @_ : keys %disabled);
11705af53050Schristos    while (@tocheckfor) {
11715af53050Schristos        my %new_tocheckfor = ();
11725af53050Schristos        my @cascade_copy = (@disable_cascades);
11735af53050Schristos        while (@cascade_copy) {
11744261787cSchristos            my ($test, $descendents) =
11754261787cSchristos                (shift @cascade_copy, shift @cascade_copy);
11765af53050Schristos            if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
11775af53050Schristos                foreach (grep { !defined($disabled{$_}) } @$descendents) {
11784261787cSchristos                    $new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
1179a89c9211Schristos                }
1180a89c9211Schristos            }
11815af53050Schristos        }
11825af53050Schristos        @tocheckfor = (keys %new_tocheckfor);
1183a89c9211Schristos    }
11844261787cSchristos}
11854261787cSchristosdisable();                     # First cascade run
1186a89c9211Schristos
11875af53050Schristosour $die = sub { die @_; };
1188a89c9211Schristosif ($target eq "TABLE") {
11895af53050Schristos    local $die = sub { warn @_; };
11905af53050Schristos    foreach (sort keys %table) {
11915af53050Schristos        print_table_entry($_, "TABLE");
1192a89c9211Schristos    }
1193a89c9211Schristos    exit 0;
1194a89c9211Schristos}
1195a89c9211Schristos
1196a89c9211Schristosif ($target eq "LIST") {
1197a89c9211Schristos    foreach (sort keys %table) {
11985af53050Schristos        print $_,"\n" unless $table{$_}->{template};
1199a89c9211Schristos    }
1200a89c9211Schristos    exit 0;
1201a89c9211Schristos}
1202a89c9211Schristos
12035af53050Schristosif ($target eq "HASH") {
12045af53050Schristos    local $die = sub { warn @_; };
12055af53050Schristos    print "%table = (\n";
12065af53050Schristos    foreach (sort keys %table) {
12075af53050Schristos        print_table_entry($_, "HASH");
12085af53050Schristos    }
12095af53050Schristos    exit 0;
12105af53050Schristos}
12115af53050Schristos
12128fbed61eSchristosprint "Configuring OpenSSL version $config{full_version} ";
12138fbed61eSchristosprint "for target $target\n";
1214e0ea3921Schristos
1215e0ea3921Schristosif (scalar(@seed_sources) == 0) {
1216e0ea3921Schristos    print "Using os-specific seed configuration\n";
1217e0ea3921Schristos    push @seed_sources, 'os';
1218e0ea3921Schristos}
12194a7cf967Schristosif (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) {
12204a7cf967Schristos    delete $disabled{'egd'};
12214a7cf967Schristos}
1222e0ea3921Schristosif (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
1223e0ea3921Schristos    die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
1224e0ea3921Schristos    warn <<_____ if scalar(@seed_sources) == 1;
1225e0ea3921Schristos
1226bf8eace1Schristos============================== WARNING ===============================
1227bf8eace1SchristosYou have selected the --with-rand-seed=none option, which effectively
1228bf8eace1Schristosdisables automatic reseeding of the OpenSSL random generator.
1229bf8eace1SchristosAll operations depending on the random generator such as creating keys
1230bf8eace1Schristoswill not work unless the random generator is seeded manually by the
1231bf8eace1Schristosapplication.
1232bf8eace1Schristos
1233bf8eace1SchristosPlease read the 'Note on random number generation' section in the
12348fbed61eSchristosINSTALL.md instructions and the RAND_DRBG(7) manual page for more
12358fbed61eSchristosdetails.
1236bf8eace1Schristos============================== WARNING ===============================
1237bf8eace1Schristos
1238e0ea3921Schristos_____
1239e0ea3921Schristos}
12408fbed61eSchristospush @{$config{openssl_feature_defines}},
1241e0ea3921Schristos     map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
1242e0ea3921Schristos        @seed_sources;
1243e0ea3921Schristos
12445af53050Schristos# Backward compatibility?
1245a89c9211Schristosif ($target =~ m/^CygWin32(-.*)$/) {
1246a89c9211Schristos    $target = "Cygwin".$1;
1247a89c9211Schristos}
1248a89c9211Schristos
12495af53050Schristos# Support for legacy targets having a name starting with 'debug-'
12505af53050Schristosmy ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
12515af53050Schristosif ($d) {
12525af53050Schristos    $config{build_type} = "debug";
12535af53050Schristos
12545af53050Schristos    # If we do not find debug-foo in the table, the target is set to foo.
12555af53050Schristos    if (!$table{$target}) {
12565af53050Schristos        $target = $t;
12575af53050Schristos    }
12585af53050Schristos}
12592500041cSchristos
12608fbed61eSchristosif ($target) {
12618fbed61eSchristos    # It's possible that we have different config targets for specific
12628fbed61eSchristos    # toolchains, so we try to detect them, and go for the plain config
12638fbed61eSchristos    # target if not.
12648fbed61eSchristos    my $found;
12658fbed61eSchristos    foreach ( ( "$target-$user{CC}", "$target", undef ) ) {
12668fbed61eSchristos        $found=$_ if $table{$_} && !$table{$_}->{template};
12678fbed61eSchristos        last if $found;
12688fbed61eSchristos    }
12698fbed61eSchristos    $target = $found;
12708fbed61eSchristos} else {
12718fbed61eSchristos    # If we don't have a config target now, we try the C compiler as we
12728fbed61eSchristos    # fallback
12738fbed61eSchristos    my $cc = $user{CC} // 'cc';
12748fbed61eSchristos    $target = $cc if $table{$cc} && !$table{$cc}->{template};
12758fbed61eSchristos}
12768fbed61eSchristos
12778fbed61eSchristos&usage unless $target;
12788fbed61eSchristos
12798fbed61eSchristosexit 0 if $dryrun;              # From older 'config'
12802500041cSchristos
12815af53050Schristos$config{target} = $target;
12825af53050Schristosmy %target = resolve_config($target);
12835af53050Schristos
1284e0ea3921Schristosforeach (keys %target_attr_translate) {
1285e0ea3921Schristos    $target{$target_attr_translate{$_}} = $target{$_}
1286e0ea3921Schristos        if $target{$_};
1287e0ea3921Schristos    delete $target{$_};
1288e0ea3921Schristos}
1289e0ea3921Schristos
12905af53050Schristos%target = ( %{$table{DEFAULTS}}, %target );
12915af53050Schristos
1292e0ea3921Schristosmy %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
1293e0ea3921Schristos$config{conf_files} = [ sort keys %conf_files ];
1294e0ea3921Schristos
12954261787cSchristos# Using sub disable within these loops may prove fragile, so we run
12964261787cSchristos# a cascade afterwards
1297e0ea3921Schristosforeach my $feature (@{$target{disable}}) {
1298e0ea3921Schristos    if (exists $deprecated_disablables{$feature}) {
1299e0ea3921Schristos        warn "***** config $target disables deprecated feature $feature\n";
1300e0ea3921Schristos    } elsif (!grep { $feature eq $_ } @disablables) {
1301e0ea3921Schristos        die "***** config $target disables unknown feature $feature\n";
1302e0ea3921Schristos    }
1303e0ea3921Schristos    $disabled{$feature} = 'config';
1304e0ea3921Schristos}
1305e0ea3921Schristosforeach my $feature (@{$target{enable}}) {
130665b9e620Schristos    if ("default" eq ($disabled{$feature} // "")) {
1307e0ea3921Schristos        if (exists $deprecated_disablables{$feature}) {
1308e0ea3921Schristos            warn "***** config $target enables deprecated feature $feature\n";
1309e0ea3921Schristos        } elsif (!grep { $feature eq $_ } @disablables) {
1310e0ea3921Schristos            die "***** config $target enables unknown feature $feature\n";
1311e0ea3921Schristos        }
131265b9e620Schristos        delete $disabled{$feature};
1313e0ea3921Schristos    }
1314e0ea3921Schristos}
13158fbed61eSchristos
13168fbed61eSchristos# If uplink_arch isn't defined, disable uplink
13178fbed61eSchristos$disabled{uplink} = 'no uplink_arch' unless (defined $target{uplink_arch});
13188fbed61eSchristos# If asm_arch isn't defined, disable asm
13198fbed61eSchristos$disabled{asm} = 'no asm_arch' unless (defined $target{asm_arch});
13208fbed61eSchristos
13214261787cSchristosdisable();                      # Run a cascade now
1322e0ea3921Schristos
1323e0ea3921Schristos$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
1324e0ea3921Schristos$target{cxxflags}//=$target{cflags} if $target{CXX};
13258fbed61eSchristos$target{exe_extension}=".exe" if ($config{target} eq "DJGPP");
13265af53050Schristos$target{exe_extension}=".pm"  if ($config{target} =~ /vos/);
13275af53050Schristos
1328e0ea3921Schristos# Fill %config with values from %user, and in case those are undefined or
1329e0ea3921Schristos# empty, use values from %target (acting as a default).
1330e0ea3921Schristosforeach (keys %user) {
1331e0ea3921Schristos    my $ref_type = ref $user{$_};
13325af53050Schristos
1333e0ea3921Schristos    # Temporary function.  Takes an intended ref type (empty string or "ARRAY")
1334e0ea3921Schristos    # and a value that's to be coerced into that type.
1335e0ea3921Schristos    my $mkvalue = sub {
1336e0ea3921Schristos        my $type = shift;
1337e0ea3921Schristos        my $value = shift;
1338e0ea3921Schristos        my $undef_p = shift;
13395af53050Schristos
1340e0ea3921Schristos        die "Too many arguments for \$mkvalue" if @_;
1341e0ea3921Schristos
1342e0ea3921Schristos        while (ref $value eq 'CODE') {
1343e0ea3921Schristos            $value = $value->();
1344e0ea3921Schristos        }
1345e0ea3921Schristos
1346e0ea3921Schristos        if ($type eq 'ARRAY') {
1347e0ea3921Schristos            return undef unless defined $value;
1348e0ea3921Schristos            return undef if ref $value ne 'ARRAY' && !$value;
1349e0ea3921Schristos            return undef if ref $value eq 'ARRAY' && !@$value;
1350e0ea3921Schristos            return [ $value ] unless ref $value eq 'ARRAY';
1351e0ea3921Schristos        }
1352e0ea3921Schristos        return undef unless $value;
1353e0ea3921Schristos        return $value;
1354e0ea3921Schristos    };
1355e0ea3921Schristos
1356e0ea3921Schristos    $config{$_} =
1357e0ea3921Schristos        $mkvalue->($ref_type, $user{$_})
1358e0ea3921Schristos        || $mkvalue->($ref_type, $target{$_});
1359e0ea3921Schristos    delete $config{$_} unless defined $config{$_};
1360e0ea3921Schristos}
13615af53050Schristos
13624261787cSchristos# Finish up %config by appending things the user gave us on the command line
13634261787cSchristos# apart from "make variables"
13644261787cSchristosforeach (keys %useradd) {
13654261787cSchristos    # The must all be lists, so we assert that here
13664261787cSchristos    die "internal error: \$useradd{$_} isn't an ARRAY\n"
13674261787cSchristos        unless ref $useradd{$_} eq 'ARRAY';
13684261787cSchristos
13694261787cSchristos    if (defined $config{$_}) {
13704261787cSchristos        push @{$config{$_}}, @{$useradd{$_}};
13714261787cSchristos    } else {
13724261787cSchristos        $config{$_} = [ @{$useradd{$_}} ];
13734261787cSchristos    }
13744261787cSchristos}
13754261787cSchristos# At this point, we can forget everything about %user and %useradd,
13764261787cSchristos# because it's now all been merged into the corresponding $config entry
13774261787cSchristos
1378b46c97feSchristosif ($config{prefix} && !$config{CROSS_COMPILE}) {
1379b46c97feSchristos    die "Directory given with --prefix MUST be absolute\n"
1380b46c97feSchristos        unless file_name_is_absolute($config{prefix});
1381b46c97feSchristos}
1382b46c97feSchristos
13838fbed61eSchristosif (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) {
1384c50ed29dSchristos    disable('static', 'pic', 'threads');
1385c50ed29dSchristos}
1386c50ed29dSchristos
13875af53050Schristos# Allow overriding the build file name
1388e0ea3921Schristos$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
13895af53050Schristos
13905af53050Schristos# Make sure build_scheme is consistent.
13915af53050Schristos$target{build_scheme} = [ $target{build_scheme} ]
13925af53050Schristos    if ref($target{build_scheme}) ne "ARRAY";
13935af53050Schristos
13945af53050Schristosmy ($builder, $builder_platform, @builder_opts) =
13955af53050Schristos    @{$target{build_scheme}};
13965af53050Schristos
1397be43b372Schristosforeach my $checker (($builder_platform."-".$config{build_file}."-checker.pm",
13985af53050Schristos                      $builder_platform."-checker.pm")) {
13995af53050Schristos    my $checker_path = catfile($srcdir, "Configurations", $checker);
14005af53050Schristos    if (-f $checker_path) {
14015af53050Schristos        my $fn = $ENV{CONFIGURE_CHECKER_WARN}
14025af53050Schristos            ? sub { warn $@; } : sub { die $@; };
14035af53050Schristos        if (! do $checker_path) {
14045af53050Schristos            if ($@) {
14055af53050Schristos                $fn->($@);
14065af53050Schristos            } elsif ($!) {
14075af53050Schristos                $fn->($!);
14085af53050Schristos            } else {
14095af53050Schristos                $fn->("The detected tools didn't match the platform\n");
14105af53050Schristos            }
14115af53050Schristos        }
14125af53050Schristos        last;
14135af53050Schristos    }
14145af53050Schristos}
14155af53050Schristos
14165af53050Schristospush @{$config{defines}}, "NDEBUG"    if $config{build_type} eq "release";
14175af53050Schristos
1418e0ea3921Schristosif ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
1419a89c9211Schristos        {
1420e0ea3921Schristos        push @{$config{cflags}}, "-mno-cygwin";
1421e0ea3921Schristos        push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
1422e0ea3921Schristos        push @{$config{shared_ldflag}}, "-mno-cygwin";
1423a89c9211Schristos        }
1424a89c9211Schristos
1425e0ea3921Schristosif ($target =~ /linux.*-mips/ && !$disabled{asm}
1426d6e24a89Schristos        && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
142731b855a0Sspz        # minimally required architecture flags for assembly modules
1428e0ea3921Schristos        my $value;
1429e0ea3921Schristos        $value = '-mips2' if ($target =~ /mips32/);
1430e0ea3921Schristos        $value = '-mips3' if ($target =~ /mips64/);
1431e0ea3921Schristos        unshift @{$config{cflags}}, $value;
1432e0ea3921Schristos        unshift @{$config{cxxflags}}, $value if $config{CXX};
1433a89c9211Schristos}
1434a89c9211Schristos
14355af53050Schristos# If threads aren't disabled, check how possible they are
14365af53050Schristosunless ($disabled{threads}) {
14375af53050Schristos    if ($auto_threads) {
14385af53050Schristos        # Enabled by default, disable it forcibly if unavailable
14395af53050Schristos        if ($target{thread_scheme} eq "(unknown)") {
14404261787cSchristos            disable("unavailable", 'threads');
1441a89c9211Schristos        }
14425af53050Schristos    } else {
14435af53050Schristos        # The user chose to enable threads explicitly, let's see
14445af53050Schristos        # if there's a chance that's possible
14455af53050Schristos        if ($target{thread_scheme} eq "(unknown)") {
14465af53050Schristos            # If the user asked for "threads" and we don't have internal
14475af53050Schristos            # knowledge how to do it, [s]he is expected to provide any
14485af53050Schristos            # system-dependent compiler options that are necessary.  We
14495af53050Schristos            # can't truly check that the given options are correct, but
14505af53050Schristos            # we expect the user to know what [s]He is doing.
14514261787cSchristos            if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
14525af53050Schristos                die "You asked for multi-threading support, but didn't\n"
14535af53050Schristos                    ,"provide any system-specific compiler options\n";
14545af53050Schristos            }
14555af53050Schristos        }
1456a89c9211Schristos    }
1457a89c9211Schristos}
1458a89c9211Schristos
14598fbed61eSchristos# Find out if clang's sanitizers have been enabled with -fsanitize
14608fbed61eSchristos# flags and ensure that the corresponding %disabled elements area
14618fbed61eSchristos# removed to reflect that the sanitizers are indeed enabled.
14628fbed61eSchristosmy %detected_sanitizers = ();
14638fbed61eSchristosforeach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) {
14648fbed61eSchristos    (my $checks = $_) =~ s/^-fsanitize=//;
14658fbed61eSchristos    foreach (split /,/, $checks) {
14668fbed61eSchristos        my $d = { address       => 'asan',
14678fbed61eSchristos                  undefined     => 'ubsan',
14688fbed61eSchristos                  memory        => 'msan' } -> {$_};
14698fbed61eSchristos        next unless defined $d;
14708fbed61eSchristos
14718fbed61eSchristos        $detected_sanitizers{$d} = 1;
14728fbed61eSchristos        if (defined $disabled{$d}) {
14738fbed61eSchristos            die "***** Conflict between disabling $d and enabling $_ sanitizer"
14748fbed61eSchristos                if $disabled{$d} ne "default";
14758fbed61eSchristos            delete $disabled{$d};
14768fbed61eSchristos        }
14778fbed61eSchristos    }
14788fbed61eSchristos}
14798fbed61eSchristos
14805af53050Schristos# If threads still aren't disabled, add a C macro to ensure the source
14815af53050Schristos# code knows about it.  Any other flag is taken care of by the configs.
14825af53050Schristosunless($disabled{threads}) {
14838fbed61eSchristos    push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS";
14845af53050Schristos}
14855af53050Schristos
1486e0ea3921Schristosmy $no_shared_warn=0;
14878fbed61eSchristosif (($target{shared_target} // '') eq "")
14885af53050Schristos        {
14895af53050Schristos        $no_shared_warn = 1
1490e0ea3921Schristos            if (!$disabled{shared} || !$disabled{"dynamic-engine"});
14914261787cSchristos        disable('no-shared-target', 'pic');
14925af53050Schristos        }
14935af53050Schristos
14945af53050Schristosif ($disabled{"dynamic-engine"}) {
14955af53050Schristos        $config{dynamic_engines} = 0;
14965af53050Schristos} else {
14975af53050Schristos        $config{dynamic_engines} = 1;
14985af53050Schristos}
14995af53050Schristos
15008fbed61eSchristosunless ($disabled{asan} || defined $detected_sanitizers{asan}) {
1501e0ea3921Schristos    push @{$config{cflags}}, "-fsanitize=address";
15025af53050Schristos}
15035af53050Schristos
15048fbed61eSchristosunless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) {
15058fbed61eSchristos    push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC";
15065af53050Schristos}
15075af53050Schristos
15088fbed61eSchristosunless ($disabled{msan} || defined $detected_sanitizers{msan}) {
1509e0ea3921Schristos  push @{$config{cflags}}, "-fsanitize=memory";
15105af53050Schristos}
15115af53050Schristos
15125af53050Schristosunless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
15135af53050Schristos        && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
1514e0ea3921Schristos    push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
1515e0ea3921Schristos    push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
15165af53050Schristos}
1517a89c9211Schristos#
1518a89c9211Schristos# Platform fix-ups
1519a89c9211Schristos#
1520a89c9211Schristos
15215af53050Schristos# This saves the build files from having to check
15225af53050Schristosif ($disabled{pic})
1523a89c9211Schristos        {
1524e0ea3921Schristos        foreach (qw(shared_cflag shared_cxxflag shared_cppflag
1525e0ea3921Schristos                    shared_defines shared_includes shared_ldflag
1526e0ea3921Schristos                    module_cflags module_cxxflags module_cppflags
1527e0ea3921Schristos                    module_defines module_includes module_lflags))
1528e0ea3921Schristos                {
1529e0ea3921Schristos                delete $config{$_};
1530e0ea3921Schristos                $target{$_} = "";
1531e0ea3921Schristos                }
153231b855a0Sspz        }
153331b855a0Sspzelse
153431b855a0Sspz        {
1535e0ea3921Schristos        push @{$config{lib_defines}}, "OPENSSL_PIC";
153631b855a0Sspz        }
15375af53050Schristos
15385af53050Schristosif ($target{sys_id} ne "")
1539a89c9211Schristos        {
15405af53050Schristos        push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
1541a89c9211Schristos        }
15425af53050Schristos
15434261787cSchristosmy %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
15444261787cSchristosmy %predefined_CXX = $config{CXX}
15454261787cSchristos    ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
15464261787cSchristos    : ();
15475af53050Schristos
15488fbed61eSchristosunless ($disabled{asm}) {
15498fbed61eSchristos    # big endian systems can use ELFv2 ABI
15508fbed61eSchristos    if ($target eq "linux-ppc64") {
15518fbed61eSchristos        $target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2);
15528fbed61eSchristos    }
15538fbed61eSchristos}
15548fbed61eSchristos
1555e0ea3921Schristos# Check for makedepend capabilities.
15565af53050Schristosif (!$disabled{makedepend}) {
15578fbed61eSchristos    # If the attribute makedep_scheme is defined, then we assume that the
15588fbed61eSchristos    # config target and its associated build file are programmed to deal
15598fbed61eSchristos    # with it.
15608fbed61eSchristos    # If makedep_scheme is undefined, we go looking for GCC compatible
15618fbed61eSchristos    # dependency making, and if that's not available, we try to fall back
15628fbed61eSchristos    # on 'makedepend'.
15638fbed61eSchristos    if ($target{makedep_scheme}) {
15648fbed61eSchristos        $config{makedep_scheme} = $target{makedep_scheme};
15658fbed61eSchristos        # If the makedepcmd attribute is defined, copy it.  If not, the
15668fbed61eSchristos        # build files will have to fend for themselves.
15678fbed61eSchristos        $config{makedepcmd} = $target{makedepcmd} if $target{makedepcmd};
15684261787cSchristos    } elsif (($predefined_C{__GNUC__} // -1) >= 3
15694261787cSchristos             && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
15705af53050Schristos        # We know that GNU C version 3 and up as well as all clang
15712500041cSchristos        # versions support dependency generation, but Xcode did not
15722500041cSchristos        # handle $cc -M before clang support (but claims __GNUC__ = 3)
15738fbed61eSchristos        $config{makedep_scheme} = 'gcc';
15745af53050Schristos    } else {
15758fbed61eSchristos        # In all other cases, we look for 'makedepend', and set the
15768fbed61eSchristos        # makedep_scheme value if we found it.
15778fbed61eSchristos        $config{makedepcmd} = which('makedepend');
15788fbed61eSchristos        $config{makedep_scheme} = 'makedepend' if $config{makedepcmd};
15795af53050Schristos    }
15808fbed61eSchristos
15818fbed61eSchristos    # If no depend scheme is set, we disable makedepend
15828fbed61eSchristos    disable('unavailable', 'makedepend') unless $config{makedep_scheme};
15835af53050Schristos}
1584e0ea3921Schristos
1585*7d9ffdb3Schristosif (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS' && !$predefined_C{_AIX}) {
1586e0ea3921Schristos    # probe for -Wa,--noexecstack option...
15874261787cSchristos    if ($predefined_C{__clang__}) {
1588e0ea3921Schristos        # clang has builtin assembler, which doesn't recognize --help,
1589e0ea3921Schristos        # but it apparently recognizes the option in question on all
1590e0ea3921Schristos        # supported platforms even when it's meaningless. In other words
1591e0ea3921Schristos        # probe would fail, but probed option always accepted...
1592e0ea3921Schristos        push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
1593e0ea3921Schristos    } else {
1594e0ea3921Schristos        my $cc = $config{CROSS_COMPILE}.$config{CC};
1595e0ea3921Schristos        open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
1596e0ea3921Schristos        while(<PIPE>) {
1597e0ea3921Schristos            if (m/--noexecstack/) {
1598e0ea3921Schristos                push @{$config{cflags}}, "-Wa,--noexecstack";
1599e0ea3921Schristos                last;
16005af53050Schristos            }
1601e0ea3921Schristos        }
1602e0ea3921Schristos        close(PIPE);
1603e0ea3921Schristos        unlink("null.$$.o");
1604e0ea3921Schristos    }
1605e0ea3921Schristos}
16065af53050Schristos
16075af53050Schristos# Deal with bn_ops ###################################################
16085af53050Schristos
16095af53050Schristos$config{bn_ll}                  =0;
16105af53050Schristosmy $def_int="unsigned int";
16115af53050Schristos$config{rc4_int}                =$def_int;
16125af53050Schristos($config{b64l},$config{b64},$config{b32})=(0,0,1);
16135af53050Schristos
16145af53050Schristosmy $count = 0;
16155af53050Schristosforeach (sort split(/\s+/,$target{bn_ops})) {
16165af53050Schristos    $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
16175af53050Schristos    $config{bn_ll}=1                            if $_ eq 'BN_LLONG';
16185af53050Schristos    $config{rc4_int}="unsigned char"            if $_ eq 'RC4_CHAR';
16195af53050Schristos    ($config{b64l},$config{b64},$config{b32})
16205af53050Schristos        =(0,1,0)                                if $_ eq 'SIXTY_FOUR_BIT';
16215af53050Schristos    ($config{b64l},$config{b64},$config{b32})
16225af53050Schristos        =(1,0,0)                                if $_ eq 'SIXTY_FOUR_BIT_LONG';
16235af53050Schristos    ($config{b64l},$config{b64},$config{b32})
16245af53050Schristos        =(0,0,1)                                if $_ eq 'THIRTY_TWO_BIT';
16255af53050Schristos}
16265af53050Schristosdie "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
16275af53050Schristos    if $count > 1;
16285af53050Schristos
16298fbed61eSchristos$config{api} = $config{major} * 10000 + $config{minor} * 100
16308fbed61eSchristos    unless $config{api};
16318fbed61eSchristosforeach (keys %$apitable) {
16328fbed61eSchristos    $disabled{"deprecated-$_"} = "deprecation"
16338fbed61eSchristos        if $disabled{deprecated} && $config{api} >= $apitable->{$_};
16348fbed61eSchristos}
16358fbed61eSchristos
16368fbed61eSchristosdisable();                      # Run a cascade now
16375af53050Schristos
16385af53050Schristos# Hack cflags for better warnings (dev option) #######################
1639a89c9211Schristos
1640e0ea3921Schristos# "Stringify" the C and C++ flags string.  This permits it to be made part of
1641e0ea3921Schristos# a string and works as well on command lines.
1642e0ea3921Schristos$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1643e0ea3921Schristos                        @{$config{cflags}} ];
1644e0ea3921Schristos$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
1645e0ea3921Schristos                          @{$config{cxxflags}} ] if $config{CXX};
1646a89c9211Schristos
16478fbed61eSchristos$config{openssl_api_defines} = [
16488fbed61eSchristos    "OPENSSL_CONFIGURED_API=".$config{api},
16498fbed61eSchristos];
165031b855a0Sspz
16514261787cSchristosmy @strict_warnings_collection=();
165231b855a0Sspzif ($strict_warnings)
165331b855a0Sspz        {
1654cef2ee70Schristos        my $wopt;
16554261787cSchristos        my $gccver = $predefined_C{__GNUC__} // -1;
1656e0ea3921Schristos
165752629741Schristos        if ($gccver >= 4)
165852629741Schristos                {
16594261787cSchristos                push @strict_warnings_collection, @gcc_devteam_warn;
16604261787cSchristos                push @strict_warnings_collection, @clang_devteam_warn
16614261787cSchristos                    if (defined($predefined_C{__clang__}));
1662261bb388Schristos                }
166352629741Schristos        elsif ($config{target} =~ /^VC-/)
166452629741Schristos                {
166552629741Schristos                push @strict_warnings_collection, @cl_devteam_warn;
166652629741Schristos                }
166752629741Schristos        else
166852629741Schristos                {
166952629741Schristos                warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike, or MSVC"
167052629741Schristos                }
167152629741Schristos        }
16724261787cSchristos
16734261787cSchristos$config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
16744261787cSchristos                              ? @strict_warnings_collection
16754261787cSchristos                              : ( $_ ) }
16764261787cSchristos                    @{$config{CFLAGS}} ];
1677cef2ee70Schristos
16785af53050Schristosunless ($disabled{afalgeng}) {
16795af53050Schristos    $config{afalgeng}="";
1680e0ea3921Schristos    if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
16815af53050Schristos        my $minver = 4*10000 + 1*100 + 0;
1682e0ea3921Schristos        if ($config{CROSS_COMPILE} eq "") {
16835af53050Schristos            my $verstr = `uname -r`;
16845af53050Schristos            my ($ma, $mi1, $mi2) = split("\\.", $verstr);
16855af53050Schristos            ($mi2) = $mi2 =~ /(\d+)/;
16865af53050Schristos            my $ver = $ma*10000 + $mi1*100 + $mi2;
16875af53050Schristos            if ($ver < $minver) {
16884261787cSchristos                disable('too-old-kernel', 'afalgeng');
1689a89c9211Schristos            } else {
16905af53050Schristos                push @{$config{engdirs}}, "afalg";
16915af53050Schristos            }
1692a89c9211Schristos        } else {
16934261787cSchristos            disable('cross-compiling', 'afalgeng');
1694a89c9211Schristos        }
16955af53050Schristos    } else {
16964261787cSchristos        disable('not-linux', 'afalgeng');
1697a89c9211Schristos    }
1698a89c9211Schristos}
1699a89c9211Schristos
170052629741Schristosunless ($disabled{devcryptoeng}) {
170152629741Schristos    if ($target =~ m/^BSD/) {
170252629741Schristos        my $maxver = 5*100 + 7;
170352629741Schristos        my $sysstr = `uname -s`;
170452629741Schristos        my $verstr = `uname -r`;
170552629741Schristos        $sysstr =~ s|\R$||;
170652629741Schristos        $verstr =~ s|\R$||;
170752629741Schristos        my ($ma, $mi, @rest) = split m|\.|, $verstr;
170852629741Schristos        my $ver = $ma*100 + $mi;
170952629741Schristos        if ($sysstr eq 'OpenBSD' && $ver >= $maxver) {
171052629741Schristos            disable('too-new-kernel', 'devcryptoeng');
171152629741Schristos        }
171252629741Schristos    }
171352629741Schristos}
17145af53050Schristos
17158fbed61eSchristosunless ($disabled{ktls}) {
17168fbed61eSchristos    $config{ktls}="";
17178fbed61eSchristos    my $cc = $config{CROSS_COMPILE}.$config{CC};
17188fbed61eSchristos    if ($target =~ m/^linux/) {
17198fbed61eSchristos        system("printf '#include <sys/types.h>\n#include <linux/tls.h>' | $cc -E - >/dev/null 2>&1");
17208fbed61eSchristos        if ($? != 0) {
17218fbed61eSchristos            disable('too-old-kernel', 'ktls');
17228fbed61eSchristos        }
17238fbed61eSchristos    } elsif ($target =~ m/^BSD/) {
17248fbed61eSchristos        system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1");
17258fbed61eSchristos        if ($? != 0) {
17268fbed61eSchristos            disable('too-old-freebsd', 'ktls');
17278fbed61eSchristos        }
17288fbed61eSchristos    } else {
17298fbed61eSchristos        disable('not-linux-or-freebsd', 'ktls');
17308fbed61eSchristos    }
17318fbed61eSchristos}
17328fbed61eSchristos
17338fbed61eSchristospush @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls});
17348fbed61eSchristos
17354261787cSchristos# Get the extra flags used when building shared libraries and modules.  We
17364261787cSchristos# do this late because some of them depend on %disabled.
1737e0ea3921Schristos
17384261787cSchristos# Make the flags to build DSOs the same as for shared libraries unless they
17394261787cSchristos# are already defined
17404261787cSchristos$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
17414261787cSchristos$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
17424261787cSchristos$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
17434261787cSchristos{
17444261787cSchristos    my $shared_info_pl =
17454261787cSchristos        catfile(dirname($0), "Configurations", "shared-info.pl");
17464261787cSchristos    my %shared_info = read_eval_file($shared_info_pl);
17474261787cSchristos    push @{$target{_conf_fname_int}}, $shared_info_pl;
17484261787cSchristos    my $si = $target{shared_target};
17494261787cSchristos    while (ref $si ne "HASH") {
17504261787cSchristos        last if ! defined $si;
17514261787cSchristos        if (ref $si eq "CODE") {
17524261787cSchristos            $si = $si->();
1753e0ea3921Schristos        } else {
17544261787cSchristos            $si = $shared_info{$si};
1755e0ea3921Schristos        }
1756e0ea3921Schristos    }
1757e0ea3921Schristos
17584261787cSchristos    # Some of the 'shared_target' values don't have any entries in
17594261787cSchristos    # %shared_info.  That's perfectly fine, AS LONG AS the build file
17604261787cSchristos    # template knows how to handle this.  That is currently the case for
17614261787cSchristos    # Windows and VMS.
17624261787cSchristos    if (defined $si) {
17634261787cSchristos        # Just as above, copy certain shared_* attributes to the corresponding
17644261787cSchristos        # module_ attribute unless the latter is already defined
17654261787cSchristos        $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
17664261787cSchristos        $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
17674261787cSchristos        $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
17684261787cSchristos        foreach (sort keys %$si) {
17694261787cSchristos            $target{$_} = defined $target{$_}
17704261787cSchristos                ? add($si->{$_})->($target{$_})
17714261787cSchristos                : $si->{$_};
17724261787cSchristos        }
17734261787cSchristos    }
17744261787cSchristos}
17754261787cSchristos
17764261787cSchristos# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
1777e0ea3921Schristos
17788fbed61eSchristos######################################################################
17798fbed61eSchristos# Build up information for skipping certain directories depending on disabled
17808fbed61eSchristos# features, as well as setting up macros for disabled features.
17818fbed61eSchristos
17828fbed61eSchristos# This is a tentative database of directories to skip.  Some entries may not
17838fbed61eSchristos# correspond to anything real, but that's ok, they will simply be ignored.
17848fbed61eSchristos# The actual processing of these entries is done in the build.info lookup
17858fbed61eSchristos# loop further down.
17868fbed61eSchristos#
17878fbed61eSchristos# The key is a Unix formatted path in the source tree, the value is an index
17888fbed61eSchristos# into %disabled_info, so any existing path gets added to a corresponding
17898fbed61eSchristos# 'skipped' entry in there with the list of skipped directories.
17908fbed61eSchristosmy %skipdir = ();
179152629741Schristosmy %disabled_info = ();         # For configdata.pm
179252629741Schristosforeach my $what (sort keys %disabled) {
17938fbed61eSchristos    # There are deprecated disablables that translate to themselves.
17948fbed61eSchristos    # They cause disabling cascades, but should otherwise not regiter.
17958fbed61eSchristos    next if $deprecated_disablables{$what};
17968fbed61eSchristos    # The generated $disabled{"deprecated-x.y"} entries are special
17978fbed61eSchristos    # and treated properly elsewhere
17988fbed61eSchristos    next if $what =~ m|^deprecated-|;
17998fbed61eSchristos
180052629741Schristos    $config{options} .= " no-$what";
180152629741Schristos
18028fbed61eSchristos    if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared',
18038fbed61eSchristos                                'module', 'pic', 'dynamic-engine', 'makedepend',
18048fbed61eSchristos                                'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) {
180552629741Schristos        (my $WHAT = uc $what) =~ s|-|_|g;
18068fbed61eSchristos        my $skipdir = $what;
180752629741Schristos
180852629741Schristos        # fix-up crypto/directory name(s)
18098fbed61eSchristos        $skipdir = "ripemd" if $what eq "rmd160";
18108fbed61eSchristos        $skipdir = "whrlpool" if $what eq "whirlpool";
181152629741Schristos
181252629741Schristos        my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
18138fbed61eSchristos        push @{$config{openssl_feature_defines}}, $macro;
181452629741Schristos
18158fbed61eSchristos        $skipdir{engines} = $what if $what eq 'engine';
18168fbed61eSchristos        $skipdir{"crypto/$skipdir"} = $what
18178fbed61eSchristos            unless $what eq 'async' || $what eq 'err' || $what eq 'dso';
181852629741Schristos    }
181952629741Schristos}
182052629741Schristos
182152629741Schristosif ($disabled{"dynamic-engine"}) {
18228fbed61eSchristos    push @{$config{openssl_feature_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
182352629741Schristos} else {
18248fbed61eSchristos    push @{$config{openssl_feature_defines}}, "OPENSSL_NO_STATIC_ENGINE";
182552629741Schristos}
182652629741Schristos
18275af53050Schristos# If we use the unified build, collect information from build.info files
18285af53050Schristosmy %unified_info = ();
18295af53050Schristos
18305af53050Schristosmy $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
18315af53050Schristosif ($builder eq "unified") {
18328fbed61eSchristos    use Text::Template 1.46;
18335af53050Schristos
18345af53050Schristos    sub cleandir {
18355af53050Schristos        my $base = shift;
18365af53050Schristos        my $dir = shift;
18375af53050Schristos        my $relativeto = shift || ".";
1838b46c97feSchristos        my $no_mkpath = shift // 0;
18395af53050Schristos
18405af53050Schristos        $dir = catdir($base,$dir) unless isabsolute($dir);
18415af53050Schristos
18425af53050Schristos        # Make sure the directories we're building in exists
1843b46c97feSchristos        mkpath($dir) unless $no_mkpath;
18445af53050Schristos
18455af53050Schristos        my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
18465af53050Schristos        #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
18475af53050Schristos        return $res;
1848a89c9211Schristos    }
1849a89c9211Schristos
18505af53050Schristos    sub cleanfile {
18515af53050Schristos        my $base = shift;
18525af53050Schristos        my $file = shift;
18535af53050Schristos        my $relativeto = shift || ".";
1854b46c97feSchristos        my $no_mkpath = shift // 0;
1855a89c9211Schristos
18565af53050Schristos        $file = catfile($base,$file) unless isabsolute($file);
18575af53050Schristos
18585af53050Schristos        my $d = dirname($file);
18595af53050Schristos        my $f = basename($file);
18605af53050Schristos
18615af53050Schristos        # Make sure the directories we're building in exists
1862b46c97feSchristos        mkpath($d) unless $no_mkpath;
18635af53050Schristos
18645af53050Schristos        my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
18655af53050Schristos        #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
18665af53050Schristos        return $res;
18675af53050Schristos    }
18685af53050Schristos
18695af53050Schristos    # Store the name of the template file we will build the build file from
18705af53050Schristos    # in %config.  This may be useful for the build file itself.
18715af53050Schristos    my @build_file_template_names =
1872be43b372Schristos        ( $builder_platform."-".$config{build_file}.".tmpl",
1873be43b372Schristos          $config{build_file}.".tmpl" );
18745af53050Schristos    my @build_file_templates = ();
18755af53050Schristos
18765af53050Schristos    # First, look in the user provided directory, if given
1877e0ea3921Schristos    if (defined env($local_config_envname)) {
18785af53050Schristos        @build_file_templates =
18795af53050Schristos            map {
18805af53050Schristos                if ($^O eq 'VMS') {
18815af53050Schristos                    # VMS environment variables are logical names,
18825af53050Schristos                    # which can be used as is
18835af53050Schristos                    $local_config_envname . ':' . $_;
18845af53050Schristos                } else {
1885e0ea3921Schristos                    catfile(env($local_config_envname), $_);
18865af53050Schristos                }
18875af53050Schristos            }
18885af53050Schristos            @build_file_template_names;
18895af53050Schristos    }
18905af53050Schristos    # Then, look in our standard directory
18915af53050Schristos    push @build_file_templates,
1892b46c97feSchristos        ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir, 1) }
18935af53050Schristos          @build_file_template_names );
18945af53050Schristos
18955af53050Schristos    my $build_file_template;
18965af53050Schristos    for $_ (@build_file_templates) {
18975af53050Schristos        $build_file_template = $_;
18985af53050Schristos        last if -f $build_file_template;
18995af53050Schristos
19005af53050Schristos        $build_file_template = undef;
19015af53050Schristos    }
19025af53050Schristos    if (!defined $build_file_template) {
19035af53050Schristos        die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
19045af53050Schristos    }
19055af53050Schristos    $config{build_file_templates}
1906e0ea3921Schristos      = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
1907b46c97feSchristos                    $blddir, 1),
19088fbed61eSchristos           $build_file_template ];
19095af53050Schristos
19108fbed61eSchristos    my @build_dirs = ( [ ] );   # current directory
19115af53050Schristos
19125af53050Schristos    $config{build_infos} = [ ];
19135af53050Schristos
191478327f04Schristos    # We want to detect configdata.pm in the source tree, so we
191578327f04Schristos    # don't use it if the build tree is different.
1916b46c97feSchristos    my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir, 1);
191778327f04Schristos
19188fbed61eSchristos    # Any source file that we recognise is placed in this hash table, with
19198fbed61eSchristos    # the list of its intended destinations as value.  When everything has
19208fbed61eSchristos    # been collected, there's a routine that checks that these source files
19218fbed61eSchristos    # exist, or if they are generated, that the generator exists.
19228fbed61eSchristos    my %check_exist = ();
19238fbed61eSchristos    my %check_generate = ();
19248fbed61eSchristos
19258fbed61eSchristos    my %ordinals = ();
19268fbed61eSchristos    while (@build_dirs) {
19278fbed61eSchristos        my @curd = @{shift @build_dirs};
19288fbed61eSchristos        my $sourced = catdir($srcdir, @curd);
19298fbed61eSchristos        my $buildd = catdir($blddir, @curd);
19308fbed61eSchristos
19318fbed61eSchristos        my $unixdir = join('/', @curd);
19328fbed61eSchristos        if (exists $skipdir{$unixdir}) {
19338fbed61eSchristos            my $what = $skipdir{$unixdir};
19348fbed61eSchristos            push @{$disabled_info{$what}->{skipped}}, catdir(@curd);
19358fbed61eSchristos            next;
19368fbed61eSchristos        }
19378fbed61eSchristos
19388fbed61eSchristos        mkpath($buildd);
19398fbed61eSchristos
19408fbed61eSchristos        my $f = 'build.info';
19418fbed61eSchristos        # The basic things we're trying to build
19428fbed61eSchristos        my @programs = ();
19438fbed61eSchristos        my @libraries = ();
19448fbed61eSchristos        my @modules = ();
19458fbed61eSchristos        my @scripts = ();
19468fbed61eSchristos
19478fbed61eSchristos        my %sources = ();
19488fbed61eSchristos        my %shared_sources = ();
19498fbed61eSchristos        my %includes = ();
19508fbed61eSchristos        my %defines = ();
19518fbed61eSchristos        my %depends = ();
19528fbed61eSchristos        my %generate = ();
19538fbed61eSchristos        my %imagedocs = ();
19548fbed61eSchristos        my %htmldocs = ();
19558fbed61eSchristos        my %mandocs = ();
19568fbed61eSchristos
19578fbed61eSchristos        # Support for $variablename in build.info files.
19588fbed61eSchristos        # Embedded perl code is the ultimate master, still.  If its output
19598fbed61eSchristos        # contains a dollar sign, it had better be escaped, or it will be
19608fbed61eSchristos        # taken for a variable name prefix.
19618fbed61eSchristos        my %variables = ();
19628fbed61eSchristos        # Variable name syntax
19638fbed61eSchristos        my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/;
19648fbed61eSchristos        # Value modifier syntaxes
19658fbed61eSchristos        my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/;
19668fbed61eSchristos        # Variable reference
19678fbed61eSchristos        my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/;
19688fbed61eSchristos        my $variable_w_mod_re =
19698fbed61eSchristos            qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/;
19708fbed61eSchristos        # Tie it all together
19718fbed61eSchristos        my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/;
19728fbed61eSchristos
19738fbed61eSchristos        my $expand_variables = sub {
19748fbed61eSchristos            my $value = '';
19758fbed61eSchristos            my $value_rest = shift;
19768fbed61eSchristos
19778fbed61eSchristos            if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
19788fbed61eSchristos                print STDERR
19798fbed61eSchristos                    "DEBUG[\$expand_variables] Parsed '$value_rest' ...\n"
19808fbed61eSchristos            }
19818fbed61eSchristos
19828fbed61eSchristos            while ($value_rest =~ /${variable_re}/) {
19838fbed61eSchristos                # We must save important regexp values, because the next
19848fbed61eSchristos                # regexp clears them
19858fbed61eSchristos                my $mod = $+{MOD};
19868fbed61eSchristos                my $variable_value = $variables{$+{VARIABLE}};
19878fbed61eSchristos
19888fbed61eSchristos                $value_rest = $';
19898fbed61eSchristos                $value .= $`;
19908fbed61eSchristos
19918fbed61eSchristos                # Process modifier expressions, if present
19928fbed61eSchristos                if (defined $mod) {
19938fbed61eSchristos                    if ($mod =~ /^${variable_subst_re}$/) {
19948fbed61eSchristos                        my $re = $+{RE};
19958fbed61eSchristos                        my $subst = $+{SUBST};
19968fbed61eSchristos
19978fbed61eSchristos                        $variable_value =~ s/\Q$re\E/$subst/g;
19988fbed61eSchristos
19998fbed61eSchristos                        if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
20008fbed61eSchristos                            print STDERR
20018fbed61eSchristos                                "DEBUG[\$expand_variables] ... and substituted ",
20028fbed61eSchristos                                "'$re' with '$subst'\n";
20038fbed61eSchristos                        }
20048fbed61eSchristos                    }
20058fbed61eSchristos                }
20068fbed61eSchristos
20078fbed61eSchristos                $value .= $variable_value;
20088fbed61eSchristos            }
20098fbed61eSchristos            if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) {
20108fbed61eSchristos                print STDERR
20118fbed61eSchristos                    "DEBUG[\$expand_variables] ... into: '$value$value_rest'\n";
20128fbed61eSchristos            }
20138fbed61eSchristos            return $value . $value_rest;
20148fbed61eSchristos        };
20158fbed61eSchristos
20168fbed61eSchristos        # Support for attributes in build.info files
20178fbed61eSchristos        my %attributes = ();
20188fbed61eSchristos        my $handle_attributes = sub {
20198fbed61eSchristos            my $attr_str = shift;
20208fbed61eSchristos            my $ref = shift;
20218fbed61eSchristos            my @goals = @_;
20228fbed61eSchristos
20238fbed61eSchristos            return unless defined $attr_str;
20248fbed61eSchristos
20258fbed61eSchristos            my @a = tokenize($attr_str, qr|\s*,\s*|);
20268fbed61eSchristos            foreach my $a (@a) {
20278fbed61eSchristos                my $ac = 1;
20288fbed61eSchristos                my $ak = $a;
20298fbed61eSchristos                my $av = 1;
20308fbed61eSchristos                if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) {
20318fbed61eSchristos                    $ac = ! $1;
20328fbed61eSchristos                    $ak = $2;
20338fbed61eSchristos                    $av = $3;
20348fbed61eSchristos                }
20358fbed61eSchristos                foreach my $g (@goals) {
20368fbed61eSchristos                    if ($ac) {
20378fbed61eSchristos                        $$ref->{$g}->{$ak} = $av;
20388fbed61eSchristos                    } else {
20398fbed61eSchristos                        delete $$ref->{$g}->{$ak};
20408fbed61eSchristos                    }
20418fbed61eSchristos                }
20428fbed61eSchristos            }
20438fbed61eSchristos        };
20448fbed61eSchristos
20458fbed61eSchristos        # Support for pushing values on multiple indexes of a given hash
20468fbed61eSchristos        # array.
20478fbed61eSchristos        my $push_to = sub {
20488fbed61eSchristos            my $valueref = shift;
20498fbed61eSchristos            my $index_str = shift; # May be undef or empty
20508fbed61eSchristos            my $attrref = shift;   # May be undef
20518fbed61eSchristos            my $attr_str = shift;
20528fbed61eSchristos            my @values = @_;
20538fbed61eSchristos
20548fbed61eSchristos            if (defined $index_str) {
20558fbed61eSchristos                my @indexes = ( '' );
20568fbed61eSchristos                if ($index_str !~ m|^\s*$|) {
20578fbed61eSchristos                    @indexes = tokenize($index_str);
20588fbed61eSchristos                }
20598fbed61eSchristos                foreach (@indexes) {
20608fbed61eSchristos                    push @{$valueref->{$_}}, @values;
20618fbed61eSchristos                    if (defined $attrref) {
20628fbed61eSchristos                        $handle_attributes->($attr_str, \$$attrref->{$_},
20638fbed61eSchristos                                             @values);
20648fbed61eSchristos                    }
20658fbed61eSchristos                }
20668fbed61eSchristos            } else {
20678fbed61eSchristos                push @$valueref, @values;
20688fbed61eSchristos                $handle_attributes->($attr_str, $attrref, @values)
20698fbed61eSchristos                    if defined $attrref;
20708fbed61eSchristos            }
20718fbed61eSchristos        };
20728fbed61eSchristos
20738fbed61eSchristos        if ($buildinfo_debug) {
20748fbed61eSchristos            print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n";
20758fbed61eSchristos        }
20765af53050Schristos        push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
207778327f04Schristos        my $template =
207878327f04Schristos            Text::Template->new(TYPE => 'FILE',
207978327f04Schristos                                SOURCE => catfile($sourced, $f),
208078327f04Schristos                                PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
20815af53050Schristos        die "Something went wrong with $sourced/$f: $!\n" unless $template;
20825af53050Schristos        my @text =
20835af53050Schristos            split /^/m,
20845af53050Schristos            $template->fill_in(HASH => { config => \%config,
20855af53050Schristos                                         target => \%target,
20865af53050Schristos                                         disabled => \%disabled,
20875af53050Schristos                                         withargs => \%withargs,
20885af53050Schristos                                         builddir => abs2rel($buildd, $blddir),
20895af53050Schristos                                         sourcedir => abs2rel($sourced, $blddir),
20905af53050Schristos                                         buildtop => abs2rel($blddir, $blddir),
20915af53050Schristos                                         sourcetop => abs2rel($srcdir, $blddir) },
20925af53050Schristos                               DELIMITERS => [ "{-", "-}" ]);
20935af53050Schristos
20945af53050Schristos        # The top item of this stack has the following values
20955af53050Schristos        # -2 positive already run and we found ELSE (following ELSIF should fail)
20965af53050Schristos        # -1 positive already run (skip until ENDIF)
20975af53050Schristos        # 0 negatives so far (if we're at a condition, check it)
20985af53050Schristos        # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
20995af53050Schristos        # 2 positive ELSE (following ELSIF should fail)
21005af53050Schristos        my @skip = ();
21018fbed61eSchristos
21028fbed61eSchristos        # A few useful generic regexps
21038fbed61eSchristos        my $index_re = qr/\[\s*(?P<INDEX>(?:\\.|.)*?)\s*\]/;
21048fbed61eSchristos        my $cond_re = qr/\[\s*(?P<COND>(?:\\.|.)*?)\s*\]/;
21058fbed61eSchristos        my $attribs_re = qr/(?:\{\s*(?P<ATTRIBS>(?:\\.|.)*?)\s*\})?/;
21068fbed61eSchristos        my $value_re = qr/(?P<VALUE>.*?)/;
21075af53050Schristos        collect_information(
21085af53050Schristos            collect_from_array([ @text ],
21095af53050Schristos                               qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
21105af53050Schristos                                                $l1 =~ s/\\$//; $l1.$l2 }),
21115af53050Schristos            # Info we're looking for
21128fbed61eSchristos            qr/^\s* IF ${cond_re} \s*$/x
21135af53050Schristos            => sub {
21145af53050Schristos                if (! @skip || $skip[$#skip] > 0) {
21158fbed61eSchristos                    push @skip, !! $expand_variables->($+{COND});
21165af53050Schristos                } else {
21175af53050Schristos                    push @skip, -1;
21185af53050Schristos                }
21195af53050Schristos            },
21208fbed61eSchristos            qr/^\s* ELSIF ${cond_re} \s*$/x
21215af53050Schristos            => sub { die "ELSIF out of scope" if ! @skip;
21225af53050Schristos                     die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
21235af53050Schristos                     $skip[$#skip] = -1 if $skip[$#skip] != 0;
21248fbed61eSchristos                     $skip[$#skip] = !! $expand_variables->($+{COND})
21255af53050Schristos                         if $skip[$#skip] == 0; },
21268fbed61eSchristos            qr/^\s* ELSE \s*$/x
21275af53050Schristos            => sub { die "ELSE out of scope" if ! @skip;
21285af53050Schristos                     $skip[$#skip] = -2 if $skip[$#skip] != 0;
21295af53050Schristos                     $skip[$#skip] = 2 if $skip[$#skip] == 0; },
21308fbed61eSchristos            qr/^\s* ENDIF \s*$/x
21315af53050Schristos            => sub { die "ENDIF out of scope" if ! @skip;
21325af53050Schristos                     pop @skip; },
21338fbed61eSchristos            qr/^\s* ${variable_re} \s* = \s* ${value_re} \s* $/x
21345af53050Schristos            => sub {
21355af53050Schristos                if (!@skip || $skip[$#skip] > 0) {
21368fbed61eSchristos                    $variables{$+{VARIABLE}} = $expand_variables->($+{VALUE});
21375af53050Schristos                }
21385af53050Schristos            },
21398fbed61eSchristos            qr/^\s* SUBDIRS \s* = \s* ${value_re} \s* $/x
21405af53050Schristos            => sub {
21415af53050Schristos                if (!@skip || $skip[$#skip] > 0) {
21428fbed61eSchristos                    foreach (tokenize($expand_variables->($+{VALUE}))) {
21438fbed61eSchristos                        push @build_dirs, [ @curd, splitdir($_, 1) ];
21448fbed61eSchristos                    }
21455af53050Schristos                }
21465af53050Schristos            },
21478fbed61eSchristos            qr/^\s* PROGRAMS ${attribs_re} \s* =  \s* ${value_re} \s* $/x
21488fbed61eSchristos            => sub { $push_to->(\@programs, undef,
21498fbed61eSchristos                                \$attributes{programs}, $+{ATTRIBS},
21508fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21518fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21528fbed61eSchristos            qr/^\s* LIBS ${attribs_re} \s* =  \s* ${value_re} \s* $/x
21538fbed61eSchristos            => sub { $push_to->(\@libraries, undef,
21548fbed61eSchristos                                \$attributes{libraries}, $+{ATTRIBS},
21558fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21568fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21578fbed61eSchristos            qr/^\s* MODULES ${attribs_re} \s* =  \s* ${value_re} \s* $/x
21588fbed61eSchristos            => sub { $push_to->(\@modules, undef,
21598fbed61eSchristos                                \$attributes{modules}, $+{ATTRIBS},
21608fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21618fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21628fbed61eSchristos            qr/^\s* SCRIPTS ${attribs_re} \s* = \s* ${value_re} \s* $/x
21638fbed61eSchristos            => sub { $push_to->(\@scripts, undef,
21648fbed61eSchristos                                \$attributes{scripts}, $+{ATTRIBS},
21658fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21668fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21678fbed61eSchristos            qr/^\s* IMAGEDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
21688fbed61eSchristos            => sub { $push_to->(\%imagedocs, $expand_variables->($+{INDEX}),
21698fbed61eSchristos                                undef, undef,
21708fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21718fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21728fbed61eSchristos            qr/^\s* HTMLDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
21738fbed61eSchristos            => sub { $push_to->(\%htmldocs, $expand_variables->($+{INDEX}),
21748fbed61eSchristos                                undef, undef,
21758fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21768fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21778fbed61eSchristos            qr/^\s* MANDOCS ${index_re} \s* = \s* ${value_re} \s* $/x
21788fbed61eSchristos            => sub { $push_to->(\%mandocs, $expand_variables->($+{INDEX}),
21798fbed61eSchristos                                undef, undef,
21808fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21818fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21828fbed61eSchristos            qr/^\s* SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
21838fbed61eSchristos            => sub { $push_to->(\%sources, $expand_variables->($+{INDEX}),
21848fbed61eSchristos                                \$attributes{sources}, $+{ATTRIBS},
21858fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21868fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21878fbed61eSchristos            qr/^\s* SHARED_SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
21888fbed61eSchristos            => sub { $push_to->(\%shared_sources, $expand_variables->($+{INDEX}),
21898fbed61eSchristos                                \$attributes{sources}, $+{ATTRIBS},
21908fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21918fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21928fbed61eSchristos            qr/^\s* INCLUDE ${index_re} \s* = \s* ${value_re} \s* $/x
21938fbed61eSchristos            => sub { $push_to->(\%includes, $expand_variables->($+{INDEX}),
21948fbed61eSchristos                                undef, undef,
21958fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
21968fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
21978fbed61eSchristos            qr/^\s* DEFINE ${index_re} \s* = \s* ${value_re} \s* $/x
21988fbed61eSchristos            => sub { $push_to->(\%defines, $expand_variables->($+{INDEX}),
21998fbed61eSchristos                                undef, undef,
22008fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
22018fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
22028fbed61eSchristos            qr/^\s* DEPEND ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
22038fbed61eSchristos            => sub { $push_to->(\%depends, $expand_variables->($+{INDEX}),
22048fbed61eSchristos                                \$attributes{depends}, $+{ATTRIBS},
22058fbed61eSchristos                                tokenize($expand_variables->($+{VALUE})))
22068fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
22078fbed61eSchristos            qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x
22088fbed61eSchristos            => sub { $push_to->(\%generate, $expand_variables->($+{INDEX}),
22098fbed61eSchristos                                \$attributes{generate}, $+{ATTRIBS},
22108fbed61eSchristos                                $expand_variables->($+{VALUE}))
22118fbed61eSchristos                         if !@skip || $skip[$#skip] > 0; },
22128fbed61eSchristos            qr/^\s* (?:\#.*)? $/x => sub { },
22135af53050Schristos            "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
22145af53050Schristos            "BEFORE" => sub {
22155af53050Schristos                if ($buildinfo_debug) {
22165af53050Schristos                    print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
22175af53050Schristos                    print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
22185af53050Schristos                }
22195af53050Schristos            },
22205af53050Schristos            "AFTER" => sub {
22215af53050Schristos                if ($buildinfo_debug) {
22225af53050Schristos                    print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
22235af53050Schristos                }
22245af53050Schristos            },
22255af53050Schristos            );
22265af53050Schristos        die "runaway IF?" if (@skip);
22275af53050Schristos
22288fbed61eSchristos        if (grep { defined $attributes{modules}->{$_}->{engine} } keys %attributes
22298fbed61eSchristos                and !$config{dynamic_engines}) {
22308fbed61eSchristos            die <<"EOF"
22315af53050SchristosENGINES can only be used if configured with 'dynamic-engine'.
22325af53050SchristosThis is usually a fault in a build.info file.
2233a89c9211SchristosEOF
2234a89c9211Schristos        }
2235a89c9211Schristos
22368fbed61eSchristos        {
22378fbed61eSchristos            my %infos = ( programs  => [ @programs  ],
22388fbed61eSchristos                          libraries => [ @libraries ],
22398fbed61eSchristos                          modules   => [ @modules   ],
22408fbed61eSchristos                          scripts   => [ @scripts   ] );
22418fbed61eSchristos            foreach my $k (keys %infos) {
22428fbed61eSchristos                foreach (@{$infos{$k}}) {
22438fbed61eSchristos                    my $item = cleanfile($buildd, $_, $blddir);
22448fbed61eSchristos                    $unified_info{$k}->{$item} = 1;
22455af53050Schristos
22468fbed61eSchristos                    # Fix up associated attributes
22478fbed61eSchristos                    $unified_info{attributes}->{$k}->{$item} =
22488fbed61eSchristos                        $attributes{$k}->{$_}
22498fbed61eSchristos                        if defined $attributes{$k}->{$_};
22505af53050Schristos                }
22515af53050Schristos            }
22525af53050Schristos        }
22535af53050Schristos
2254e0ea3921Schristos        # Check that we haven't defined any library as both shared and
2255e0ea3921Schristos        # explicitly static.  That is forbidden.
2256e0ea3921Schristos        my @doubles = ();
2257e0ea3921Schristos        foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
2258e0ea3921Schristos            (my $l = $_) =~ s/\.a$//;
22598fbed61eSchristos            push @doubles, $l if defined $unified_info{libraries}->{$l};
22605af53050Schristos        }
2261e0ea3921Schristos        die "these libraries are both explicitly static and shared:\n  ",
2262e0ea3921Schristos            join(" ", @doubles), "\n"
2263e0ea3921Schristos            if @doubles;
22645af53050Schristos
22655af53050Schristos        foreach (keys %sources) {
22665af53050Schristos            my $dest = $_;
22675af53050Schristos            my $ddest = cleanfile($buildd, $_, $blddir);
22685af53050Schristos            foreach (@{$sources{$dest}}) {
2269b46c97feSchristos                my $s = cleanfile($sourced, $_, $blddir, 1);
22705af53050Schristos
22718fbed61eSchristos                # If it's generated or we simply don't find it in the source
22728fbed61eSchristos                # tree, we assume it's in the build tree.
22738fbed61eSchristos                if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
22745af53050Schristos                    $s = cleanfile($buildd, $_, $blddir);
22755af53050Schristos                }
22768fbed61eSchristos                my $o = $_;
2277e0ea3921Schristos                # We recognise C++, C and asm files
2278e0ea3921Schristos                if ($s =~ /\.(cc|cpp|c|s|S)$/) {
22798fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
2280e0ea3921Schristos                    $o =~ s/\.[csS]$/.o/; # C and assembler
2281e0ea3921Schristos                    $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
22825af53050Schristos                    $o = cleanfile($buildd, $o, $blddir);
22838fbed61eSchristos                    $unified_info{sources}->{$ddest}->{$o} = -1;
22848fbed61eSchristos                    $unified_info{sources}->{$o}->{$s} = -1;
2285e0ea3921Schristos                } elsif ($s =~ /\.rc$/) {
2286e0ea3921Schristos                    # We also recognise resource files
22878fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
2288e0ea3921Schristos                    $o =~ s/\.rc$/.res/; # Resource configuration
22898fbed61eSchristos                    $o = cleanfile($buildd, $o, $blddir);
22908fbed61eSchristos                    $unified_info{sources}->{$ddest}->{$o} = -1;
22918fbed61eSchristos                    $unified_info{sources}->{$o}->{$s} = -1;
22925af53050Schristos                } else {
22938fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
22945af53050Schristos                    $unified_info{sources}->{$ddest}->{$s} = 1;
22955af53050Schristos                }
22968fbed61eSchristos                # Fix up associated attributes
22978fbed61eSchristos                if ($o ne $_) {
22988fbed61eSchristos                    $unified_info{attributes}->{sources}->{$ddest}->{$o} =
22998fbed61eSchristos                        $unified_info{attributes}->{sources}->{$o}->{$s} =
23008fbed61eSchristos                        $attributes{sources}->{$dest}->{$_}
23018fbed61eSchristos                        if defined $attributes{sources}->{$dest}->{$_};
23028fbed61eSchristos                } else {
23038fbed61eSchristos                    $unified_info{attributes}->{sources}->{$ddest}->{$s} =
23048fbed61eSchristos                        $attributes{sources}->{$dest}->{$_}
23058fbed61eSchristos                        if defined $attributes{sources}->{$dest}->{$_};
23068fbed61eSchristos                }
23075af53050Schristos            }
23085af53050Schristos        }
23095af53050Schristos
23105af53050Schristos        foreach (keys %shared_sources) {
23115af53050Schristos            my $dest = $_;
23125af53050Schristos            my $ddest = cleanfile($buildd, $_, $blddir);
23135af53050Schristos            foreach (@{$shared_sources{$dest}}) {
2314b46c97feSchristos                my $s = cleanfile($sourced, $_, $blddir, 1);
23155af53050Schristos
23168fbed61eSchristos                # If it's generated or we simply don't find it in the source
23178fbed61eSchristos                # tree, we assume it's in the build tree.
23188fbed61eSchristos                if ($s eq $src_configdata || $generate{$_} || ! -f $s) {
23195af53050Schristos                    $s = cleanfile($buildd, $_, $blddir);
23205af53050Schristos                }
2321e0ea3921Schristos
23228fbed61eSchristos                my $o = $_;
2323e0ea3921Schristos                if ($s =~ /\.(cc|cpp|c|s|S)$/) {
2324e0ea3921Schristos                    # We recognise C++, C and asm files
23258fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
2326e0ea3921Schristos                    $o =~ s/\.[csS]$/.o/; # C and assembler
2327e0ea3921Schristos                    $o =~ s/\.(cc|cpp)$/_cc.o/; # C++
23285af53050Schristos                    $o = cleanfile($buildd, $o, $blddir);
23298fbed61eSchristos                    $unified_info{shared_sources}->{$ddest}->{$o} = -1;
23308fbed61eSchristos                    $unified_info{sources}->{$o}->{$s} = -1;
2331e0ea3921Schristos                } elsif ($s =~ /\.rc$/) {
2332e0ea3921Schristos                    # We also recognise resource files
23338fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
2334e0ea3921Schristos                    $o =~ s/\.rc$/.res/; # Resource configuration
23358fbed61eSchristos                    $o = cleanfile($buildd, $o, $blddir);
23368fbed61eSchristos                    $unified_info{shared_sources}->{$ddest}->{$o} = -1;
23378fbed61eSchristos                    $unified_info{sources}->{$o}->{$s} = -1;
23388fbed61eSchristos                } elsif ($s =~ /\.ld$/) {
23398fbed61eSchristos                    # We also recognise linker scripts (or corresponding)
2340e0ea3921Schristos                    # We know they are generated files
23418fbed61eSchristos                    push @{$check_exist{$s}}, $ddest;
23428fbed61eSchristos                    $o = cleanfile($buildd, $_, $blddir);
23438fbed61eSchristos                    $unified_info{shared_sources}->{$ddest}->{$o} = 1;
23445af53050Schristos                } else {
23455af53050Schristos                    die "unrecognised source file type for shared library: $s\n";
23465af53050Schristos                }
23478fbed61eSchristos                # Fix up associated attributes
23488fbed61eSchristos                if ($o ne $_) {
23498fbed61eSchristos                    $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
23508fbed61eSchristos                        $unified_info{attributes}->{sources}->{$o}->{$s} =
23518fbed61eSchristos                        $attributes{sources}->{$dest}->{$_}
23528fbed61eSchristos                        if defined $attributes{sources}->{$dest}->{$_};
23538fbed61eSchristos                } else {
23548fbed61eSchristos                    $unified_info{attributes}->{shared_sources}->{$ddest}->{$o} =
23558fbed61eSchristos                        $attributes{sources}->{$dest}->{$_}
23568fbed61eSchristos                        if defined $attributes{sources}->{$dest}->{$_};
23578fbed61eSchristos                }
23585af53050Schristos            }
23595af53050Schristos        }
23605af53050Schristos
23615af53050Schristos        foreach (keys %generate) {
23625af53050Schristos            my $dest = $_;
23635af53050Schristos            my $ddest = cleanfile($buildd, $_, $blddir);
23645af53050Schristos            die "more than one generator for $dest: "
23655af53050Schristos                ,join(" ", @{$generate{$_}}),"\n"
23665af53050Schristos                if scalar @{$generate{$_}} > 1;
23675af53050Schristos            my @generator = split /\s+/, $generate{$dest}->[0];
23688fbed61eSchristos            my $gen = $generator[0];
2369b46c97feSchristos            $generator[0] = cleanfile($sourced, $gen, $blddir, 1);
23708fbed61eSchristos
23718fbed61eSchristos            # If the generator is itself generated, it's in the build tree
23728fbed61eSchristos            if ($generate{$gen} || ! -f $generator[0]) {
23738fbed61eSchristos                $generator[0] = cleanfile($buildd, $gen, $blddir);
23748fbed61eSchristos            }
23758fbed61eSchristos            $check_generate{$ddest}->{$generator[0]}++;
23768fbed61eSchristos
23775af53050Schristos            $unified_info{generate}->{$ddest} = [ @generator ];
23788fbed61eSchristos            # Fix up associated attributes
23798fbed61eSchristos            $unified_info{attributes}->{generate}->{$ddest} =
23808fbed61eSchristos                $attributes{generate}->{$dest}->{$gen}
23818fbed61eSchristos                if defined $attributes{generate}->{$dest}->{$gen};
23825af53050Schristos        }
23835af53050Schristos
23845af53050Schristos        foreach (keys %depends) {
23855af53050Schristos            my $dest = $_;
23868fbed61eSchristos            my $ddest = $dest;
23878fbed61eSchristos
23888fbed61eSchristos            if ($dest =~ /^\|(.*)\|$/) {
23898fbed61eSchristos                # Collect the raw target
23908fbed61eSchristos                $unified_info{targets}->{$1} = 1;
23918fbed61eSchristos                $ddest = $1;
23928fbed61eSchristos            } elsif ($dest eq '') {
23938fbed61eSchristos                $ddest = '';
23948fbed61eSchristos            } else {
2395b46c97feSchristos                $ddest = cleanfile($sourced, $_, $blddir, 1);
23965af53050Schristos
23975af53050Schristos                # If the destination doesn't exist in source, it can only be
23985af53050Schristos                # a generated file in the build tree.
23998fbed61eSchristos                if ($ddest eq $src_configdata || ! -f $ddest) {
24005af53050Schristos                    $ddest = cleanfile($buildd, $_, $blddir);
24015af53050Schristos                }
24025af53050Schristos            }
24035af53050Schristos            foreach (@{$depends{$dest}}) {
2404b46c97feSchristos                my $d = cleanfile($sourced, $_, $blddir, 1);
24058fbed61eSchristos                my $d2 = cleanfile($buildd, $_, $blddir);
24065af53050Schristos
24075af53050Schristos                # If we know it's generated, or assume it is because we can't
24085af53050Schristos                # find it in the source tree, we set file we depend on to be
24098fbed61eSchristos                # in the build tree rather than the source tree.
241078327f04Schristos                if ($d eq $src_configdata
24118fbed61eSchristos                    || (grep { $d2 eq $_ }
24128fbed61eSchristos                        keys %{$unified_info{generate}})
24138fbed61eSchristos                    || ! -f $d) {
24148fbed61eSchristos                    $d = $d2;
24155af53050Schristos                }
24165af53050Schristos                $unified_info{depends}->{$ddest}->{$d} = 1;
24178fbed61eSchristos
24188fbed61eSchristos                # Fix up associated attributes
24198fbed61eSchristos                $unified_info{attributes}->{depends}->{$ddest}->{$d} =
24208fbed61eSchristos                    $attributes{depends}->{$dest}->{$_}
24218fbed61eSchristos                    if defined $attributes{depends}->{$dest}->{$_};
24225af53050Schristos            }
24235af53050Schristos        }
24245af53050Schristos
24255af53050Schristos        foreach (keys %includes) {
24265af53050Schristos            my $dest = $_;
2427b46c97feSchristos            my $ddest = cleanfile($sourced, $_, $blddir, 1);
24285af53050Schristos
24295af53050Schristos            # If the destination doesn't exist in source, it can only be
24305af53050Schristos            # a generated file in the build tree.
243178327f04Schristos            if ($ddest eq $src_configdata || ! -f $ddest) {
24325af53050Schristos                $ddest = cleanfile($buildd, $_, $blddir);
24335af53050Schristos            }
24345af53050Schristos            foreach (@{$includes{$dest}}) {
2435b46c97feSchristos                my $is = cleandir($sourced, $_, $blddir, 1);
24365af53050Schristos                my $ib = cleandir($buildd, $_, $blddir);
24375af53050Schristos                push @{$unified_info{includes}->{$ddest}->{source}}, $is
24385af53050Schristos                    unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
24395af53050Schristos                push @{$unified_info{includes}->{$ddest}->{build}}, $ib
24405af53050Schristos                    unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
24415af53050Schristos            }
24425af53050Schristos        }
24438fbed61eSchristos
24448fbed61eSchristos        foreach my $dest (keys %defines) {
24458fbed61eSchristos            my $ddest;
24468fbed61eSchristos
24478fbed61eSchristos            if ($dest ne "") {
2448b46c97feSchristos                $ddest = cleanfile($sourced, $dest, $blddir, 1);
24498fbed61eSchristos
24508fbed61eSchristos                # If the destination doesn't exist in source, it can only
24518fbed61eSchristos                # be a generated file in the build tree.
24528fbed61eSchristos                if (! -f $ddest) {
24538fbed61eSchristos                    $ddest = cleanfile($buildd, $dest, $blddir);
24548fbed61eSchristos                }
24558fbed61eSchristos            }
24568fbed61eSchristos            foreach my $v (@{$defines{$dest}}) {
24578fbed61eSchristos                $v =~ m|^([^=]*)(=.*)?$|;
24588fbed61eSchristos                die "0 length macro name not permitted\n" if $1 eq "";
24598fbed61eSchristos                if ($dest ne "") {
24608fbed61eSchristos                    die "$1 defined more than once\n"
24618fbed61eSchristos                        if defined $unified_info{defines}->{$ddest}->{$1};
24628fbed61eSchristos                    $unified_info{defines}->{$ddest}->{$1} = $2;
24638fbed61eSchristos                } else {
24648fbed61eSchristos                    die "$1 defined more than once\n"
24658fbed61eSchristos                        if grep { $v eq $_ } @{$config{defines}};
24668fbed61eSchristos                    push @{$config{defines}}, $v;
24678fbed61eSchristos                }
24688fbed61eSchristos            }
24698fbed61eSchristos        }
24708fbed61eSchristos
24718fbed61eSchristos        foreach my $section (keys %imagedocs) {
24728fbed61eSchristos            foreach (@{$imagedocs{$section}}) {
24738fbed61eSchristos                my $imagedocs = cleanfile($buildd, $_, $blddir);
24748fbed61eSchristos                $unified_info{imagedocs}->{$section}->{$imagedocs} = 1;
24758fbed61eSchristos            }
24768fbed61eSchristos        }
24778fbed61eSchristos
24788fbed61eSchristos        foreach my $section (keys %htmldocs) {
24798fbed61eSchristos            foreach (@{$htmldocs{$section}}) {
24808fbed61eSchristos                my $htmldocs = cleanfile($buildd, $_, $blddir);
24818fbed61eSchristos                $unified_info{htmldocs}->{$section}->{$htmldocs} = 1;
24828fbed61eSchristos            }
24838fbed61eSchristos        }
24848fbed61eSchristos
24858fbed61eSchristos        foreach my $section (keys %mandocs) {
24868fbed61eSchristos            foreach (@{$mandocs{$section}}) {
24878fbed61eSchristos                my $mandocs = cleanfile($buildd, $_, $blddir);
24888fbed61eSchristos                $unified_info{mandocs}->{$section}->{$mandocs} = 1;
24898fbed61eSchristos            }
24908fbed61eSchristos        }
24915af53050Schristos    }
24925af53050Schristos
2493e0ea3921Schristos    my $ordinals_text = join(', ', sort keys %ordinals);
2494e0ea3921Schristos    warn <<"EOF" if $ordinals_text;
2495e0ea3921Schristos
2496e0ea3921SchristosWARNING: ORDINALS were specified for $ordinals_text
2497e0ea3921SchristosThey are ignored and should be replaced with a combination of GENERATE,
2498e0ea3921SchristosDEPEND and SHARED_SOURCE.
2499e0ea3921SchristosEOF
2500e0ea3921Schristos
25018fbed61eSchristos    # Check that each generated file is only generated once
25028fbed61eSchristos    my $ambiguous_generation = 0;
25038fbed61eSchristos    foreach (sort keys %check_generate) {
25048fbed61eSchristos        my @generators = sort keys %{$check_generate{$_}};
25058fbed61eSchristos        my $generators_txt = join(', ', @generators);
25068fbed61eSchristos        if (scalar @generators > 1) {
25078fbed61eSchristos            warn "$_ is GENERATEd by more than one generator ($generators_txt)\n";
25088fbed61eSchristos            $ambiguous_generation++;
25098fbed61eSchristos        }
25108fbed61eSchristos        if ($check_generate{$_}->{$generators[0]} > 1) {
25118fbed61eSchristos            warn "INFO: $_ has more than one GENERATE declaration (same generator)\n"
25128fbed61eSchristos        }
25138fbed61eSchristos    }
25148fbed61eSchristos    die "There are ambiguous source file generations\n"
25158fbed61eSchristos        if $ambiguous_generation > 0;
251678327f04Schristos
25178fbed61eSchristos    # All given source files should exist, or if generated, their
25188fbed61eSchristos    # generator should exist.  This loop ensures this is true.
25198fbed61eSchristos    my $missing = 0;
25208fbed61eSchristos    foreach my $orig (sort keys %check_exist) {
25218fbed61eSchristos        foreach my $dest (@{$check_exist{$orig}}) {
25228fbed61eSchristos            if ($orig ne $src_configdata) {
25238fbed61eSchristos                if ($orig =~ /\.a$/) {
25248fbed61eSchristos                    # Static library names may be used as sources, so we
25258fbed61eSchristos                    # need to detect those and give them special treatment.
25268fbed61eSchristos                    unless (grep { $_ eq $orig }
25278fbed61eSchristos                            keys %{$unified_info{libraries}}) {
25288fbed61eSchristos                        warn "$orig is given as source for $dest, but no such library is built\n";
25298fbed61eSchristos                        $missing++;
25308fbed61eSchristos                    }
25318fbed61eSchristos                } else {
25328fbed61eSchristos                    # A source may be generated, and its generator may be
25338fbed61eSchristos                    # generated as well.  We therefore loop to dig out the
25348fbed61eSchristos                    # first generator.
25358fbed61eSchristos                    my $gen = $orig;
25368fbed61eSchristos
25378fbed61eSchristos                    while (my @next = keys %{$check_generate{$gen}}) {
25388fbed61eSchristos                        $gen = $next[0];
25398fbed61eSchristos                    }
25408fbed61eSchristos
25418fbed61eSchristos                    if (! -f $gen) {
25428fbed61eSchristos                        if ($gen ne $orig) {
25438fbed61eSchristos                            $missing++;
25448fbed61eSchristos                            warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n";
25458fbed61eSchristos                        } else {
25468fbed61eSchristos                            $missing++;
25478fbed61eSchristos                            warn "$orig is given as source for $dest, but is missing\n";
2548bf8eace1Schristos                        }
2549bf8eace1Schristos                    }
2550bf8eace1Schristos                }
25518fbed61eSchristos            }
25528fbed61eSchristos        }
25538fbed61eSchristos    }
25548fbed61eSchristos    die "There are files missing\n" if $missing > 0;
25558fbed61eSchristos
25568fbed61eSchristos    # Go through the sources of all libraries and check that the same basename
25578fbed61eSchristos    # doesn't appear more than once.  Some static library archivers depend on
25588fbed61eSchristos    # them being unique.
25598fbed61eSchristos    {
25608fbed61eSchristos        my $err = 0;
25618fbed61eSchristos        foreach my $prod (keys %{$unified_info{libraries}}) {
25628fbed61eSchristos            my @prod_sources =
25638fbed61eSchristos                map { keys %{$unified_info{sources}->{$_}} }
25648fbed61eSchristos                keys %{$unified_info{sources}->{$prod}};
25658fbed61eSchristos            my %srccnt = ();
25668fbed61eSchristos
25678fbed61eSchristos            # Count how many times a given each source basename
25688fbed61eSchristos            # appears for each product.
25698fbed61eSchristos            foreach my $src (@prod_sources) {
25708fbed61eSchristos                $srccnt{basename $src}++;
25718fbed61eSchristos            }
25728fbed61eSchristos
25738fbed61eSchristos            foreach my $src (keys %srccnt) {
25748fbed61eSchristos                if ((my $cnt = $srccnt{$src}) > 1) {
25758fbed61eSchristos                    print STDERR "$src appears $cnt times for the product $prod\n";
25768fbed61eSchristos                    $err++
25778fbed61eSchristos                }
25788fbed61eSchristos            }
25798fbed61eSchristos        }
25808fbed61eSchristos        die if $err > 0;
25818fbed61eSchristos    }
25828fbed61eSchristos
25838fbed61eSchristos    # Massage the result
2584bf8eace1Schristos
258578327f04Schristos    # If we depend on a header file or a perl module, add an inclusion of
258678327f04Schristos    # its directory to allow smoothe inclusion
258778327f04Schristos    foreach my $dest (keys %{$unified_info{depends}}) {
258878327f04Schristos        next if $dest eq "";
258978327f04Schristos        foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
259078327f04Schristos            next unless $d =~ /\.(h|pm)$/;
259178327f04Schristos            my $i = dirname($d);
259278327f04Schristos            my $spot =
259378327f04Schristos                $d eq "configdata.pm" || defined($unified_info{generate}->{$d})
259478327f04Schristos                ? 'build' : 'source';
259578327f04Schristos            push @{$unified_info{includes}->{$dest}->{$spot}}, $i
259678327f04Schristos                unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
259778327f04Schristos        }
259878327f04Schristos    }
259978327f04Schristos
26008fbed61eSchristos    # Go through all intermediary files and change their names to something that
26018fbed61eSchristos    # reflects what they will be built for.  Note that for some source files,
26028fbed61eSchristos    # this leads to duplicate object files because they are used multiple times.
26038fbed61eSchristos    # the goal is to rename all object files according to this scheme:
26048fbed61eSchristos    #    {productname}-{midfix}-{origobjname}.[o|res]
26058fbed61eSchristos    # the {midfix} is a keyword indicating the type of product, which is mostly
26068fbed61eSchristos    # valuable for libraries since they come in two forms.
26078fbed61eSchristos    #
26088fbed61eSchristos    # This also reorganises the {sources} and {shared_sources} so that the
26098fbed61eSchristos    # former only contains ALL object files that are supposed to end up in
26108fbed61eSchristos    # static libraries and programs, while the latter contains ALL object files
26118fbed61eSchristos    # that are supposed to end up in shared libraries and DSOs.
26128fbed61eSchristos    # The main reason for having two different source structures is to allow
26138fbed61eSchristos    # the same name to be used for the static and the shared variants of a
26148fbed61eSchristos    # library.
26158fbed61eSchristos    {
26168fbed61eSchristos        # Take copies so we don't get interference from added stuff
26178fbed61eSchristos        my %unified_copy = ();
26188fbed61eSchristos        foreach (('sources', 'shared_sources')) {
26198fbed61eSchristos            $unified_copy{$_} = { %{$unified_info{$_}} }
26208fbed61eSchristos                if defined($unified_info{$_});
26218fbed61eSchristos            delete $unified_info{$_};
26228fbed61eSchristos        }
26238fbed61eSchristos        foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) {
26248fbed61eSchristos            # $intent serves multi purposes:
26258fbed61eSchristos            # - give a prefix for the new object files names
26268fbed61eSchristos            # - in the case of libraries, rearrange the object files so static
26278fbed61eSchristos            #   libraries use the 'sources' structure exclusively, while shared
26288fbed61eSchristos            #   libraries use the 'shared_sources' structure exclusively.
26298fbed61eSchristos            my $intent = {
26308fbed61eSchristos                programs  => { bin    => { src => [ 'sources' ],
26318fbed61eSchristos                                           dst => 'sources' } },
26328fbed61eSchristos                libraries => { lib    => { src => [ 'sources' ],
26338fbed61eSchristos                                           dst => 'sources' },
26348fbed61eSchristos                               shlib  => { prodselect =>
26358fbed61eSchristos                                               sub { grep !/\.a$/, @_ },
26368fbed61eSchristos                                           src => [ 'sources',
26378fbed61eSchristos                                                    'shared_sources' ],
26388fbed61eSchristos                                           dst => 'shared_sources' } },
26398fbed61eSchristos                modules   => { dso    => { src => [ 'sources' ],
26408fbed61eSchristos                                           dst => 'sources' } },
26418fbed61eSchristos                scripts   => { script => { src => [ 'sources' ],
26428fbed61eSchristos                                           dst => 'sources' } }
26438fbed61eSchristos               } -> {$prodtype};
26448fbed61eSchristos            foreach my $kind (keys %$intent) {
26458fbed61eSchristos                next if ($intent->{$kind}->{dst} eq 'shared_sources'
26468fbed61eSchristos                             && $disabled{shared});
26478fbed61eSchristos
26488fbed61eSchristos                my @src = @{$intent->{$kind}->{src}};
26498fbed61eSchristos                my $dst = $intent->{$kind}->{dst};
26508fbed61eSchristos                my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ };
26518fbed61eSchristos                foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) {
26528fbed61eSchristos                    # %prod_sources has all applicable objects as keys, and
26538fbed61eSchristos                    # their corresponding sources as values
26548fbed61eSchristos                    my %prod_sources =
26558fbed61eSchristos                        map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] }
26568fbed61eSchristos                        map { keys %{$unified_copy{$_}->{$prod}} }
26578fbed61eSchristos                        @src;
26588fbed61eSchristos                    foreach (keys %prod_sources) {
26598fbed61eSchristos                        # Only affect object files and resource files,
26608fbed61eSchristos                        # the others simply get a new value
26618fbed61eSchristos                        # (+1 instead of -1)
26628fbed61eSchristos                        if ($_ =~ /\.(o|res)$/) {
26638fbed61eSchristos                            (my $prodname = $prod) =~ s|\.a$||;
26648fbed61eSchristos                            my $newobj =
26658fbed61eSchristos                                catfile(dirname($_),
26668fbed61eSchristos                                        basename($prodname)
26678fbed61eSchristos                                            . '-' . $kind
26688fbed61eSchristos                                            . '-' . basename($_));
26698fbed61eSchristos                            $unified_info{$dst}->{$prod}->{$newobj} = 1;
26708fbed61eSchristos                            foreach my $src (@{$prod_sources{$_}}) {
26718fbed61eSchristos                                $unified_info{sources}->{$newobj}->{$src} = 1;
26728fbed61eSchristos                                # Adjust source attributes
26738fbed61eSchristos                                my $attrs = $unified_info{attributes}->{sources};
26748fbed61eSchristos                                if (defined $attrs->{$prod}
26758fbed61eSchristos                                    && defined $attrs->{$prod}->{$_}) {
26768fbed61eSchristos                                    $attrs->{$prod}->{$newobj} =
26778fbed61eSchristos                                        $attrs->{$prod}->{$_};
26788fbed61eSchristos                                    delete $attrs->{$prod}->{$_};
26798fbed61eSchristos                                }
26808fbed61eSchristos                                foreach my $objsrc (keys %{$attrs->{$_} // {}}) {
26818fbed61eSchristos                                    $attrs->{$newobj}->{$objsrc} =
26828fbed61eSchristos                                        $attrs->{$_}->{$objsrc};
26838fbed61eSchristos                                    delete $attrs->{$_}->{$objsrc};
26848fbed61eSchristos                                }
26858fbed61eSchristos                            }
26868fbed61eSchristos                            # Adjust dependencies
26878fbed61eSchristos                            foreach my $deps (keys %{$unified_info{depends}->{$_}}) {
26888fbed61eSchristos                                $unified_info{depends}->{$_}->{$deps} = -1;
26898fbed61eSchristos                                $unified_info{depends}->{$newobj}->{$deps} = 1;
26908fbed61eSchristos                            }
26918fbed61eSchristos                            # Adjust includes
26928fbed61eSchristos                            foreach my $k (('source', 'build')) {
26938fbed61eSchristos                                next unless
26948fbed61eSchristos                                    defined($unified_info{includes}->{$_}->{$k});
26958fbed61eSchristos                                my @incs = @{$unified_info{includes}->{$_}->{$k}};
26968fbed61eSchristos                                $unified_info{includes}->{$newobj}->{$k} = [ @incs ];
26978fbed61eSchristos                            }
26988fbed61eSchristos                        } else {
26998fbed61eSchristos                            $unified_info{$dst}->{$prod}->{$_} = 1;
270078327f04Schristos                        }
270178327f04Schristos                    }
270278327f04Schristos                }
270378327f04Schristos            }
27048fbed61eSchristos        }
27058fbed61eSchristos    }
27068fbed61eSchristos
27078fbed61eSchristos    # At this point, we have a number of sources with the value -1.  They
27088fbed61eSchristos    # aren't part of the local build and are probably meant for a different
27098fbed61eSchristos    # platform, and can therefore be cleaned away.  That happens when making
27108fbed61eSchristos    # %unified_info more efficient below.
271178327f04Schristos
27125af53050Schristos    ### Make unified_info a bit more efficient
27135af53050Schristos    # One level structures
27148fbed61eSchristos    foreach (("programs", "libraries", "modules", "scripts", "targets")) {
27155af53050Schristos        $unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
27165af53050Schristos    }
27175af53050Schristos    # Two level structures
27188fbed61eSchristos    foreach my $l1 (("sources", "shared_sources", "ldadd", "depends",
27198fbed61eSchristos                     "imagedocs", "htmldocs", "mandocs")) {
27205af53050Schristos        foreach my $l2 (sort keys %{$unified_info{$l1}}) {
27218fbed61eSchristos            my @items =
27228fbed61eSchristos                sort
27238fbed61eSchristos                grep { $unified_info{$l1}->{$l2}->{$_} > 0 }
27248fbed61eSchristos                keys %{$unified_info{$l1}->{$l2}};
27258fbed61eSchristos            if (@items) {
27268fbed61eSchristos                $unified_info{$l1}->{$l2} = [ @items ];
27278fbed61eSchristos            } else {
27288fbed61eSchristos                delete $unified_info{$l1}->{$l2};
27295af53050Schristos            }
27305af53050Schristos        }
27318fbed61eSchristos    }
27328fbed61eSchristos    # Defines
27338fbed61eSchristos    foreach my $dest (sort keys %{$unified_info{defines}}) {
27348fbed61eSchristos        $unified_info{defines}->{$dest}
27358fbed61eSchristos            = [ map { $_.$unified_info{defines}->{$dest}->{$_} }
27368fbed61eSchristos                sort keys %{$unified_info{defines}->{$dest}} ];
27378fbed61eSchristos    }
27385af53050Schristos    # Includes
27395af53050Schristos    foreach my $dest (sort keys %{$unified_info{includes}}) {
27405af53050Schristos        if (defined($unified_info{includes}->{$dest}->{build})) {
274178327f04Schristos            my @source_includes = ();
274278327f04Schristos            @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
274378327f04Schristos                if defined($unified_info{includes}->{$dest}->{source});
27445af53050Schristos            $unified_info{includes}->{$dest} =
27455af53050Schristos                [ @{$unified_info{includes}->{$dest}->{build}} ];
27465af53050Schristos            foreach my $inc (@source_includes) {
27475af53050Schristos                push @{$unified_info{includes}->{$dest}}, $inc
27485af53050Schristos                    unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
27495af53050Schristos            }
27508fbed61eSchristos        } elsif (defined($unified_info{includes}->{$dest}->{source})) {
27515af53050Schristos            $unified_info{includes}->{$dest} =
27525af53050Schristos                [ @{$unified_info{includes}->{$dest}->{source}} ];
27538fbed61eSchristos        } else {
27548fbed61eSchristos            delete $unified_info{includes}->{$dest};
27555af53050Schristos        }
27565af53050Schristos    }
2757bf8eace1Schristos
2758bf8eace1Schristos    # For convenience collect information regarding directories where
2759bf8eace1Schristos    # files are generated, those generated files and the end product
2760bf8eace1Schristos    # they end up in where applicable.  Then, add build rules for those
2761bf8eace1Schristos    # directories
2762bf8eace1Schristos    my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
27638fbed61eSchristos                     "dso" => [ @{$unified_info{modules}} ],
2764bf8eace1Schristos                     "bin" => [ @{$unified_info{programs}} ],
27658fbed61eSchristos                     "script" => [ @{$unified_info{scripts}} ],
27668fbed61eSchristos                     "docs" => [ (map { @{$unified_info{imagedocs}->{$_} // []} }
27678fbed61eSchristos                                  keys %{$unified_info{imagedocs} // {}}),
27688fbed61eSchristos                                 (map { @{$unified_info{htmldocs}->{$_} // []} }
27698fbed61eSchristos                                  keys %{$unified_info{htmldocs} // {}}),
27708fbed61eSchristos                                 (map { @{$unified_info{mandocs}->{$_} // []} }
27718fbed61eSchristos                                  keys %{$unified_info{mandocs} // {}}) ] );
27728fbed61eSchristos    foreach my $type (sort keys %loopinfo) {
2773bf8eace1Schristos        foreach my $product (@{$loopinfo{$type}}) {
2774bf8eace1Schristos            my %dirs = ();
2775bf8eace1Schristos            my $pd = dirname($product);
2776bf8eace1Schristos
2777bf8eace1Schristos            foreach (@{$unified_info{sources}->{$product} // []},
2778bf8eace1Schristos                     @{$unified_info{shared_sources}->{$product} // []}) {
2779bf8eace1Schristos                my $d = dirname($_);
2780bf8eace1Schristos
2781bf8eace1Schristos                # We don't want to create targets for source directories
2782bf8eace1Schristos                # when building out of source
2783bf8eace1Schristos                next if ($config{sourcedir} ne $config{builddir}
2784bf8eace1Schristos                             && $d =~ m|^\Q$config{sourcedir}\E|);
2785bf8eace1Schristos                # We already have a "test" target, and the current directory
2786bf8eace1Schristos                # is just silly to make a target for
2787bf8eace1Schristos                next if $d eq "test" || $d eq ".";
2788bf8eace1Schristos
2789bf8eace1Schristos                $dirs{$d} = 1;
2790bf8eace1Schristos                push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
2791bf8eace1Schristos                    if $d ne $pd;
2792bf8eace1Schristos            }
27938fbed61eSchristos            foreach (sort keys %dirs) {
2794bf8eace1Schristos                push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
2795bf8eace1Schristos                    $product;
2796bf8eace1Schristos            }
2797bf8eace1Schristos        }
2798bf8eace1Schristos    }
27995af53050Schristos}
28005af53050Schristos
28015af53050Schristos# For the schemes that need it, we provide the old *_obj configs
28025af53050Schristos# from the *_asm_obj ones
28035af53050Schristosforeach (grep /_(asm|aux)_src$/, keys %target) {
28045af53050Schristos    my $src = $_;
28055af53050Schristos    (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
2806e0ea3921Schristos    $target{$obj} = $target{$src};
2807e0ea3921Schristos    $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
2808e0ea3921Schristos    $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
28095af53050Schristos}
28105af53050Schristos
28115af53050Schristos# Write down our configuration where it fits #########################
28125af53050Schristos
28138fbed61eSchristosmy %template_vars = (
28148fbed61eSchristos    config => \%config,
28158fbed61eSchristos    target => \%target,
28168fbed61eSchristos    disablables => \@disablables,
28178fbed61eSchristos    disablables_int => \@disablables_int,
28188fbed61eSchristos    disabled => \%disabled,
28198fbed61eSchristos    withargs => \%withargs,
28208fbed61eSchristos    unified_info => \%unified_info,
28218fbed61eSchristos    tls => \@tls,
28228fbed61eSchristos    dtls => \@dtls,
28238fbed61eSchristos    makevars => [ sort keys %user ],
28248fbed61eSchristos    disabled_info => \%disabled_info,
28258fbed61eSchristos    user_crossable => \@user_crossable,
28265af53050Schristos);
28278fbed61eSchristosmy $configdata_outname = 'configdata.pm';
28288fbed61eSchristosopen CONFIGDATA, ">$configdata_outname.new"
28298fbed61eSchristos    or die "Trying to create $configdata_outname.new: $!";
2830b46c97feSchristosmy $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir, 1);
28318fbed61eSchristosmy $configdata_tmpl =
28328fbed61eSchristos    OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname);
28338fbed61eSchristos$configdata_tmpl->fill_in(
28348fbed61eSchristos    FILENAME => $configdata_tmplname,
28358fbed61eSchristos    OUTPUT => \*CONFIGDATA,
28368fbed61eSchristos    HASH => { %template_vars,
28378fbed61eSchristos              autowarntext => [
28388fbed61eSchristos                  'WARNING: do not edit!',
28398fbed61eSchristos                  "Generated by Configure from $configdata_tmplname",
28408fbed61eSchristos              ] }
28418fbed61eSchristos) or die $Text::Template::ERROR;
28428fbed61eSchristosclose CONFIGDATA;
28435af53050Schristos
28448fbed61eSchristosrename "$configdata_outname.new", $configdata_outname;
2845e0ea3921Schristosif ($builder_platform eq 'unix') {
2846e0ea3921Schristos    my $mode = (0755 & ~umask);
2847e0ea3921Schristos    chmod $mode, 'configdata.pm'
2848e0ea3921Schristos        or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
2849e0ea3921Schristos}
28508fbed61eSchristosprint "Created $configdata_outname\n";
28515af53050Schristos
28528fbed61eSchristosprint "Running $configdata_outname\n";
28538fbed61eSchristosmy $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
28548fbed61eSchristosmy $cmd = "$perlcmd $configdata_outname";
28558fbed61eSchristos#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
28568fbed61eSchristossystem($cmd);
28578fbed61eSchristosexit 1 if $? != 0;
28585af53050Schristos
28592500041cSchristos$SIG{__DIE__} = $orig_death_handler;
28602500041cSchristos
28615af53050Schristosprint <<"EOF" if ($disabled{threads} eq "unavailable");
2862a89c9211Schristos
2863a89c9211SchristosThe library could not be configured for supporting multi-threaded
2864a89c9211Schristosapplications as the compiler options required on this system are not known.
28658fbed61eSchristosSee file INSTALL.md for details if you need multi-threading.
2866a89c9211SchristosEOF
2867a89c9211Schristos
28685af53050Schristosprint <<"EOF" if ($no_shared_warn);
2869a89c9211Schristos
28705af53050SchristosThe options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
28715af53050Schristosplatform, so we will pretend you gave the option 'no-pic', which also disables
28725af53050Schristos'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
28735af53050Schristosor position independent code, please let us know (but please first make sure
28745af53050Schristosyou have tried with a current version of OpenSSL).
28754060c40eSchristosEOF
28764060c40eSchristos
28778fbed61eSchristosprint $banner;
2878e0ea3921Schristos
2879a89c9211Schristosexit(0);
2880a89c9211Schristos
28815af53050Schristos######################################################################
28825af53050Schristos#
28835af53050Schristos# Helpers and utility functions
28845af53050Schristos#
28855af53050Schristos
28862500041cSchristos# Death handler, to print a helpful message in case of failure #######
28872500041cSchristos#
28882500041cSchristossub death_handler {
28892500041cSchristos    die @_ if $^S;              # To prevent the added message in eval blocks
2890be43b372Schristos    my $build_file = $config{build_file} // "build file";
28912500041cSchristos    my @message = ( <<"_____", @_ );
28922500041cSchristos
28932500041cSchristosFailure!  $build_file wasn't produced.
28948fbed61eSchristosPlease read INSTALL.md and associated NOTES-* files.  You may also have to
28958fbed61eSchristoslook over your available compiler tool chain or change your configuration.
28962500041cSchristos
28972500041cSchristos_____
28982500041cSchristos
28992500041cSchristos    # Dying is terminal, so it's ok to reset the signal handler here.
29002500041cSchristos    $SIG{__DIE__} = $orig_death_handler;
29012500041cSchristos    die @message;
29022500041cSchristos}
29032500041cSchristos
29045af53050Schristos# Configuration file reading #########################################
29055af53050Schristos
29065af53050Schristos# Note: All of the helper functions are for lazy evaluation.  They all
29075af53050Schristos# return a CODE ref, which will return the intended value when evaluated.
29085af53050Schristos# Thus, whenever there's mention of a returned value, it's about that
29095af53050Schristos# intended value.
29105af53050Schristos
29115af53050Schristos# Helper function to implement conditional value variants, with a default
29125af53050Schristos# plus additional values based on the value of $config{build_type}.
29135af53050Schristos# Arguments are given in hash table form:
29145af53050Schristos#
29155af53050Schristos#       picker(default => "Basic string: ",
29165af53050Schristos#              debug   => "debug",
29175af53050Schristos#              release => "release")
29185af53050Schristos#
29195af53050Schristos# When configuring with --debug, the resulting string will be
29205af53050Schristos# "Basic string: debug", and when not, it will be "Basic string: release"
29215af53050Schristos#
29225af53050Schristos# This can be used to create variants of sets of flags according to the
29235af53050Schristos# build type:
29245af53050Schristos#
29255af53050Schristos#       cflags => picker(default => "-Wall",
29265af53050Schristos#                        debug   => "-g -O0",
29275af53050Schristos#                        release => "-O3")
29285af53050Schristos#
29295af53050Schristossub picker {
29305af53050Schristos    my %opts = @_;
29315af53050Schristos    return sub { add($opts{default} || (),
29325af53050Schristos                     $opts{$config{build_type}} || ())->(); }
29335af53050Schristos}
29345af53050Schristos
29355af53050Schristos# Helper function to combine several values of different types into one.
29365af53050Schristos# This is useful if you want to combine a string with the result of a
29375af53050Schristos# lazy function, such as:
29385af53050Schristos#
29395af53050Schristos#       cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
29405af53050Schristos#
29415af53050Schristossub combine {
29425af53050Schristos    my @stuff = @_;
29435af53050Schristos    return sub { add(@stuff)->(); }
29445af53050Schristos}
29455af53050Schristos
29465af53050Schristos# Helper function to implement conditional values depending on the value
29475af53050Schristos# of $disabled{threads}.  Can be used as follows:
29485af53050Schristos#
29495af53050Schristos#       cflags => combine("-Wall", threads("-pthread"))
29505af53050Schristos#
29515af53050Schristossub threads {
29525af53050Schristos    my @flags = @_;
29535af53050Schristos    return sub { add($disabled{threads} ? () : @flags)->(); }
29545af53050Schristos}
29555af53050Schristos
2956e0ea3921Schristossub shared {
2957e0ea3921Schristos    my @flags = @_;
2958e0ea3921Schristos    return sub { add($disabled{shared} ? () : @flags)->(); }
2959e0ea3921Schristos}
29605af53050Schristos
29615af53050Schristosour $add_called = 0;
29625af53050Schristos# Helper function to implement adding values to already existing configuration
29635af53050Schristos# values.  It handles elements that are ARRAYs, CODEs and scalars
29645af53050Schristossub _add {
29655af53050Schristos    my $separator = shift;
29665af53050Schristos
29675af53050Schristos    # If there's any ARRAY in the collection of values OR the separator
29685af53050Schristos    # is undef, we will return an ARRAY of combined values, otherwise a
29695af53050Schristos    # string of joined values with $separator as the separator.
29705af53050Schristos    my $found_array = !defined($separator);
29715af53050Schristos
29725af53050Schristos    my @values =
29735af53050Schristos        map {
29745af53050Schristos            my $res = $_;
29755af53050Schristos            while (ref($res) eq "CODE") {
29765af53050Schristos                $res = $res->();
29775af53050Schristos            }
29785af53050Schristos            if (defined($res)) {
29795af53050Schristos                if (ref($res) eq "ARRAY") {
29805af53050Schristos                    $found_array = 1;
29815af53050Schristos                    @$res;
29825af53050Schristos                } else {
29835af53050Schristos                    $res;
29845af53050Schristos                }
29855af53050Schristos            } else {
29865af53050Schristos                ();
29875af53050Schristos            }
29885af53050Schristos    } (@_);
29895af53050Schristos
29905af53050Schristos    $add_called = 1;
29915af53050Schristos
29925af53050Schristos    if ($found_array) {
29935af53050Schristos        [ @values ];
29945af53050Schristos    } else {
29955af53050Schristos        join($separator, grep { defined($_) && $_ ne "" } @values);
29965af53050Schristos    }
29975af53050Schristos}
29985af53050Schristossub add_before {
29995af53050Schristos    my $separator = " ";
30005af53050Schristos    if (ref($_[$#_]) eq "HASH") {
30015af53050Schristos        my $opts = pop;
30025af53050Schristos        $separator = $opts->{separator};
30035af53050Schristos    }
30045af53050Schristos    my @x = @_;
30055af53050Schristos    sub { _add($separator, @x, @_) };
30065af53050Schristos}
30075af53050Schristossub add {
30085af53050Schristos    my $separator = " ";
30095af53050Schristos    if (ref($_[$#_]) eq "HASH") {
30105af53050Schristos        my $opts = pop;
30115af53050Schristos        $separator = $opts->{separator};
30125af53050Schristos    }
30135af53050Schristos    my @x = @_;
30145af53050Schristos    sub { _add($separator, @_, @x) };
30155af53050Schristos}
30165af53050Schristos
3017e0ea3921Schristossub read_eval_file {
3018e0ea3921Schristos    my $fname = shift;
3019e0ea3921Schristos    my $content;
3020e0ea3921Schristos    my @result;
3021e0ea3921Schristos
3022e0ea3921Schristos    open F, "< $fname" or die "Can't open '$fname': $!\n";
3023e0ea3921Schristos    {
3024e0ea3921Schristos        undef local $/;
3025e0ea3921Schristos        $content = <F>;
3026e0ea3921Schristos    }
3027e0ea3921Schristos    close F;
3028e0ea3921Schristos    {
3029e0ea3921Schristos        local $@;
3030e0ea3921Schristos
3031e0ea3921Schristos        @result = ( eval $content );
3032e0ea3921Schristos        warn $@ if $@;
3033e0ea3921Schristos    }
3034e0ea3921Schristos    return wantarray ? @result : $result[0];
3035e0ea3921Schristos}
3036e0ea3921Schristos
30375af53050Schristos# configuration reader, evaluates the input file as a perl script and expects
30385af53050Schristos# it to fill %targets with target configurations.  Those are then added to
30395af53050Schristos# %table.
30405af53050Schristossub read_config {
30415af53050Schristos    my $fname = shift;
3042e0ea3921Schristos    my %targets;
3043e0ea3921Schristos
30445af53050Schristos    {
30455af53050Schristos        # Protect certain tables from tampering
3046e0ea3921Schristos        local %table = ();
30475af53050Schristos
3048e0ea3921Schristos        %targets = read_eval_file($fname);
30495af53050Schristos    }
305078327f04Schristos    my %preexisting = ();
305178327f04Schristos    foreach (sort keys %targets) {
305278327f04Schristos        $preexisting{$_} = 1 if $table{$_};
305378327f04Schristos    }
305478327f04Schristos    die <<"EOF",
305578327f04SchristosThe following config targets from $fname
305678327f04Schristosshadow pre-existing config targets with the same name:
305778327f04SchristosEOF
305878327f04Schristos        map { "  $_\n" } sort keys %preexisting
305978327f04Schristos        if %preexisting;
306078327f04Schristos
30615af53050Schristos
30625af53050Schristos    # For each target, check that it's configured with a hash table.
30635af53050Schristos    foreach (keys %targets) {
30645af53050Schristos        if (ref($targets{$_}) ne "HASH") {
30655af53050Schristos            if (ref($targets{$_}) eq "") {
30665af53050Schristos                warn "Deprecated target configuration for $_, ignoring...\n";
30675af53050Schristos            } else {
30685af53050Schristos                warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
30695af53050Schristos            }
30705af53050Schristos            delete $targets{$_};
30715af53050Schristos        } else {
30725af53050Schristos            $targets{$_}->{_conf_fname_int} = add([ $fname ]);
30735af53050Schristos        }
30745af53050Schristos    }
30755af53050Schristos
30765af53050Schristos    %table = (%table, %targets);
30775af53050Schristos
30785af53050Schristos}
30795af53050Schristos
30805af53050Schristos# configuration resolver.  Will only resolve all the lazy evaluation
30815af53050Schristos# codeblocks for the chosen target and all those it inherits from,
30825af53050Schristos# recursively
30835af53050Schristossub resolve_config {
30845af53050Schristos    my $target = shift;
30855af53050Schristos    my @breadcrumbs = @_;
30865af53050Schristos
30875af53050Schristos#    my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
30885af53050Schristos
30895af53050Schristos    if (grep { $_ eq $target } @breadcrumbs) {
30905af53050Schristos        die "inherit_from loop!  target backtrace:\n  "
30915af53050Schristos            ,$target,"\n  ",join("\n  ", @breadcrumbs),"\n";
30925af53050Schristos    }
30935af53050Schristos
30945af53050Schristos    if (!defined($table{$target})) {
30955af53050Schristos        warn "Warning! target $target doesn't exist!\n";
30965af53050Schristos        return ();
30975af53050Schristos    }
30985af53050Schristos    # Recurse through all inheritances.  They will be resolved on the
30995af53050Schristos    # fly, so when this operation is done, they will all just be a
31005af53050Schristos    # bunch of attributes with string values.
31015af53050Schristos    # What we get here, though, are keys with references to lists of
31025af53050Schristos    # the combined values of them all.  We will deal with lists after
31035af53050Schristos    # this stage is done.
31045af53050Schristos    my %combined_inheritance = ();
31055af53050Schristos    if ($table{$target}->{inherit_from}) {
31065af53050Schristos        my @inherit_from =
31075af53050Schristos            map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
31085af53050Schristos        foreach (@inherit_from) {
31095af53050Schristos            my %inherited_config = resolve_config($_, $target, @breadcrumbs);
31105af53050Schristos
31115af53050Schristos            # 'template' is a marker that's considered private to
31125af53050Schristos            # the config that had it.
31135af53050Schristos            delete $inherited_config{template};
31145af53050Schristos
31155af53050Schristos            foreach (keys %inherited_config) {
31165af53050Schristos                if (!$combined_inheritance{$_}) {
31175af53050Schristos                    $combined_inheritance{$_} = [];
31185af53050Schristos                }
31195af53050Schristos                push @{$combined_inheritance{$_}}, $inherited_config{$_};
31205af53050Schristos            }
31215af53050Schristos        }
31225af53050Schristos    }
31235af53050Schristos
31245af53050Schristos    # We won't need inherit_from in this target any more, since we've
31255af53050Schristos    # resolved all the inheritances that lead to this
31265af53050Schristos    delete $table{$target}->{inherit_from};
31275af53050Schristos
31285af53050Schristos    # Now is the time to deal with those lists.  Here's the place to
31295af53050Schristos    # decide what shall be done with those lists, all based on the
31305af53050Schristos    # values of the target we're currently dealing with.
31315af53050Schristos    # - If a value is a coderef, it will be executed with the list of
31325af53050Schristos    #   inherited values as arguments.
31335af53050Schristos    # - If the corresponding key doesn't have a value at all or is the
31345af53050Schristos    #   empty string, the inherited value list will be run through the
31355af53050Schristos    #   default combiner (below), and the result becomes this target's
31365af53050Schristos    #   value.
31375af53050Schristos    # - Otherwise, this target's value is assumed to be a string that
31385af53050Schristos    #   will simply override the inherited list of values.
31395af53050Schristos    my $default_combiner = add();
31405af53050Schristos
31415af53050Schristos    my %all_keys =
31425af53050Schristos        map { $_ => 1 } (keys %combined_inheritance,
31435af53050Schristos                         keys %{$table{$target}});
31445af53050Schristos
31455af53050Schristos    sub process_values {
31465af53050Schristos        my $object    = shift;
31475af53050Schristos        my $inherited = shift;  # Always a [ list ]
31485af53050Schristos        my $target    = shift;
31495af53050Schristos        my $entry     = shift;
31505af53050Schristos
31515af53050Schristos        $add_called = 0;
31525af53050Schristos
31535af53050Schristos        while(ref($object) eq "CODE") {
31545af53050Schristos            $object = $object->(@$inherited);
31555af53050Schristos        }
31565af53050Schristos        if (!defined($object)) {
31575af53050Schristos            return ();
31585af53050Schristos        }
31595af53050Schristos        elsif (ref($object) eq "ARRAY") {
31605af53050Schristos            local $add_called;  # To make sure recursive calls don't affect it
31615af53050Schristos            return [ map { process_values($_, $inherited, $target, $entry) }
31625af53050Schristos                     @$object ];
31635af53050Schristos        } elsif (ref($object) eq "") {
31645af53050Schristos            return $object;
31655af53050Schristos        } else {
31665af53050Schristos            die "cannot handle reference type ",ref($object)
31675af53050Schristos                ," found in target ",$target," -> ",$entry,"\n";
31685af53050Schristos        }
31695af53050Schristos    }
31705af53050Schristos
31719330ead5Schristos    foreach my $key (sort keys %all_keys) {
31729330ead5Schristos        my $previous = $combined_inheritance{$key};
31735af53050Schristos
31745af53050Schristos        # Current target doesn't have a value for the current key?
31755af53050Schristos        # Assign it the default combiner, the rest of this loop body
31765af53050Schristos        # will handle it just like any other coderef.
31779330ead5Schristos        if (!exists $table{$target}->{$key}) {
31789330ead5Schristos            $table{$target}->{$key} = $default_combiner;
31795af53050Schristos        }
31805af53050Schristos
31819330ead5Schristos        $table{$target}->{$key} = process_values($table{$target}->{$key},
31829330ead5Schristos                                               $combined_inheritance{$key},
31839330ead5Schristos                                               $target, $key);
31849330ead5Schristos        unless(defined($table{$target}->{$key})) {
31859330ead5Schristos            delete $table{$target}->{$key};
31865af53050Schristos        }
31875af53050Schristos#        if ($extra_checks &&
31889330ead5Schristos#            $previous && !($add_called ||  $previous ~~ $table{$target}->{$key})) {
31899330ead5Schristos#            warn "$key got replaced in $target\n";
31905af53050Schristos#        }
31915af53050Schristos    }
31925af53050Schristos
31935af53050Schristos    # Finally done, return the result.
31945af53050Schristos    return %{$table{$target}};
31955af53050Schristos}
31965af53050Schristos
3197a89c9211Schristossub usage
3198a89c9211Schristos        {
3199a89c9211Schristos        print STDERR $usage;
3200a89c9211Schristos        print STDERR "\npick os/compiler from:\n";
3201a89c9211Schristos        my $j=0;
3202a89c9211Schristos        my $i;
3203a89c9211Schristos        my $k=0;
3204a89c9211Schristos        foreach $i (sort keys %table)
3205a89c9211Schristos                {
32065af53050Schristos                next if $table{$i}->{template};
3207a89c9211Schristos                next if $i =~ /^debug/;
3208a89c9211Schristos                $k += length($i) + 1;
3209a89c9211Schristos                if ($k > 78)
3210a89c9211Schristos                        {
3211a89c9211Schristos                        print STDERR "\n";
3212a89c9211Schristos                        $k=length($i);
3213a89c9211Schristos                        }
3214a89c9211Schristos                print STDERR $i . " ";
3215a89c9211Schristos                }
3216a89c9211Schristos        foreach $i (sort keys %table)
3217a89c9211Schristos                {
32185af53050Schristos                next if $table{$i}->{template};
3219a89c9211Schristos                next if $i !~ /^debug/;
3220a89c9211Schristos                $k += length($i) + 1;
3221a89c9211Schristos                if ($k > 78)
3222a89c9211Schristos                        {
3223a89c9211Schristos                        print STDERR "\n";
3224a89c9211Schristos                        $k=length($i);
3225a89c9211Schristos                        }
3226a89c9211Schristos                print STDERR $i . " ";
3227a89c9211Schristos                }
3228a89c9211Schristos        exit(1);
3229a89c9211Schristos        }
3230a89c9211Schristos
3231e0ea3921Schristossub compiler_predefined {
3232e0ea3921Schristos    state %predefined;
3233e0ea3921Schristos    my $cc = shift;
3234e0ea3921Schristos
3235e0ea3921Schristos    return () if $^O eq 'VMS';
3236e0ea3921Schristos
3237e0ea3921Schristos    die 'compiler_predefined called without a compiler command'
3238e0ea3921Schristos        unless $cc;
3239e0ea3921Schristos
3240e0ea3921Schristos    if (! $predefined{$cc}) {
3241e0ea3921Schristos
3242e0ea3921Schristos        $predefined{$cc} = {};
3243e0ea3921Schristos
3244e0ea3921Schristos        # collect compiler pre-defines from gcc or gcc-alike...
3245e0ea3921Schristos        open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
3246e0ea3921Schristos        while (my $l = <PIPE>) {
3247e0ea3921Schristos            $l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
3248e0ea3921Schristos            $predefined{$cc}->{$1} = $2 // '';
3249e0ea3921Schristos        }
3250e0ea3921Schristos        close(PIPE);
3251e0ea3921Schristos    }
3252e0ea3921Schristos
3253e0ea3921Schristos    return %{$predefined{$cc}};
3254e0ea3921Schristos}
3255e0ea3921Schristos
3256a89c9211Schristossub which
3257a89c9211Schristos{
3258a89c9211Schristos    my ($name)=@_;
32595af53050Schristos
32605af53050Schristos    if (eval { require IPC::Cmd; 1; }) {
32615af53050Schristos        IPC::Cmd->import();
32625af53050Schristos        return scalar IPC::Cmd::can_run($name);
32635af53050Schristos    } else {
32645af53050Schristos        # if there is $directories component in splitpath,
32655af53050Schristos        # then it's not something to test with $PATH...
32665af53050Schristos        return $name if (File::Spec->splitpath($name))[1];
32675af53050Schristos
32685af53050Schristos        foreach (File::Spec->path()) {
32695af53050Schristos            my $fullpath = catfile($_, "$name$target{exe_extension}");
32705af53050Schristos            if (-f $fullpath and -x $fullpath) {
32715af53050Schristos                return $fullpath;
32725af53050Schristos            }
3273a89c9211Schristos        }
3274a89c9211Schristos    }
3275a89c9211Schristos}
3276a89c9211Schristos
3277e0ea3921Schristossub env
3278e0ea3921Schristos{
3279e0ea3921Schristos    my $name = shift;
3280e0ea3921Schristos    my %opts = @_;
3281e0ea3921Schristos
3282e0ea3921Schristos    unless ($opts{cacheonly}) {
3283e0ea3921Schristos        # Note that if $ENV{$name} doesn't exist or is undefined,
3284e0ea3921Schristos        # $config{perlenv}->{$name} will be created with the value
3285e0ea3921Schristos        # undef.  This is intentional.
3286e0ea3921Schristos
3287e0ea3921Schristos        $config{perlenv}->{$name} = $ENV{$name}
3288e0ea3921Schristos            if ! exists $config{perlenv}->{$name};
3289e0ea3921Schristos    }
3290e0ea3921Schristos    return $config{perlenv}->{$name};
3291e0ea3921Schristos}
3292e0ea3921Schristos
32935af53050Schristos# Configuration printer ##############################################
3294a89c9211Schristos
3295a89c9211Schristossub print_table_entry
3296a89c9211Schristos{
3297e0ea3921Schristos    local $now_printing = shift;
3298e0ea3921Schristos    my %target = resolve_config($now_printing);
32995af53050Schristos    my $type = shift;
3300a89c9211Schristos
33015af53050Schristos    # Don't print the templates
33025af53050Schristos    return if $target{template};
3303a89c9211Schristos
33045af53050Schristos    my @sequence = (
33055af53050Schristos        "sys_id",
3306e0ea3921Schristos        "cpp",
3307e0ea3921Schristos        "cppflags",
3308e0ea3921Schristos        "defines",
3309e0ea3921Schristos        "includes",
33105af53050Schristos        "cc",
33115af53050Schristos        "cflags",
33125af53050Schristos        "ld",
33135af53050Schristos        "lflags",
33145af53050Schristos        "loutflag",
33155af53050Schristos        "ex_libs",
33165af53050Schristos        "bn_ops",
33178fbed61eSchristos        "enable",
33188fbed61eSchristos        "disable",
33195af53050Schristos        "poly1035_asm_src",
33205af53050Schristos        "thread_scheme",
33215af53050Schristos        "perlasm_scheme",
33225af53050Schristos        "dso_scheme",
33235af53050Schristos        "shared_target",
33245af53050Schristos        "shared_cflag",
33255af53050Schristos        "shared_defines",
33265af53050Schristos        "shared_ldflag",
33275af53050Schristos        "shared_rcflag",
33285af53050Schristos        "shared_extension",
33295af53050Schristos        "dso_extension",
33305af53050Schristos        "obj_extension",
33315af53050Schristos        "exe_extension",
33325af53050Schristos        "ranlib",
33335af53050Schristos        "ar",
33345af53050Schristos        "arflags",
33355af53050Schristos        "aroutflag",
33365af53050Schristos        "rc",
33375af53050Schristos        "rcflags",
33385af53050Schristos        "rcoutflag",
33395af53050Schristos        "mt",
33405af53050Schristos        "mtflags",
33415af53050Schristos        "mtinflag",
33425af53050Schristos        "mtoutflag",
33435af53050Schristos        "multilib",
33445af53050Schristos        "build_scheme",
33455af53050Schristos        );
3346a89c9211Schristos
33475af53050Schristos    if ($type eq "TABLE") {
33485af53050Schristos        print "\n";
3349e0ea3921Schristos        print "*** $now_printing\n";
33505af53050Schristos        foreach (@sequence) {
33515af53050Schristos            if (ref($target{$_}) eq "ARRAY") {
33525af53050Schristos                printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
33535af53050Schristos            } else {
33545af53050Schristos                printf "\$%-12s = %s\n", $_, $target{$_};
3355a89c9211Schristos            }
3356a89c9211Schristos        }
33575af53050Schristos    } elsif ($type eq "HASH") {
33585af53050Schristos        my $largest =
33595af53050Schristos            length((sort { length($a) <=> length($b) } @sequence)[-1]);
3360e0ea3921Schristos        print "    '$now_printing' => {\n";
33615af53050Schristos        foreach (@sequence) {
33625af53050Schristos            if ($target{$_}) {
33635af53050Schristos                if (ref($target{$_}) eq "ARRAY") {
33645af53050Schristos                    print "      '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
33655af53050Schristos                } else {
33665af53050Schristos                    print "      '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
33675af53050Schristos                }
33685af53050Schristos            }
33695af53050Schristos        }
33705af53050Schristos        print "    },\n";
33715af53050Schristos    }
3372a89c9211Schristos}
3373b367ed38Sspz
33745af53050Schristos# Utility routines ###################################################
33755af53050Schristos
33765af53050Schristos# On VMS, if the given file is a logical name, File::Spec::Functions
33775af53050Schristos# will consider it an absolute path.  There are cases when we want a
33785af53050Schristos# purely syntactic check without checking the environment.
33795af53050Schristossub isabsolute {
33805af53050Schristos    my $file = shift;
33815af53050Schristos
33825af53050Schristos    # On non-platforms, we just use file_name_is_absolute().
33835af53050Schristos    return file_name_is_absolute($file) unless $^O eq "VMS";
33845af53050Schristos
33855af53050Schristos    # If the file spec includes a device or a directory spec,
33865af53050Schristos    # file_name_is_absolute() is perfectly safe.
33875af53050Schristos    return file_name_is_absolute($file) if $file =~ m|[:\[]|;
33885af53050Schristos
33895af53050Schristos    # Here, we know the given file spec isn't absolute
33905af53050Schristos    return 0;
33915af53050Schristos}
33925af53050Schristos
33935af53050Schristos# Makes a directory absolute and cleans out /../ in paths like foo/../bar
33945af53050Schristos# On some platforms, this uses rel2abs(), while on others, realpath() is used.
33955af53050Schristos# realpath() requires that at least all path components except the last is an
33965af53050Schristos# existing directory.  On VMS, the last component of the directory spec must
33975af53050Schristos# exist.
33985af53050Schristossub absolutedir {
33995af53050Schristos    my $dir = shift;
34005af53050Schristos
34015af53050Schristos    # realpath() is quite buggy on VMS.  It uses LIB$FID_TO_NAME, which
34025af53050Schristos    # will return the volume name for the device, no matter what.  Also,
34035af53050Schristos    # it will return an incorrect directory spec if the argument is a
34045af53050Schristos    # directory that doesn't exist.
34055af53050Schristos    if ($^O eq "VMS") {
34065af53050Schristos        return rel2abs($dir);
34075af53050Schristos    }
34085af53050Schristos
3409*7d9ffdb3Schristos    # realpath() on Windows seems to check if the directory actually exists,
3410*7d9ffdb3Schristos    # which isn't what is wanted here.  All we want to know is if a directory
3411*7d9ffdb3Schristos    # spec is absolute, not if it exists.
3412*7d9ffdb3Schristos    if ($^O eq "MSWin32") {
3413*7d9ffdb3Schristos        return rel2abs($dir);
3414*7d9ffdb3Schristos    }
3415*7d9ffdb3Schristos
34165af53050Schristos    # We use realpath() on Unix, since no other will properly clean out
34175af53050Schristos    # a directory spec.
34185af53050Schristos    use Cwd qw/realpath/;
34195af53050Schristos
34205af53050Schristos    return realpath($dir);
34215af53050Schristos}
34225af53050Schristos
34234a7cf967Schristos# Check if all paths are one and the same, using stat.  They must both exist
34244a7cf967Schristos# We need this for the cases when File::Spec doesn't detect case insensitivity
34254a7cf967Schristos# (File::Spec::Unix assumes case sensitivity)
34264a7cf967Schristossub samedir {
34274a7cf967Schristos    die "samedir expects two arguments\n" unless scalar @_ == 2;
34284a7cf967Schristos
34294a7cf967Schristos    my @stat0 = stat($_[0]);    # First argument
34304a7cf967Schristos    my @stat1 = stat($_[1]);    # Second argument
34314a7cf967Schristos
34324a7cf967Schristos    die "Couldn't stat $_[0]" unless @stat0;
34334a7cf967Schristos    die "Couldn't stat $_[1]" unless @stat1;
34344a7cf967Schristos
34354a7cf967Schristos    # Compare device number
34364a7cf967Schristos    return 0 unless ($stat0[0] == $stat1[0]);
34374a7cf967Schristos    # Compare "inode".  The perl manual recommends comparing as
34384a7cf967Schristos    # string rather than as number.
34394a7cf967Schristos    return 0 unless ($stat0[1] eq $stat1[1]);
34404a7cf967Schristos
34414a7cf967Schristos    return 1;                   # All the same
34424a7cf967Schristos}
34434a7cf967Schristos
34445af53050Schristossub quotify {
34455af53050Schristos    my %processors = (
34465af53050Schristos        perl    => sub { my $x = shift;
34475af53050Schristos                         $x =~ s/([\\\$\@"])/\\$1/g;
34485af53050Schristos                         return '"'.$x.'"'; },
34495af53050Schristos        maybeshell => sub { my $x = shift;
34505af53050Schristos                            (my $y = $x) =~ s/([\\\"])/\\$1/g;
34515af53050Schristos                            if ($x ne $y || $x =~ m|\s|) {
34525af53050Schristos                                return '"'.$y.'"';
34535af53050Schristos                            } else {
34545af53050Schristos                                return $x;
34555af53050Schristos                            }
34565af53050Schristos                        },
34575af53050Schristos        );
34585af53050Schristos    my $for = shift;
34595af53050Schristos    my $processor =
34605af53050Schristos        defined($processors{$for}) ? $processors{$for} : sub { shift; };
34615af53050Schristos
34625af53050Schristos    return map { $processor->($_); } @_;
34635af53050Schristos}
34645af53050Schristos
34655af53050Schristos# collect_from_file($filename, $line_concat_cond_re, $line_concat)
34665af53050Schristos# $filename is a file name to read from
34675af53050Schristos# $line_concat_cond_re is a regexp detecting a line continuation ending
34685af53050Schristos# $line_concat is a CODEref that takes care of concatenating two lines
34695af53050Schristossub collect_from_file {
34705af53050Schristos    my $filename = shift;
34715af53050Schristos    my $line_concat_cond_re = shift;
34725af53050Schristos    my $line_concat = shift;
34735af53050Schristos
34745af53050Schristos    open my $fh, $filename || die "unable to read $filename: $!\n";
34755af53050Schristos    return sub {
34765af53050Schristos        my $saved_line = "";
34775af53050Schristos        $_ = "";
34785af53050Schristos        while (<$fh>) {
34795af53050Schristos            s|\R$||;
34805af53050Schristos            if (defined $line_concat) {
34815af53050Schristos                $_ = $line_concat->($saved_line, $_);
34825af53050Schristos                $saved_line = "";
34835af53050Schristos            }
34845af53050Schristos            if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
34855af53050Schristos                $saved_line = $_;
34865af53050Schristos                next;
34875af53050Schristos            }
34885af53050Schristos            return $_;
34895af53050Schristos        }
34905af53050Schristos        die "$filename ending with continuation line\n" if $_;
34915af53050Schristos        close $fh;
34925af53050Schristos        return undef;
34935af53050Schristos    }
34945af53050Schristos}
34955af53050Schristos
34965af53050Schristos# collect_from_array($array, $line_concat_cond_re, $line_concat)
34975af53050Schristos# $array is an ARRAYref of lines
34985af53050Schristos# $line_concat_cond_re is a regexp detecting a line continuation ending
34995af53050Schristos# $line_concat is a CODEref that takes care of concatenating two lines
35005af53050Schristossub collect_from_array {
35015af53050Schristos    my $array = shift;
35025af53050Schristos    my $line_concat_cond_re = shift;
35035af53050Schristos    my $line_concat = shift;
35045af53050Schristos    my @array = (@$array);
35055af53050Schristos
35065af53050Schristos    return sub {
35075af53050Schristos        my $saved_line = "";
35085af53050Schristos        $_ = "";
35095af53050Schristos        while (defined($_ = shift @array)) {
35105af53050Schristos            s|\R$||;
35115af53050Schristos            if (defined $line_concat) {
35125af53050Schristos                $_ = $line_concat->($saved_line, $_);
35135af53050Schristos                $saved_line = "";
35145af53050Schristos            }
35155af53050Schristos            if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
35165af53050Schristos                $saved_line = $_;
35175af53050Schristos                next;
35185af53050Schristos            }
35195af53050Schristos            return $_;
35205af53050Schristos        }
35215af53050Schristos        die "input text ending with continuation line\n" if $_;
35225af53050Schristos        return undef;
35235af53050Schristos    }
35245af53050Schristos}
35255af53050Schristos
35265af53050Schristos# collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
35275af53050Schristos# $lineiterator is a CODEref that delivers one line at a time.
35285af53050Schristos# All following arguments are regex/CODEref pairs, where the regexp detects a
35295af53050Schristos# line and the CODEref does something with the result of the regexp.
35305af53050Schristossub collect_information {
35315af53050Schristos    my $lineiterator = shift;
35325af53050Schristos    my %collectors = @_;
35335af53050Schristos
35345af53050Schristos    while(defined($_ = $lineiterator->())) {
35355af53050Schristos        s|\R$||;
35365af53050Schristos        my $found = 0;
35375af53050Schristos        if ($collectors{"BEFORE"}) {
35385af53050Schristos            $collectors{"BEFORE"}->($_);
35395af53050Schristos        }
35405af53050Schristos        foreach my $re (keys %collectors) {
35415af53050Schristos            if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
35425af53050Schristos                $collectors{$re}->($lineiterator);
35435af53050Schristos                $found = 1;
35445af53050Schristos            };
35455af53050Schristos        }
35465af53050Schristos        if ($collectors{"OTHERWISE"}) {
35475af53050Schristos            $collectors{"OTHERWISE"}->($lineiterator, $_)
35485af53050Schristos                unless $found || !defined $collectors{"OTHERWISE"};
35495af53050Schristos        }
35505af53050Schristos        if ($collectors{"AFTER"}) {
35515af53050Schristos            $collectors{"AFTER"}->($_);
35525af53050Schristos        }
35535af53050Schristos    }
35545af53050Schristos}
35555af53050Schristos
35565af53050Schristos# tokenize($line)
35578fbed61eSchristos# tokenize($line,$separator)
35585af53050Schristos# $line is a line of text to split up into tokens
35598fbed61eSchristos# $separator [optional] is a regular expression that separates the tokens,
35608fbed61eSchristos# the default being spaces.  Do not use quotes of any kind as separators,
35618fbed61eSchristos# that will give undefined results.
35628fbed61eSchristos# Returns a list of tokens.
35635af53050Schristos#
35648fbed61eSchristos# Tokens are divided by separator (spaces by default).  If the tokens include
35658fbed61eSchristos# the separators, they have to be quoted with single or double quotes.
35668fbed61eSchristos# Double quotes inside a double quoted token must be escaped.  Escaping is done
35675af53050Schristos# with backslash.
35685af53050Schristos# Basically, the same quoting rules apply for " and ' as in any
35695af53050Schristos# Unix shell.
35705af53050Schristossub tokenize {
35715af53050Schristos    my $line = my $debug_line = shift;
35728fbed61eSchristos    my $separator = shift // qr|\s+|;
35735af53050Schristos    my @result = ();
35745af53050Schristos
35758fbed61eSchristos    if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
35768fbed61eSchristos        print STDERR "DEBUG[tokenize]: \$separator = $separator\n";
35778fbed61eSchristos    }
35788fbed61eSchristos
35798fbed61eSchristos    while ($line =~ s|^${separator}||, $line ne "") {
35805af53050Schristos        my $token = "";
35818fbed61eSchristos    again:
35828fbed61eSchristos        $line =~ m/^(.*?)(${separator}|"|'|$)/;
35838fbed61eSchristos        $token .= $1;
35848fbed61eSchristos        $line = $2.$';
35858fbed61eSchristos
35865af53050Schristos        if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
35875af53050Schristos            $token .= $1;
35885af53050Schristos            $line = $';
35898fbed61eSchristos            goto again;
35905af53050Schristos        } elsif ($line =~ m/^'([^']*)'/) {
35915af53050Schristos            $token .= $1;
35925af53050Schristos            $line = $';
35938fbed61eSchristos            goto again;
35945af53050Schristos        }
35955af53050Schristos        push @result, $token;
35965af53050Schristos    }
35975af53050Schristos
35985af53050Schristos    if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
35995af53050Schristos        print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
36005af53050Schristos        print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
36015af53050Schristos    }
36025af53050Schristos    return @result;
3603b367ed38Sspz}
3604