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