Changeset View
Changeset View
Standalone View
Standalone View
Configure
#! /usr/bin/env perl | #! /usr/bin/env perl | ||||
# -*- mode: perl; -*- | # -*- mode: perl; -*- | ||||
# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. | # Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. | ||||
# | # | ||||
# Licensed under the OpenSSL license (the "License"). You may not use | # Licensed under the Apache License 2.0 (the "License"). You may not use | ||||
# this file except in compliance with the License. You can obtain a copy | # this file except in compliance with the License. You can obtain a copy | ||||
# in the file LICENSE in the source distribution or at | # in the file LICENSE in the source distribution or at | ||||
# https://www.openssl.org/source/license.html | # https://www.openssl.org/source/license.html | ||||
## Configure -- OpenSSL source tree configuration script | ## Configure -- OpenSSL source tree configuration script | ||||
use 5.10.0; | use 5.10.0; | ||||
use strict; | use strict; | ||||
use Config; | use Config; | ||||
use FindBin; | use FindBin; | ||||
use lib "$FindBin::Bin/util/perl"; | use lib "$FindBin::Bin/util/perl"; | ||||
use File::Basename; | use File::Basename; | ||||
use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; | use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs splitdir/; | ||||
use File::Path qw/mkpath/; | use File::Path qw/mkpath/; | ||||
use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt"; | |||||
use OpenSSL::Glob; | use OpenSSL::Glob; | ||||
use OpenSSL::Template; | |||||
use OpenSSL::config; | |||||
# see INSTALL for instructions. | # see INSTALL.md for instructions. | ||||
my $orig_death_handler = $SIG{__DIE__}; | my $orig_death_handler = $SIG{__DIE__}; | ||||
$SIG{__DIE__} = \&death_handler; | $SIG{__DIE__} = \&death_handler; | ||||
my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n"; | my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n"; | ||||
my $banner = <<"EOF"; | |||||
********************************************************************** | |||||
*** *** | |||||
*** OpenSSL has been successfully configured *** | |||||
*** *** | |||||
*** If you encounter a problem while building, please open an *** | |||||
*** issue on GitHub <https://github.com/openssl/openssl/issues> *** | |||||
*** and include the output from the following command: *** | |||||
*** *** | |||||
*** perl configdata.pm --dump *** | |||||
*** *** | |||||
*** (If you are new to OpenSSL, you might want to consult the *** | |||||
*** 'Troubleshooting' section in the INSTALL.md file first) *** | |||||
*** *** | |||||
********************************************************************** | |||||
EOF | |||||
# Options: | # Options: | ||||
# | # | ||||
# --config add the given configuration file, which will be read after | # --config add the given configuration file, which will be read after | ||||
# any "Configurations*" files that are found in the same | # any "Configurations*" files that are found in the same | ||||
# directory as this script. | # directory as this script. | ||||
# --prefix prefix for the OpenSSL installation, which includes the | # --prefix prefix for the OpenSSL installation, which includes the | ||||
# directories bin, lib, include, share/man, share/doc/openssl | # directories bin, lib, include, share/man, share/doc/openssl | ||||
# This becomes the value of INSTALLTOP in Makefile | # This becomes the value of INSTALLTOP in Makefile | ||||
# (Default: /usr/local) | # (Default: /usr/local) | ||||
# --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys. | # --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys. | ||||
# If it's a relative directory, it will be added on the directory | # If it's a relative directory, it will be added on the directory | ||||
# given with --prefix. | # given with --prefix. | ||||
# This becomes the value of OPENSSLDIR in Makefile and in C. | # This becomes the value of OPENSSLDIR in Makefile and in C. | ||||
# (Default: PREFIX/ssl) | # (Default: PREFIX/ssl) | ||||
# --banner=".." Output specified text instead of default completion banner | |||||
# | # | ||||
# -w Don't wait after showing a Configure warning | |||||
# | |||||
# --cross-compile-prefix Add specified prefix to binutils components. | # --cross-compile-prefix Add specified prefix to binutils components. | ||||
# | # | ||||
# --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for | # --api One of 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0, 1.1.1, or 3.0 | ||||
# interfaces deprecated as of the specified OpenSSL version. | # Define the public APIs as they were for that version | ||||
# including patch releases. If 'no-deprecated' is also | |||||
# given, do not compile support for interfaces deprecated | |||||
# up to and including the specified OpenSSL version. | |||||
# | # | ||||
# no-hw-xxx do not compile support for specific crypto hardware. | # no-hw-xxx do not compile support for specific crypto hardware. | ||||
# Generic OpenSSL-style methods relating to this support | # Generic OpenSSL-style methods relating to this support | ||||
# are always compiled but return NULL if the hardware | # are always compiled but return NULL if the hardware | ||||
# support isn't compiled. | # support isn't compiled. | ||||
# no-hw do not compile support for any crypto hardware. | # no-hw do not compile support for any crypto hardware. | ||||
# [no-]threads [don't] try to create a library that is suitable for | # [no-]threads [don't] try to create a library that is suitable for | ||||
# multithreaded applications (default is "threads" if we | # multithreaded applications (default is "threads" if we | ||||
# know how to do it) | # know how to do it) | ||||
# [no-]shared [don't] try to create shared libraries when supported. | # [no-]shared [don't] try to create shared libraries when supported. | ||||
# [no-]pic [don't] try to build position independent code when supported. | # [no-]pic [don't] try to build position independent code when supported. | ||||
# If disabled, it also disables shared and dynamic-engine. | # If disabled, it also disables shared and dynamic-engine. | ||||
# no-asm do not use assembler | # no-asm do not use assembler | ||||
# no-egd do not compile support for the entropy-gathering daemon APIs | # no-egd do not compile support for the entropy-gathering daemon APIs | ||||
# [no-]zlib [don't] compile support for zlib compression. | # [no-]zlib [don't] compile support for zlib compression. | ||||
# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared | # zlib-dynamic Like "zlib", but the zlib library is expected to be a shared | ||||
# library and will be loaded in run-time by the OpenSSL library. | # library and will be loaded in run-time by the OpenSSL library. | ||||
# sctp include SCTP support | # sctp include SCTP support | ||||
# no-uplink Don't build support for UPLINK interface. | |||||
# enable-weak-ssl-ciphers | # enable-weak-ssl-ciphers | ||||
# Enable weak ciphers that are disabled by default. | # Enable weak ciphers that are disabled by default. | ||||
# 386 generate 80386 code in assembly modules | # 386 generate 80386 code in assembly modules | ||||
# no-sse2 disables IA-32 SSE2 code in assembly modules, the above | # no-sse2 disables IA-32 SSE2 code in assembly modules, the above | ||||
# mentioned '386' option implies this one | # mentioned '386' option implies this one | ||||
# no-<cipher> build without specified algorithm (rsa, idea, rc5, ...) | # no-<cipher> build without specified algorithm (dsa, idea, rc5, ...) | ||||
# -<xxx> +<xxx> All options which are unknown to the 'Configure' script are | # -<xxx> +<xxx> All options which are unknown to the 'Configure' script are | ||||
# /<xxx> passed through to the compiler. Unix-style options beginning | # /<xxx> passed through to the compiler. Unix-style options beginning | ||||
# with a '-' or '+' are recognized, as well as Windows-style | # with a '-' or '+' are recognized, as well as Windows-style | ||||
# options beginning with a '/'. If the option contains arguments | # options beginning with a '/'. If the option contains arguments | ||||
# separated by spaces, then the URL-style notation %20 can be | # separated by spaces, then the URL-style notation %20 can be | ||||
# used for the space character in order to avoid having to quote | # used for the space character in order to avoid having to quote | ||||
# the option. For example, -opt%20arg gets expanded to -opt arg. | # the option. For example, -opt%20arg gets expanded to -opt arg. | ||||
# In fact, any ASCII character can be encoded as %xx using its | # In fact, any ASCII character can be encoded as %xx using its | ||||
Show All 25 Lines | |||||
# SHA256_ASM sha256_block is implemented in assembler | # SHA256_ASM sha256_block is implemented in assembler | ||||
# SHA512_ASM sha512_block is implemented in assembler | # SHA512_ASM sha512_block is implemented in assembler | ||||
# AES_ASM AES_[en|de]crypt is implemented in assembler | # AES_ASM AES_[en|de]crypt is implemented in assembler | ||||
# Minimum warning options... any contributions to OpenSSL should at least | # Minimum warning options... any contributions to OpenSSL should at least | ||||
# get past these. Note that we only use these with C compilers, not with | # get past these. Note that we only use these with C compilers, not with | ||||
# C++ compilers. | # C++ compilers. | ||||
# DEBUG_UNUSED enables __owur (warn unused result) checks. | |||||
# -DPEDANTIC complements -pedantic and is meant to mask code that | # -DPEDANTIC complements -pedantic and is meant to mask code that | ||||
# is not strictly standard-compliant and/or implementation-specific, | # is not strictly standard-compliant and/or implementation-specific, | ||||
# e.g. inline assembly, disregards to alignment requirements, such | # e.g. inline assembly, disregards to alignment requirements, such | ||||
# that -pedantic would complain about. Incidentally -DPEDANTIC has | # that -pedantic would complain about. Incidentally -DPEDANTIC has | ||||
# to be used even in sanitized builds, because sanitizer too is | # to be used even in sanitized builds, because sanitizer too is | ||||
# supposed to and does take notice of non-standard behaviour. Then | # supposed to and does take notice of non-standard behaviour. Then | ||||
# -pedantic with pre-C9x compiler would also complain about 'long | # -pedantic with pre-C9x compiler would also complain about 'long | ||||
# long' not being supported. As 64-bit algorithms are common now, | # long' not being supported. As 64-bit algorithms are common now, | ||||
# it grew impossible to resolve this without sizeable additional | # it grew impossible to resolve this without sizeable additional | ||||
# code, so we just tell compiler to be pedantic about everything | # code, so we just tell compiler to be pedantic about everything | ||||
# but 'long long' type. | # but 'long long' type. | ||||
my @gcc_devteam_warn = qw( | my @gcc_devteam_warn = qw( | ||||
-DDEBUG_UNUSED | -DPEDANTIC -pedantic -Wno-long-long -DUNUSEDRESULT_DEBUG | ||||
-DPEDANTIC -pedantic -Wno-long-long | |||||
-Wall | -Wall | ||||
-Wmissing-declarations | |||||
-Wextra | -Wextra | ||||
-Wno-unused-parameter | -Wno-unused-parameter | ||||
-Wno-missing-field-initializers | -Wno-missing-field-initializers | ||||
-Wswitch | -Wswitch | ||||
-Wsign-compare | -Wsign-compare | ||||
-Wshadow | -Wshadow | ||||
-Wformat | -Wformat | ||||
-Wtype-limits | -Wtype-limits | ||||
Show All 21 Lines | my @clang_devteam_warn = qw( | ||||
-Wincompatible-pointer-types-discards-qualifiers | -Wincompatible-pointer-types-discards-qualifiers | ||||
-Wmissing-variable-declarations | -Wmissing-variable-declarations | ||||
); | ); | ||||
my @cl_devteam_warn = qw( | my @cl_devteam_warn = qw( | ||||
/WX | /WX | ||||
); | ); | ||||
# This adds backtrace information to the memory leak info. Is only used | |||||
# when crypto-mdebug-backtrace is enabled. | |||||
my $memleak_devteam_backtrace = "-rdynamic"; | |||||
my $strict_warnings = 0; | my $strict_warnings = 0; | ||||
# As for $BSDthreads. Idea is to maintain "collective" set of flags, | # As for $BSDthreads. Idea is to maintain "collective" set of flags, | ||||
# which would cover all BSD flavors. -pthread applies to them all, | # which would cover all BSD flavors. -pthread applies to them all, | ||||
# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD | # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD | ||||
# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r, | # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r, | ||||
# which has to be accompanied by explicit -D_THREAD_SAFE and | # which has to be accompanied by explicit -D_THREAD_SAFE and | ||||
# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which | # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which | ||||
# seems to be sufficient? | # seems to be sufficient? | ||||
our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT"; | our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT"; | ||||
# | # | ||||
# API compatibility name to version number mapping. | # API compatibility name to version number mapping. | ||||
# | # | ||||
my $maxapi = "1.1.0"; # API for "no-deprecated" builds | |||||
my $apitable = { | my $apitable = { | ||||
"1.1.0" => "0x10100000L", | # This table expresses when API additions or changes can occur. | ||||
"1.0.0" => "0x10000000L", | # The numbering used changes from 3.0 and on because we updated | ||||
"0.9.8" => "0x00908000L", | # (solidified) our version numbering scheme at that point. | ||||
# From 3.0 and on, we internalise the given version number in decimal | |||||
# as MAJOR * 10000 + MINOR * 100 + 0 | |||||
"3.0.0" => 30000, | |||||
"3.0" => 30000, | |||||
# Note that before 3.0, we didn't have the same version number scheme. | |||||
# Still, the numbering we use here covers what we need. | |||||
"1.1.1" => 10101, | |||||
"1.1.0" => 10100, | |||||
"1.0.2" => 10002, | |||||
"1.0.1" => 10001, | |||||
"1.0.0" => 10000, | |||||
"0.9.8" => 908, | |||||
}; | }; | ||||
# For OpenSSL::config::get_platform | |||||
my %guess_opts = (); | |||||
my $dryrun = 0; | |||||
our %table = (); | our %table = (); | ||||
our %config = (); | our %config = (); | ||||
our %withargs = (); | our %withargs = (); | ||||
our $now_printing; # set to current entry's name in print_table_entry | our $now_printing; # set to current entry's name in print_table_entry | ||||
# (todo: right thing would be to encapsulate name | # (todo: right thing would be to encapsulate name | ||||
# into %target [class] and make print_table_entry | # into %target [class] and make print_table_entry | ||||
# a method) | # a method) | ||||
Show All 28 Lines | if (grep(/::Unix$/, @File::Spec::ISA) | ||||
&& samedir($srcdir, $blddir)); | && samedir($srcdir, $blddir)); | ||||
my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); | my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); | ||||
my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR'; | my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR'; | ||||
$config{sourcedir} = abs2rel($srcdir, $blddir); | $config{sourcedir} = abs2rel($srcdir, $blddir); | ||||
$config{builddir} = abs2rel($blddir, $blddir); | $config{builddir} = abs2rel($blddir, $blddir); | ||||
# echo -n 'holy hand grenade of antioch' | openssl sha256 | |||||
$config{FIPSKEY} = | |||||
'f4556650ac31d35461610bac4ed81b1a181b2d8a43ea2854cbae22ca74560813'; | |||||
# Collect reconfiguration information if needed | # Collect reconfiguration information if needed | ||||
my @argvcopy=@ARGV; | my @argvcopy=@ARGV; | ||||
if (grep /^reconf(igure)?$/, @argvcopy) { | if (grep /^reconf(igure)?$/, @argvcopy) { | ||||
die "reconfiguring with other arguments present isn't supported" | die "reconfiguring with other arguments present isn't supported" | ||||
if scalar @argvcopy > 1; | if scalar @argvcopy > 1; | ||||
if (-f "./configdata.pm") { | if (-f "./configdata.pm") { | ||||
Show All 11 Lines | if (-f "./configdata.pm") { | ||||
$config{perlenv} = $configdata::config{perlenv} // {}; | $config{perlenv} = $configdata::config{perlenv} // {}; | ||||
} else { | } else { | ||||
die "Insufficient data to reconfigure, please do a normal configuration\n"; | die "Insufficient data to reconfigure, please do a normal configuration\n"; | ||||
} | } | ||||
} | } | ||||
$config{perlargv} = [ @argvcopy ]; | $config{perlargv} = [ @argvcopy ]; | ||||
# Historical: if known directories in crypto/ have been removed, it means | |||||
# that those sub-systems are disabled. | |||||
# (the other option would be to removed them from the SUBDIRS statement in | |||||
# crypto/build.info) | |||||
# We reverse the input list for cosmetic purely reasons, to compensate that | |||||
# 'unshift' adds at the front of the list (i.e. in reverse input order). | |||||
foreach ( reverse sort( 'aes', 'aria', 'bf', 'camellia', 'cast', 'des', 'dh', | |||||
'dsa', 'ec', 'hmac', 'idea', 'md2', 'md5', 'mdc2', | |||||
'rc2', 'rc4', 'rc5', 'ripemd', 'seed', 'sha', | |||||
'sm2', 'sm3', 'sm4') ) { | |||||
unshift @argvcopy, "no-$_" if ! -d catdir($srcdir, 'crypto', $_); | |||||
} | |||||
# Collect version numbers | # Collect version numbers | ||||
$config{version} = "unknown"; | my %version = (); | ||||
$config{version_num} = "unknown"; | |||||
$config{shlib_version_number} = "unknown"; | |||||
$config{shlib_version_history} = "unknown"; | |||||
collect_information( | collect_information( | ||||
collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')), | collect_from_file(catfile($srcdir,'VERSION.dat')), | ||||
qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; }, | qr/\s*(\w+)\s*=\s*(.*?)\s*$/ => | ||||
qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 }, | sub { | ||||
qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 }, | # Only define it if there is a value at all | ||||
qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 } | if ($2 ne '') { | ||||
my $k = $1; | |||||
my $v = $2; | |||||
# Some values are quoted. Trim the quotes | |||||
$v = $1 if $v =~ /^"(.*)"$/; | |||||
$version{uc $k} = $v; | |||||
} | |||||
}, | |||||
"OTHERWISE" => | |||||
sub { die "Something wrong with this line:\n$_\nin $srcdir/VERSION.dat" }, | |||||
); | ); | ||||
if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; } | |||||
($config{major}, $config{minor}) | $config{major} = $version{MAJOR} // 'unknown'; | ||||
= ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/); | $config{minor} = $version{MINOR} // 'unknown'; | ||||
($config{shlib_major}, $config{shlib_minor}) | $config{patch} = $version{PATCH} // 'unknown'; | ||||
= ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/); | $config{prerelease} = | ||||
die "erroneous version information in opensslv.h: ", | defined $version{PRE_RELEASE_TAG} ? "-$version{PRE_RELEASE_TAG}" : ''; | ||||
"$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n" | $config{build_metadata} = | ||||
if ($config{major} eq "" || $config{minor} eq "" | defined $version{BUILD_METADATA} ? "+$version{BUILD_METADATA}" : ''; | ||||
|| $config{shlib_major} eq "" || $config{shlib_minor} eq ""); | $config{shlib_version} = $version{SHLIB_VERSION} // 'unknown'; | ||||
$config{release_date} = $version{RELEASE_DATE} // 'xx XXX xxxx'; | |||||
$config{version} = "$config{major}.$config{minor}.$config{patch}"; | |||||
$config{full_version} = "$config{version}$config{prerelease}$config{build_metadata}"; | |||||
die "erroneous version information in VERSION.dat: ", | |||||
"$config{version}, $config{shlib_version}\n" | |||||
unless (defined $version{MAJOR} | |||||
&& defined $version{MINOR} | |||||
&& defined $version{PATCH} | |||||
&& defined $version{SHLIB_VERSION}); | |||||
# Collect target configurations | # Collect target configurations | ||||
my $pattern = catfile(dirname($0), "Configurations", "*.conf"); | my $pattern = catfile(dirname($0), "Configurations", "*.conf"); | ||||
foreach (sort glob($pattern)) { | foreach (sort glob($pattern)) { | ||||
&read_config($_); | &read_config($_); | ||||
} | } | ||||
if (defined env($local_config_envname)) { | if (defined env($local_config_envname)) { | ||||
Show All 17 Lines | |||||
$config{prefix}=""; | $config{prefix}=""; | ||||
$config{openssldir}=""; | $config{openssldir}=""; | ||||
$config{processor}=""; | $config{processor}=""; | ||||
$config{libdir}=""; | $config{libdir}=""; | ||||
my $auto_threads=1; # enable threads automatically? true by default | my $auto_threads=1; # enable threads automatically? true by default | ||||
my $default_ranlib; | my $default_ranlib; | ||||
# Top level directories to build | |||||
$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ]; | |||||
# crypto/ subdirectories to build | |||||
$config{sdirs} = [ | |||||
"objects", | |||||
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3", | |||||
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes", | |||||
"bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine", | |||||
"buffer", "bio", "stack", "lhash", "rand", "err", | |||||
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", | |||||
"cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store" | |||||
]; | |||||
# test/ subdirectories to build | |||||
$config{tdirs} = [ "ossl_shim" ]; | |||||
# Known TLS and DTLS protocols | # Known TLS and DTLS protocols | ||||
my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); | my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); | ||||
my @dtls = qw(dtls1 dtls1_2); | my @dtls = qw(dtls1 dtls1_2); | ||||
# Explicitly known options that are possible to disable. They can | # Explicitly known options that are possible to disable. They can | ||||
# be regexps, and will be used like this: /^no-${option}$/ | # be regexps, and will be used like this: /^no-${option}$/ | ||||
# For developers: keep it sorted alphabetically | # For developers: keep it sorted alphabetically | ||||
my @disablables = ( | my @disablables = ( | ||||
"acvp-tests", | |||||
"afalgeng", | "afalgeng", | ||||
"aria", | "aria", | ||||
"asan", | "asan", | ||||
"asm", | "asm", | ||||
"async", | "async", | ||||
"autoalginit", | "autoalginit", | ||||
"autoerrinit", | "autoerrinit", | ||||
"autoload-config", | "autoload-config", | ||||
"bf", | "bf", | ||||
"blake2", | "blake2", | ||||
"buildtest-c\\+\\+", | "buildtest-c++", | ||||
"bulk", | |||||
"cached-fetch", | |||||
"camellia", | "camellia", | ||||
"capieng", | "capieng", | ||||
"cast", | "cast", | ||||
"chacha", | "chacha", | ||||
"cmac", | "cmac", | ||||
"cmp", | |||||
"cms", | "cms", | ||||
"comp", | "comp", | ||||
"crypto-mdebug", | "crypto-mdebug", | ||||
"crypto-mdebug-backtrace", | |||||
"ct", | "ct", | ||||
"deprecated", | "deprecated", | ||||
"des", | "des", | ||||
"devcryptoeng", | "devcryptoeng", | ||||
"dgram", | "dgram", | ||||
"dh", | "dh", | ||||
"dsa", | "dsa", | ||||
"dso", | "dso", | ||||
"dtls", | "dtls", | ||||
"dynamic-engine", | "dynamic-engine", | ||||
"ec", | "ec", | ||||
"ec2m", | "ec2m", | ||||
"ec_nistp_64_gcc_128", | |||||
"ecdh", | "ecdh", | ||||
"ecdsa", | "ecdsa", | ||||
"ec_nistp_64_gcc_128", | |||||
"egd", | "egd", | ||||
"engine", | "engine", | ||||
"err", | "err", | ||||
"external-tests", | "external-tests", | ||||
"filenames", | "filenames", | ||||
"fuzz-libfuzzer", | "fips", | ||||
"fips-securitychecks", | |||||
"fuzz-afl", | "fuzz-afl", | ||||
"fuzz-libfuzzer", | |||||
"gost", | "gost", | ||||
"heartbeats", | |||||
"hw(-.+)?", | |||||
"idea", | "idea", | ||||
"ktls", | |||||
"legacy", | |||||
"loadereng", | |||||
"makedepend", | "makedepend", | ||||
"md2", | "md2", | ||||
"md4", | "md4", | ||||
"mdc2", | "mdc2", | ||||
"module", | |||||
"msan", | "msan", | ||||
"multiblock", | "multiblock", | ||||
"nextprotoneg", | "nextprotoneg", | ||||
"pinshared", | |||||
"ocb", | "ocb", | ||||
"ocsp", | "ocsp", | ||||
"padlockeng", | |||||
"pic", | "pic", | ||||
"pinshared", | |||||
"poly1305", | "poly1305", | ||||
"posix-io", | "posix-io", | ||||
"psk", | "psk", | ||||
"rc2", | "rc2", | ||||
"rc4", | "rc4", | ||||
"rc5", | "rc5", | ||||
"rdrand", | "rdrand", | ||||
"rfc3779", | "rfc3779", | ||||
"rmd160", | "rmd160", | ||||
"scrypt", | "scrypt", | ||||
"sctp", | "sctp", | ||||
"secure-memory", | |||||
"seed", | "seed", | ||||
"shared", | "shared", | ||||
"siphash", | "siphash", | ||||
"siv", | |||||
"sm2", | "sm2", | ||||
"sm3", | "sm3", | ||||
"sm4", | "sm4", | ||||
"sock", | "sock", | ||||
"srp", | "srp", | ||||
"srtp", | "srtp", | ||||
"sse2", | "sse2", | ||||
"ssl", | "ssl", | ||||
"ssl-trace", | "ssl-trace", | ||||
"static-engine", | "static-engine", | ||||
"stdio", | "stdio", | ||||
"tests", | "tests", | ||||
"threads", | "threads", | ||||
"tls", | "tls", | ||||
"trace", | |||||
"ts", | "ts", | ||||
"ubsan", | "ubsan", | ||||
"ui-console", | "ui-console", | ||||
"unit-test", | "unit-test", | ||||
"whirlpool", | "uplink", | ||||
"weak-ssl-ciphers", | "weak-ssl-ciphers", | ||||
"whirlpool", | |||||
"zlib", | "zlib", | ||||
"zlib-dynamic", | "zlib-dynamic", | ||||
); | ); | ||||
foreach my $proto ((@tls, @dtls)) | foreach my $proto ((@tls, @dtls)) | ||||
{ | { | ||||
push(@disablables, $proto); | push(@disablables, $proto); | ||||
push(@disablables, "$proto-method") unless $proto eq "tls1_3"; | push(@disablables, "$proto-method") unless $proto eq "tls1_3"; | ||||
} | } | ||||
# Internal disablables, for aliasing purposes. They serve no special | |||||
# purpose here, but allow scripts to get to know them through configdata.pm, | |||||
# where these are merged with @disablables. | |||||
# The actual aliasing mechanism is done via %disable_cascades | |||||
my @disablables_int = qw( | |||||
crmf | |||||
); | |||||
my %deprecated_disablables = ( | my %deprecated_disablables = ( | ||||
"ssl2" => undef, | "ssl2" => undef, | ||||
"buf-freelists" => undef, | "buf-freelists" => undef, | ||||
"crypto-mdebug-backtrace" => undef, | |||||
"hw" => "hw", # causes cascade, but no macro | |||||
"hw-padlock" => "padlockeng", | |||||
"ripemd" => "rmd160", | "ripemd" => "rmd160", | ||||
"ui" => "ui-console", | "ui" => "ui-console", | ||||
"heartbeats" => undef, | |||||
); | ); | ||||
# All of the following are disabled by default: | # All of the following are disabled by default: | ||||
our %disabled = ( # "what" => "comment" | our %disabled = ( # "what" => "comment" | ||||
"fips" => "default", | |||||
"asan" => "default", | "asan" => "default", | ||||
"buildtest-c++" => "default", | "buildtest-c++" => "default", | ||||
"crypto-mdebug" => "default", | "crypto-mdebug" => "default", | ||||
"crypto-mdebug-backtrace" => "default", | "crypto-mdebug-backtrace" => "default", | ||||
"devcryptoeng" => "default", | "devcryptoeng" => "default", | ||||
"ec_nistp_64_gcc_128" => "default", | "ec_nistp_64_gcc_128" => "default", | ||||
"egd" => "default", | "egd" => "default", | ||||
"external-tests" => "default", | "external-tests" => "default", | ||||
"fuzz-libfuzzer" => "default", | |||||
"fuzz-afl" => "default", | "fuzz-afl" => "default", | ||||
"heartbeats" => "default", | "fuzz-libfuzzer" => "default", | ||||
"ktls" => "default", | |||||
"md2" => "default", | "md2" => "default", | ||||
"msan" => "default", | "msan" => "default", | ||||
"rc5" => "default", | "rc5" => "default", | ||||
"sctp" => "default", | "sctp" => "default", | ||||
"ssl-trace" => "default", | |||||
"ssl3" => "default", | "ssl3" => "default", | ||||
"ssl3-method" => "default", | "ssl3-method" => "default", | ||||
"trace" => "default", | |||||
"ubsan" => "default", | "ubsan" => "default", | ||||
"unit-test" => "default", | "unit-test" => "default", | ||||
"weak-ssl-ciphers" => "default", | "weak-ssl-ciphers" => "default", | ||||
"zlib" => "default", | "zlib" => "default", | ||||
"zlib-dynamic" => "default", | "zlib-dynamic" => "default", | ||||
); | ); | ||||
# Note: => pair form used for aesthetics, not to truly make a hash table | # Note: => pair form used for aesthetics, not to truly make a hash table | ||||
my @disable_cascades = ( | my @disable_cascades = ( | ||||
# "what" => [ "cascade", ... ] | # "what" => [ "cascade", ... ] | ||||
"bulk" => [ "shared", "dso", | |||||
"aria", "async", "autoload-config", | |||||
"blake2", "bf", "camellia", "cast", "chacha", | |||||
"cmac", "cms", "cmp", "comp", "ct", | |||||
"des", "dgram", "dh", "dsa", | |||||
"ec", "engine", | |||||
"filenames", | |||||
"idea", "ktls", | |||||
"md4", "multiblock", "nextprotoneg", | |||||
"ocsp", "ocb", "poly1305", "psk", | |||||
"rc2", "rc4", "rmd160", | |||||
"seed", "siphash", "siv", | |||||
"sm3", "sm4", "srp", | |||||
"srtp", "ssl3-method", "ssl-trace", | |||||
"ts", "ui-console", "whirlpool", | |||||
"fips-securitychecks" ], | |||||
sub { $config{processor} eq "386" } | sub { $config{processor} eq "386" } | ||||
=> [ "sse2" ], | => [ "sse2" ], | ||||
"ssl" => [ "ssl3" ], | "ssl" => [ "ssl3" ], | ||||
"ssl3-method" => [ "ssl3" ], | "ssl3-method" => [ "ssl3" ], | ||||
"zlib" => [ "zlib-dynamic" ], | "zlib" => [ "zlib-dynamic" ], | ||||
"des" => [ "mdc2" ], | "des" => [ "mdc2" ], | ||||
"ec" => [ "ecdsa", "ecdh" ], | "ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ], | ||||
"dgram" => [ "dtls", "sctp" ], | "dgram" => [ "dtls", "sctp" ], | ||||
"sock" => [ "dgram" ], | "sock" => [ "dgram" ], | ||||
"dtls" => [ @dtls ], | "dtls" => [ @dtls ], | ||||
sub { 0 == scalar grep { !$disabled{$_} } @dtls } | sub { 0 == scalar grep { !$disabled{$_} } @dtls } | ||||
=> [ "dtls" ], | => [ "dtls" ], | ||||
"tls" => [ @tls ], | "tls" => [ @tls ], | ||||
sub { 0 == scalar grep { !$disabled{$_} } @tls } | sub { 0 == scalar grep { !$disabled{$_} } @tls } | ||||
=> [ "tls" ], | => [ "tls" ], | ||||
"crypto-mdebug" => [ "crypto-mdebug-backtrace" ], | "crypto-mdebug" => [ "crypto-mdebug-backtrace" ], | ||||
# Without position independent code, there can be no shared libraries or DSOs | # If no modules, then no dynamic engines either | ||||
"pic" => [ "shared" ], | "module" => [ "dynamic-engine" ], | ||||
"shared" => [ "dynamic-engine" ], | |||||
"dso" => [ "dynamic-engine" ], | |||||
"engine" => [ "afalgeng", "devcryptoeng" ], | |||||
# Without shared libraries, dynamic engines aren't possible. | |||||
# This is due to them having to link with libcrypto and register features | |||||
# using the ENGINE functionality, and since that relies on global tables, | |||||
# those *have* to be exacty the same as the ones accessed from the app, | |||||
# which cannot be guaranteed if shared libraries aren't present. | |||||
# (note that even with shared libraries, both the app and dynamic engines | |||||
# must be linked with the same library) | |||||
"shared" => [ "dynamic-engine", "uplink" ], | |||||
"dso" => [ "dynamic-engine", "module" ], | |||||
# Other modules don't necessarily have to link with libcrypto, so shared | |||||
# libraries do not have to be a condition to produce those. | |||||
# Without position independent code, there can be no shared libraries | |||||
# or modules. | |||||
"pic" => [ "shared", "module" ], | |||||
"module" => [ "fips", "dso" ], | |||||
"engine" => [ "dynamic-engine", grep(/eng$/, @disablables) ], | |||||
"dynamic-engine" => [ "loadereng" ], | |||||
"hw" => [ "padlockeng" ], | |||||
# no-autoalginit is only useful when building non-shared | # no-autoalginit is only useful when building non-shared | ||||
"autoalginit" => [ "shared", "apps" ], | "autoalginit" => [ "shared", "apps", "fips" ], | ||||
"stdio" => [ "apps", "capieng", "egd" ], | "stdio" => [ "apps", "capieng", "egd" ], | ||||
"apps" => [ "tests" ], | "apps" => [ "tests" ], | ||||
"tests" => [ "external-tests" ], | "tests" => [ "external-tests" ], | ||||
"comp" => [ "zlib" ], | "comp" => [ "zlib" ], | ||||
"ec" => [ "tls1_3", "sm2" ], | |||||
"sm3" => [ "sm2" ], | "sm3" => [ "sm2" ], | ||||
sub { !$disabled{"unit-test"} } => [ "heartbeats" ], | sub { !$disabled{"unit-test"} } => [ "heartbeats" ], | ||||
sub { !$disabled{"msan"} } => [ "asm" ], | sub { !$disabled{"msan"} } => [ "asm" ], | ||||
"cmac" => [ "siv" ], | |||||
"legacy" => [ "md2" ], | |||||
"cmp" => [ "crmf" ], | |||||
"fips" => [ "fips-securitychecks", "acvp-tests" ], | |||||
"deprecated-3.0" => [ "engine", "srp" ] | |||||
); | ); | ||||
# Avoid protocol support holes. Also disable all versions below N, if version | # Avoid protocol support holes. Also disable all versions below N, if version | ||||
# N is disabled while N+1 is enabled. | # N is disabled while N+1 is enabled. | ||||
# | # | ||||
my @list = (reverse @tls); | my @list = (reverse @tls); | ||||
while ((my $first, my $second) = (shift @list, shift @list)) { | while ((my $first, my $second) = (shift @list, shift @list)) { | ||||
last unless @list; | last unless @list; | ||||
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } | push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } | ||||
=> [ @list ] ); | => [ @list ] ); | ||||
unshift @list, $second; | unshift @list, $second; | ||||
} | } | ||||
my @list = (reverse @dtls); | my @list = (reverse @dtls); | ||||
while ((my $first, my $second) = (shift @list, shift @list)) { | while ((my $first, my $second) = (shift @list, shift @list)) { | ||||
last unless @list; | last unless @list; | ||||
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } | push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } | ||||
=> [ @list ] ); | => [ @list ] ); | ||||
unshift @list, $second; | unshift @list, $second; | ||||
} | } | ||||
# Explicit "no-..." options will be collected in %disabled along with the defaults. | # Explicit "no-..." options will be collected in %disabled along with the defaults. | ||||
# To remove something from %disabled, use "enable-foo". | # To remove something from %disabled, use "enable-foo". | ||||
# For symmetry, "disable-foo" is a synonym for "no-foo". | # For symmetry, "disable-foo" is a synonym for "no-foo". | ||||
&usage if ($#ARGV < 0); | |||||
# For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with | # For the "make variables" CPPINCLUDES and CPPDEFINES, we support lists with | ||||
# platform specific list separators. Users from those platforms should | # platform specific list separators. Users from those platforms should | ||||
# recognise those separators from how you set up the PATH to find executables. | # recognise those separators from how you set up the PATH to find executables. | ||||
# The default is the Unix like separator, :, but as an exception, we also | # The default is the Unix like separator, :, but as an exception, we also | ||||
# support the space as separator. | # support the space as separator. | ||||
my $list_separator_re = | my $list_separator_re = | ||||
{ VMS => qr/(?<!\^),/, | { VMS => qr/(?<!\^),/, | ||||
MSWin32 => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/; | MSWin32 => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/; | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
$config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ]; | $config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ]; | ||||
$config{cppflags} = [ env('__CNF_CPPFLAGS') || () ]; | $config{cppflags} = [ env('__CNF_CPPFLAGS') || () ]; | ||||
$config{cflags} = [ env('__CNF_CFLAGS') || () ]; | $config{cflags} = [ env('__CNF_CFLAGS') || () ]; | ||||
$config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ]; | $config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ]; | ||||
$config{lflags} = [ env('__CNF_LDFLAGS') || () ]; | $config{lflags} = [ env('__CNF_LDFLAGS') || () ]; | ||||
$config{ex_libs} = [ env('__CNF_LDLIBS') || () ]; | $config{ex_libs} = [ env('__CNF_LDLIBS') || () ]; | ||||
$config{openssl_api_defines}=[]; | $config{openssl_api_defines}=[]; | ||||
$config{openssl_algorithm_defines}=[]; | |||||
$config{openssl_thread_defines}=[]; | |||||
$config{openssl_sys_defines}=[]; | $config{openssl_sys_defines}=[]; | ||||
$config{openssl_other_defines}=[]; | $config{openssl_feature_defines}=[]; | ||||
$config{options}=""; | $config{options}=""; | ||||
$config{build_type} = "release"; | $config{build_type} = "release"; | ||||
my $target=""; | my $target=""; | ||||
my %cmdvars = (); # Stores FOO='blah' type arguments | my %cmdvars = (); # Stores FOO='blah' type arguments | ||||
my %unsupported_options = (); | my %unsupported_options = (); | ||||
my %deprecated_options = (); | my %deprecated_options = (); | ||||
# If you change this, update apps/version.c | # If you change this, update apps/version.c | ||||
Show All 32 Lines | while (@argvcopy) | ||||
s/^-no-(?!integrated-as)/no-/; | s/^-no-(?!integrated-as)/no-/; | ||||
# rewrite some options in "enable-..." form | # rewrite some options in "enable-..." form | ||||
s /^-?-?shared$/enable-shared/; | s /^-?-?shared$/enable-shared/; | ||||
s /^sctp$/enable-sctp/; | s /^sctp$/enable-sctp/; | ||||
s /^threads$/enable-threads/; | s /^threads$/enable-threads/; | ||||
s /^zlib$/enable-zlib/; | s /^zlib$/enable-zlib/; | ||||
s /^zlib-dynamic$/enable-zlib-dynamic/; | s /^zlib-dynamic$/enable-zlib-dynamic/; | ||||
s /^fips$/enable-fips/; | |||||
if (/^(no|disable|enable)-(.+)$/) | if (/^(no|disable|enable)-(.+)$/) | ||||
{ | { | ||||
my $word = $2; | my $word = $2; | ||||
if (!exists $deprecated_disablables{$word} | if ($word !~ m|hw(?:-.+)| # special treatment for hw regexp opt | ||||
&& !grep { $word =~ /^${_}$/ } @disablables) | && !exists $deprecated_disablables{$word} | ||||
&& !grep { $word eq $_ } @disablables) | |||||
{ | { | ||||
$unsupported_options{$_} = 1; | $unsupported_options{$_} = 1; | ||||
next; | next; | ||||
} | } | ||||
} | } | ||||
if (/^no-(.+)$/ || /^disable-(.+)$/) | if (/^no-(.+)$/ || /^disable-(.+)$/) | ||||
{ | { | ||||
foreach my $proto ((@tls, @dtls)) | foreach my $proto ((@tls, @dtls)) | ||||
Show All 31 Lines | while (@argvcopy) | ||||
delete $disabled{"dynamic-engine"}; | delete $disabled{"dynamic-engine"}; | ||||
} | } | ||||
elsif ($1 eq "dynamic-engine") | elsif ($1 eq "dynamic-engine") | ||||
{ | { | ||||
$disabled{"dynamic-engine"} = "option"; | $disabled{"dynamic-engine"} = "option"; | ||||
} | } | ||||
elsif (exists $deprecated_disablables{$1}) | elsif (exists $deprecated_disablables{$1}) | ||||
{ | { | ||||
if ($deprecated_disablables{$1} ne "") | |||||
{ | |||||
$deprecated_options{$_} = 1; | $deprecated_options{$_} = 1; | ||||
if (defined $deprecated_disablables{$1}) | if (defined $deprecated_disablables{$1}) | ||||
{ | { | ||||
$disabled{$deprecated_disablables{$1}} = "option"; | $disabled{$deprecated_disablables{$1}} = "option"; | ||||
} | } | ||||
} | } | ||||
elsif ($1 =~ m|hw(?:-.+)|) # deprecate hw options in regexp form | |||||
{ | |||||
$deprecated_options{$_} = 1; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
$disabled{$1} = "option"; | $disabled{$1} = "option"; | ||||
} | } | ||||
# No longer an automatic choice | # No longer an automatic choice | ||||
$auto_threads = 0 if ($1 eq "threads"); | $auto_threads = 0 if ($1 eq "threads"); | ||||
} | } | ||||
Show All 12 Lines | while (@argvcopy) | ||||
delete $disabled{"zlib"}; | delete $disabled{"zlib"}; | ||||
} | } | ||||
my $algo = $1; | my $algo = $1; | ||||
delete $disabled{$algo}; | delete $disabled{$algo}; | ||||
# No longer an automatic choice | # No longer an automatic choice | ||||
$auto_threads = 0 if ($1 eq "threads"); | $auto_threads = 0 if ($1 eq "threads"); | ||||
} | } | ||||
elsif (/^-d$/) # From older 'config' | |||||
{ | |||||
$config{build_type} = "debug"; | |||||
} | |||||
elsif (/^-v$/) # From older 'config' | |||||
{ | |||||
$guess_opts{verbose} = 1; | |||||
} | |||||
elsif (/^-w$/) | |||||
{ | |||||
$guess_opts{nowait} = 1; | |||||
} | |||||
elsif (/^-t$/) # From older 'config' | |||||
{ | |||||
$dryrun = 1; | |||||
} | |||||
elsif (/^--strict-warnings$/) | elsif (/^--strict-warnings$/) | ||||
{ | { | ||||
# Pretend that our strict flags is a C flag, and replace it | # Pretend that our strict flags is a C flag, and replace it | ||||
# with the proper flags later on | # with the proper flags later on | ||||
push @{$useradd{CFLAGS}}, '--ossl-strict-warnings'; | push @{$useradd{CFLAGS}}, '--ossl-strict-warnings'; | ||||
$strict_warnings=1; | $strict_warnings=1; | ||||
} | } | ||||
elsif (/^--debug$/) | elsif (/^--debug$/) | ||||
{ | { | ||||
$config{build_type} = "debug"; | $config{build_type} = "debug"; | ||||
} | } | ||||
elsif (/^--release$/) | elsif (/^--release$/) | ||||
{ | { | ||||
$config{build_type} = "release"; | $config{build_type} = "release"; | ||||
} | } | ||||
elsif (/^386$/) | elsif (/^386$/) | ||||
{ $config{processor}=386; } | { $config{processor}=386; } | ||||
elsif (/^fips$/) | |||||
{ | |||||
die "FIPS mode not supported\n"; | |||||
} | |||||
elsif (/^rsaref$/) | elsif (/^rsaref$/) | ||||
{ | { | ||||
# No RSAref support any more since it's not needed. | # No RSAref support any more since it's not needed. | ||||
# The check for the option is there so scripts aren't | # The check for the option is there so scripts aren't | ||||
# broken | # broken | ||||
} | } | ||||
elsif (/^nofipscanistercheck$/) | |||||
{ | |||||
die "FIPS mode not supported\n"; | |||||
} | |||||
elsif (m|^[-+/]|) | elsif (m|^[-+/]|) | ||||
{ | { | ||||
if (/^--prefix=(.*)$/) | if (/^--prefix=(.*)$/) | ||||
{ | { | ||||
$config{prefix}=$1; | $config{prefix}=$1; | ||||
die "Directory given with --prefix MUST be absolute\n" | die "Directory given with --prefix MUST be absolute\n" | ||||
unless file_name_is_absolute($config{prefix}); | unless file_name_is_absolute($config{prefix}); | ||||
} | } | ||||
elsif (/^--api=(.*)$/) | elsif (/^--api=(.*)$/) | ||||
{ | { | ||||
$config{api}=$1; | my $api = $1; | ||||
die "Unknown API compatibility level $api" | |||||
unless defined $apitable->{$api}; | |||||
$config{api}=$apitable->{$api}; | |||||
} | } | ||||
elsif (/^--libdir=(.*)$/) | elsif (/^--libdir=(.*)$/) | ||||
{ | { | ||||
$config{libdir}=$1; | $config{libdir}=$1; | ||||
} | } | ||||
elsif (/^--openssldir=(.*)$/) | elsif (/^--openssldir=(.*)$/) | ||||
{ | { | ||||
$config{openssldir}=$1; | $config{openssldir}=$1; | ||||
Show All 18 Lines | while (@argvcopy) | ||||
{ | { | ||||
foreach my $x (split(m|,|, $1)) | foreach my $x (split(m|,|, $1)) | ||||
{ | { | ||||
die "Unknown --with-rand-seed choice $x\n" | die "Unknown --with-rand-seed choice $x\n" | ||||
if ! grep { $x eq $_ } @known_seed_sources; | if ! grep { $x eq $_ } @known_seed_sources; | ||||
push @seed_sources, $x; | push @seed_sources, $x; | ||||
} | } | ||||
} | } | ||||
elsif (/^--fips-key=(.*)$/) | |||||
{ | |||||
$user{FIPSKEY}=lc($1); | |||||
die "Non-hex character in FIPS key\n" | |||||
if $user{FIPSKEY} =~ /[^a-f0-9]/; | |||||
die "FIPS key must have even number of characters\n" | |||||
if length $1 & 1; | |||||
die "FIPS key too long (64 bytes max)\n" | |||||
if length $1 > 64; | |||||
} | |||||
elsif (/^--banner=(.*)$/) | |||||
{ | |||||
$banner = $1 . "\n"; | |||||
} | |||||
elsif (/^--cross-compile-prefix=(.*)$/) | elsif (/^--cross-compile-prefix=(.*)$/) | ||||
{ | { | ||||
$user{CROSS_COMPILE}=$1; | $user{CROSS_COMPILE}=$1; | ||||
} | } | ||||
elsif (/^--config=(.*)$/) | elsif (/^--config=(.*)$/) | ||||
{ | { | ||||
read_config $1; | read_config $1; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | while (@argvcopy) | ||||
if ($config{options} eq "") | if ($config{options} eq "") | ||||
{ $config{options} = $_; } | { $config{options} = $_; } | ||||
else | else | ||||
{ $config{options} .= " ".$_; } | { $config{options} .= " ".$_; } | ||||
} | } | ||||
} | } | ||||
if (defined($config{api}) && !exists $apitable->{$config{api}}) { | |||||
die "***** Unsupported api compatibility level: $config{api}\n", | |||||
} | |||||
if (keys %deprecated_options) | if (keys %deprecated_options) | ||||
{ | { | ||||
warn "***** Deprecated options: ", | warn "***** Deprecated options: ", | ||||
join(", ", keys %deprecated_options), "\n"; | join(", ", keys %deprecated_options), "\n"; | ||||
} | } | ||||
if (keys %unsupported_options) | if (keys %unsupported_options) | ||||
{ | { | ||||
die "***** Unsupported options: ", | die "***** Unsupported options: ", | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ()) | if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ()) | ||||
&& !$disabled{shared} | && !$disabled{shared} | ||||
&& !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) { | && !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) { | ||||
die "***** Cannot simultaneously use -rpath, shared libraries, and\n", | die "***** Cannot simultaneously use -rpath, shared libraries, and\n", | ||||
"***** any of asan, msan or ubsan\n"; | "***** any of asan, msan or ubsan\n"; | ||||
} | } | ||||
# If no target was given, try guessing. | |||||
unless ($target) { | |||||
my %system_config = OpenSSL::config::get_platform(%guess_opts, %user); | |||||
# The $system_config{disable} is used to populate %disabled with | |||||
# entries that aren't already there. | |||||
foreach ( @{$system_config{disable} // []} ) { | |||||
$disabled{$_} = 'system' unless defined $disabled{$_}; | |||||
} | |||||
delete $system_config{disable}; | |||||
# Override config entries with stuff from the guesser. | |||||
# It's assumed that this really is nothing new. | |||||
%config = ( %config, %system_config ); | |||||
$target = $system_config{target}; | |||||
} | |||||
sub disable { | sub disable { | ||||
my $disable_type = shift; | my $disable_type = shift; | ||||
for (@_) { | for (@_) { | ||||
$disabled{$_} = $disable_type; | $disabled{$_} = $disable_type; | ||||
} | } | ||||
my @tocheckfor = (@_ ? @_ : keys %disabled); | my @tocheckfor = (@_ ? @_ : keys %disabled); | ||||
Show All 34 Lines | if ($target eq "HASH") { | ||||
local $die = sub { warn @_; }; | local $die = sub { warn @_; }; | ||||
print "%table = (\n"; | print "%table = (\n"; | ||||
foreach (sort keys %table) { | foreach (sort keys %table) { | ||||
print_table_entry($_, "HASH"); | print_table_entry($_, "HASH"); | ||||
} | } | ||||
exit 0; | exit 0; | ||||
} | } | ||||
print "Configuring OpenSSL version $config{version} ($config{version_num}) "; | print "Configuring OpenSSL version $config{full_version} "; | ||||
print "for $target\n"; | print "for target $target\n"; | ||||
if (scalar(@seed_sources) == 0) { | if (scalar(@seed_sources) == 0) { | ||||
print "Using os-specific seed configuration\n"; | print "Using os-specific seed configuration\n"; | ||||
push @seed_sources, 'os'; | push @seed_sources, 'os'; | ||||
} | } | ||||
if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) { | if (scalar(grep { $_ eq 'egd' } @seed_sources) > 0) { | ||||
delete $disabled{'egd'}; | delete $disabled{'egd'}; | ||||
} | } | ||||
if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) { | if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) { | ||||
die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1; | die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1; | ||||
warn <<_____ if scalar(@seed_sources) == 1; | warn <<_____ if scalar(@seed_sources) == 1; | ||||
============================== WARNING =============================== | ============================== WARNING =============================== | ||||
You have selected the --with-rand-seed=none option, which effectively | You have selected the --with-rand-seed=none option, which effectively | ||||
disables automatic reseeding of the OpenSSL random generator. | disables automatic reseeding of the OpenSSL random generator. | ||||
All operations depending on the random generator such as creating keys | All operations depending on the random generator such as creating keys | ||||
will not work unless the random generator is seeded manually by the | will not work unless the random generator is seeded manually by the | ||||
application. | application. | ||||
Please read the 'Note on random number generation' section in the | Please read the 'Note on random number generation' section in the | ||||
INSTALL instructions and the RAND_DRBG(7) manual page for more details. | INSTALL.md instructions and the RAND_DRBG(7) manual page for more | ||||
details. | |||||
============================== WARNING =============================== | ============================== WARNING =============================== | ||||
_____ | _____ | ||||
} | } | ||||
push @{$config{openssl_other_defines}}, | push @{$config{openssl_feature_defines}}, | ||||
map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" } | map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" } | ||||
@seed_sources; | @seed_sources; | ||||
# Backward compatibility? | # Backward compatibility? | ||||
if ($target =~ m/^CygWin32(-.*)$/) { | if ($target =~ m/^CygWin32(-.*)$/) { | ||||
$target = "Cygwin".$1; | $target = "Cygwin".$1; | ||||
} | } | ||||
# Support for legacy targets having a name starting with 'debug-' | # Support for legacy targets having a name starting with 'debug-' | ||||
my ($d, $t) = $target =~ m/^(debug-)?(.*)$/; | my ($d, $t) = $target =~ m/^(debug-)?(.*)$/; | ||||
if ($d) { | if ($d) { | ||||
$config{build_type} = "debug"; | $config{build_type} = "debug"; | ||||
# If we do not find debug-foo in the table, the target is set to foo. | # If we do not find debug-foo in the table, the target is set to foo. | ||||
if (!$table{$target}) { | if (!$table{$target}) { | ||||
$target = $t; | $target = $t; | ||||
} | } | ||||
} | } | ||||
&usage if !$table{$target} || $table{$target}->{template}; | if ($target) { | ||||
# It's possible that we have different config targets for specific | |||||
# toolchains, so we try to detect them, and go for the plain config | |||||
# target if not. | |||||
my $found; | |||||
foreach ( ( "$target-$user{CC}", "$target", undef ) ) { | |||||
$found=$_ if $table{$_} && !$table{$_}->{template}; | |||||
last if $found; | |||||
} | |||||
$target = $found; | |||||
} else { | |||||
# If we don't have a config target now, we try the C compiler as we | |||||
# fallback | |||||
my $cc = $user{CC} // 'cc'; | |||||
$target = $cc if $table{$cc} && !$table{$cc}->{template}; | |||||
} | |||||
&usage unless $target; | |||||
exit 0 if $dryrun; # From older 'config' | |||||
$config{target} = $target; | $config{target} = $target; | ||||
my %target = resolve_config($target); | my %target = resolve_config($target); | ||||
foreach (keys %target_attr_translate) { | foreach (keys %target_attr_translate) { | ||||
$target{$target_attr_translate{$_}} = $target{$_} | $target{$target_attr_translate{$_}} = $target{$_} | ||||
if $target{$_}; | if $target{$_}; | ||||
delete $target{$_}; | delete $target{$_}; | ||||
} | } | ||||
Show All 18 Lines | if ("default" eq ($disabled{$feature} // "")) { | ||||
if (exists $deprecated_disablables{$feature}) { | if (exists $deprecated_disablables{$feature}) { | ||||
warn "***** config $target enables deprecated feature $feature\n"; | warn "***** config $target enables deprecated feature $feature\n"; | ||||
} elsif (!grep { $feature eq $_ } @disablables) { | } elsif (!grep { $feature eq $_ } @disablables) { | ||||
die "***** config $target enables unknown feature $feature\n"; | die "***** config $target enables unknown feature $feature\n"; | ||||
} | } | ||||
delete $disabled{$feature}; | delete $disabled{$feature}; | ||||
} | } | ||||
} | } | ||||
# If uplink_arch isn't defined, disable uplink | |||||
$disabled{uplink} = 'no uplink_arch' unless (defined $target{uplink_arch}); | |||||
# If asm_arch isn't defined, disable asm | |||||
$disabled{asm} = 'no asm_arch' unless (defined $target{asm_arch}); | |||||
disable(); # Run a cascade now | disable(); # Run a cascade now | ||||
$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX}; | $target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX}; | ||||
$target{cxxflags}//=$target{cflags} if $target{CXX}; | $target{cxxflags}//=$target{cflags} if $target{CXX}; | ||||
$target{exe_extension}=""; | $target{exe_extension}=".exe" if ($config{target} eq "DJGPP"); | ||||
$target{exe_extension}=".exe" if ($config{target} eq "DJGPP" | |||||
|| $config{target} =~ /^(?:Cygwin|mingw)/); | |||||
$target{exe_extension}=".pm" if ($config{target} =~ /vos/); | $target{exe_extension}=".pm" if ($config{target} =~ /vos/); | ||||
($target{shared_extension_simple}=$target{shared_extension}) | |||||
=~ s|\.\$\(SHLIB_VERSION_NUMBER\)|| | |||||
unless defined($target{shared_extension_simple}); | |||||
$target{dso_extension}//=$target{shared_extension_simple}; | |||||
($target{shared_import_extension}=$target{shared_extension_simple}.".a") | |||||
if ($config{target} =~ /^(?:Cygwin|mingw)/); | |||||
# Fill %config with values from %user, and in case those are undefined or | # Fill %config with values from %user, and in case those are undefined or | ||||
# empty, use values from %target (acting as a default). | # empty, use values from %target (acting as a default). | ||||
foreach (keys %user) { | foreach (keys %user) { | ||||
my $ref_type = ref $user{$_}; | my $ref_type = ref $user{$_}; | ||||
# Temporary function. Takes an intended ref type (empty string or "ARRAY") | # Temporary function. Takes an intended ref type (empty string or "ARRAY") | ||||
# and a value that's to be coerced into that type. | # and a value that's to be coerced into that type. | ||||
my $mkvalue = sub { | my $mkvalue = sub { | ||||
Show All 34 Lines | if (defined $config{$_}) { | ||||
push @{$config{$_}}, @{$useradd{$_}}; | push @{$config{$_}}, @{$useradd{$_}}; | ||||
} else { | } else { | ||||
$config{$_} = [ @{$useradd{$_}} ]; | $config{$_} = [ @{$useradd{$_}} ]; | ||||
} | } | ||||
} | } | ||||
# At this point, we can forget everything about %user and %useradd, | # At this point, we can forget everything about %user and %useradd, | ||||
# because it's now all been merged into the corresponding $config entry | # because it's now all been merged into the corresponding $config entry | ||||
if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) { | if (grep { $_ =~ /(?:^|\s)-static(?:\s|$)/ } @{$config{LDFLAGS}}) { | ||||
disable('static', 'pic', 'threads'); | disable('static', 'pic', 'threads'); | ||||
} | } | ||||
# Allow overriding the build file name | # Allow overriding the build file name | ||||
$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile"; | $config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile"; | ||||
# Make sure build_scheme is consistent. | # Make sure build_scheme is consistent. | ||||
$target{build_scheme} = [ $target{build_scheme} ] | $target{build_scheme} = [ $target{build_scheme} ] | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if ($auto_threads) { | ||||
if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) { | if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) { | ||||
die "You asked for multi-threading support, but didn't\n" | die "You asked for multi-threading support, but didn't\n" | ||||
,"provide any system-specific compiler options\n"; | ,"provide any system-specific compiler options\n"; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
# Find out if clang's sanitizers have been enabled with -fsanitize | |||||
# flags and ensure that the corresponding %disabled elements area | |||||
# removed to reflect that the sanitizers are indeed enabled. | |||||
my %detected_sanitizers = (); | |||||
foreach (grep /^-fsanitize=/, @{$config{CFLAGS} || []}) { | |||||
(my $checks = $_) =~ s/^-fsanitize=//; | |||||
foreach (split /,/, $checks) { | |||||
my $d = { address => 'asan', | |||||
undefined => 'ubsan', | |||||
memory => 'msan' } -> {$_}; | |||||
next unless defined $d; | |||||
$detected_sanitizers{$d} = 1; | |||||
if (defined $disabled{$d}) { | |||||
die "***** Conflict between disabling $d and enabling $_ sanitizer" | |||||
if $disabled{$d} ne "default"; | |||||
delete $disabled{$d}; | |||||
} | |||||
} | |||||
} | |||||
# If threads still aren't disabled, add a C macro to ensure the source | # If threads still aren't disabled, add a C macro to ensure the source | ||||
# code knows about it. Any other flag is taken care of by the configs. | # code knows about it. Any other flag is taken care of by the configs. | ||||
unless($disabled{threads}) { | unless($disabled{threads}) { | ||||
push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS"; | push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS"; | ||||
} | } | ||||
# With "deprecated" disable all deprecated features. | |||||
if (defined($disabled{"deprecated"})) { | |||||
$config{api} = $maxapi; | |||||
} | |||||
my $no_shared_warn=0; | my $no_shared_warn=0; | ||||
if ($target{shared_target} eq "") | if (($target{shared_target} // '') eq "") | ||||
{ | { | ||||
$no_shared_warn = 1 | $no_shared_warn = 1 | ||||
if (!$disabled{shared} || !$disabled{"dynamic-engine"}); | if (!$disabled{shared} || !$disabled{"dynamic-engine"}); | ||||
disable('no-shared-target', 'pic'); | disable('no-shared-target', 'pic'); | ||||
} | } | ||||
if ($disabled{"dynamic-engine"}) { | if ($disabled{"dynamic-engine"}) { | ||||
$config{dynamic_engines} = 0; | $config{dynamic_engines} = 0; | ||||
} else { | } else { | ||||
$config{dynamic_engines} = 1; | $config{dynamic_engines} = 1; | ||||
} | } | ||||
unless ($disabled{asan}) { | unless ($disabled{asan} || defined $detected_sanitizers{asan}) { | ||||
push @{$config{cflags}}, "-fsanitize=address"; | push @{$config{cflags}}, "-fsanitize=address"; | ||||
push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX}; | |||||
} | } | ||||
unless ($disabled{ubsan}) { | unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) { | ||||
# -DPEDANTIC or -fnosanitize=alignment may also be required on some | push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC"; | ||||
# platforms. | |||||
push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"; | |||||
push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all" if $config{CXX}; | |||||
} | } | ||||
unless ($disabled{msan}) { | unless ($disabled{msan} || defined $detected_sanitizers{msan}) { | ||||
push @{$config{cflags}}, "-fsanitize=memory"; | push @{$config{cflags}}, "-fsanitize=memory"; | ||||
push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX}; | |||||
} | } | ||||
unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} | unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"} | ||||
&& $disabled{asan} && $disabled{ubsan} && $disabled{msan}) { | && $disabled{asan} && $disabled{ubsan} && $disabled{msan}) { | ||||
push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g"; | push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g"; | ||||
push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX}; | push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX}; | ||||
} | } | ||||
# | # | ||||
Show All 17 Lines | else | ||||
push @{$config{lib_defines}}, "OPENSSL_PIC"; | push @{$config{lib_defines}}, "OPENSSL_PIC"; | ||||
} | } | ||||
if ($target{sys_id} ne "") | if ($target{sys_id} ne "") | ||||
{ | { | ||||
push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; | push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; | ||||
} | } | ||||
unless ($disabled{asm}) { | |||||
$target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386"); | |||||
push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c"); | |||||
$target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m})); | |||||
# bn-586 is the only one implementing bn_*_part_words | |||||
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/); | |||||
push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/); | |||||
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/); | |||||
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/); | |||||
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/); | |||||
push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/); | |||||
if ($target{sha1_asm_src}) { | |||||
push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/); | |||||
push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/); | |||||
push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/); | |||||
} | |||||
if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) { | |||||
push @{$config{lib_defines}}, "KECCAK1600_ASM"; | |||||
} | |||||
if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) { | |||||
push @{$config{lib_defines}}, "RC4_ASM"; | |||||
} | |||||
if ($target{md5_asm_src}) { | |||||
push @{$config{lib_defines}}, "MD5_ASM"; | |||||
} | |||||
$target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC | |||||
if ($target{rmd160_asm_src}) { | |||||
push @{$config{lib_defines}}, "RMD160_ASM"; | |||||
} | |||||
if ($target{aes_asm_src}) { | |||||
push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);; | |||||
push @{$config{lib_defines}}, "AESNI_ASM" if ($target{aes_asm_src} =~ m/\baesni-/);; | |||||
# aes-ctr.fake is not a real file, only indication that assembler | |||||
# module implements AES_ctr32_encrypt... | |||||
push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//); | |||||
# aes-xts.fake indicates presence of AES_xts_[en|de]crypt... | |||||
push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//); | |||||
$target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2}); | |||||
push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/); | |||||
push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/); | |||||
} | |||||
if ($target{wp_asm_src} =~ /mmx/) { | |||||
if ($config{processor} eq "386") { | |||||
$target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src}; | |||||
} elsif (!$disabled{"whirlpool"}) { | |||||
push @{$config{lib_defines}}, "WHIRLPOOL_ASM"; | |||||
} | |||||
} | |||||
if ($target{modes_asm_src} =~ /ghash-/) { | |||||
push @{$config{lib_defines}}, "GHASH_ASM"; | |||||
} | |||||
if ($target{ec_asm_src} =~ /ecp_nistz256/) { | |||||
push @{$config{lib_defines}}, "ECP_NISTZ256_ASM"; | |||||
} | |||||
if ($target{ec_asm_src} =~ /x25519/) { | |||||
push @{$config{lib_defines}}, "X25519_ASM"; | |||||
} | |||||
if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) { | |||||
push @{$config{dso_defines}}, "PADLOCK_ASM"; | |||||
} | |||||
if ($target{poly1305_asm_src} ne "") { | |||||
push @{$config{lib_defines}}, "POLY1305_ASM"; | |||||
} | |||||
} | |||||
my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); | my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC}); | ||||
my %predefined_CXX = $config{CXX} | my %predefined_CXX = $config{CXX} | ||||
? compiler_predefined($config{CROSS_COMPILE}.$config{CXX}) | ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX}) | ||||
: (); | : (); | ||||
unless ($disabled{asm}) { | |||||
# big endian systems can use ELFv2 ABI | |||||
if ($target eq "linux-ppc64") { | |||||
$target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2); | |||||
} | |||||
} | |||||
# Check for makedepend capabilities. | # Check for makedepend capabilities. | ||||
if (!$disabled{makedepend}) { | if (!$disabled{makedepend}) { | ||||
if ($config{target} =~ /^(VC|vms)-/) { | # If the attribute makedep_scheme is defined, then we assume that the | ||||
# For VC- and vms- targets, there's nothing more to do here. The | # config target and its associated build file are programmed to deal | ||||
# functionality is hard coded in the corresponding build files for | # with it. | ||||
# cl (Windows) and CC/DECC (VMS). | # If makedep_scheme is undefined, we go looking for GCC compatible | ||||
# dependency making, and if that's not available, we try to fall back | |||||
# on 'makedepend'. | |||||
if ($target{makedep_scheme}) { | |||||
$config{makedep_scheme} = $target{makedep_scheme}; | |||||
# If the makedepcmd attribute is defined, copy it. If not, the | |||||
# build files will have to fend for themselves. | |||||
$config{makedepcmd} = $target{makedepcmd} if $target{makedepcmd}; | |||||
} elsif (($predefined_C{__GNUC__} // -1) >= 3 | } elsif (($predefined_C{__GNUC__} // -1) >= 3 | ||||
&& !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) { | && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) { | ||||
# We know that GNU C version 3 and up as well as all clang | # We know that GNU C version 3 and up as well as all clang | ||||
# versions support dependency generation, but Xcode did not | # versions support dependency generation, but Xcode did not | ||||
# handle $cc -M before clang support (but claims __GNUC__ = 3) | # handle $cc -M before clang support (but claims __GNUC__ = 3) | ||||
$config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}"; | $config{makedep_scheme} = 'gcc'; | ||||
} else { | } else { | ||||
# In all other cases, we look for 'makedepend', and disable the | # In all other cases, we look for 'makedepend', and set the | ||||
# capability if not found. | # makedep_scheme value if we found it. | ||||
$config{makedepprog} = which('makedepend'); | $config{makedepcmd} = which('makedepend'); | ||||
disable('unavailable', 'makedepend') unless $config{makedepprog}; | $config{makedep_scheme} = 'makedepend' if $config{makedepcmd}; | ||||
} | } | ||||
# If no depend scheme is set, we disable makedepend | |||||
disable('unavailable', 'makedepend') unless $config{makedep_scheme}; | |||||
} | } | ||||
if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') { | if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') { | ||||
# probe for -Wa,--noexecstack option... | # probe for -Wa,--noexecstack option... | ||||
if ($predefined_C{__clang__}) { | if ($predefined_C{__clang__}) { | ||||
# clang has builtin assembler, which doesn't recognize --help, | # clang has builtin assembler, which doesn't recognize --help, | ||||
# but it apparently recognizes the option in question on all | # but it apparently recognizes the option in question on all | ||||
# supported platforms even when it's meaningless. In other words | # supported platforms even when it's meaningless. In other words | ||||
Show All 11 Lines | if ($predefined_C{__clang__}) { | ||||
close(PIPE); | close(PIPE); | ||||
unlink("null.$$.o"); | unlink("null.$$.o"); | ||||
} | } | ||||
} | } | ||||
# Deal with bn_ops ################################################### | # Deal with bn_ops ################################################### | ||||
$config{bn_ll} =0; | $config{bn_ll} =0; | ||||
$config{export_var_as_fn} =0; | |||||
my $def_int="unsigned int"; | my $def_int="unsigned int"; | ||||
$config{rc4_int} =$def_int; | $config{rc4_int} =$def_int; | ||||
($config{b64l},$config{b64},$config{b32})=(0,0,1); | ($config{b64l},$config{b64},$config{b32})=(0,0,1); | ||||
my $count = 0; | my $count = 0; | ||||
foreach (sort split(/\s+/,$target{bn_ops})) { | foreach (sort split(/\s+/,$target{bn_ops})) { | ||||
$count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/; | $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/; | ||||
$config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN'; | |||||
$config{bn_ll}=1 if $_ eq 'BN_LLONG'; | $config{bn_ll}=1 if $_ eq 'BN_LLONG'; | ||||
$config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR'; | $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR'; | ||||
($config{b64l},$config{b64},$config{b32}) | ($config{b64l},$config{b64},$config{b32}) | ||||
=(0,1,0) if $_ eq 'SIXTY_FOUR_BIT'; | =(0,1,0) if $_ eq 'SIXTY_FOUR_BIT'; | ||||
($config{b64l},$config{b64},$config{b32}) | ($config{b64l},$config{b64},$config{b32}) | ||||
=(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG'; | =(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG'; | ||||
($config{b64l},$config{b64},$config{b32}) | ($config{b64l},$config{b64},$config{b32}) | ||||
=(0,0,1) if $_ eq 'THIRTY_TWO_BIT'; | =(0,0,1) if $_ eq 'THIRTY_TWO_BIT'; | ||||
} | } | ||||
die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n" | die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n" | ||||
if $count > 1; | if $count > 1; | ||||
$config{api} = $config{major} * 10000 + $config{minor} * 100 | |||||
unless $config{api}; | |||||
foreach (keys %$apitable) { | |||||
$disabled{"deprecated-$_"} = "deprecation" | |||||
if $disabled{deprecated} && $config{api} >= $apitable->{$_}; | |||||
} | |||||
disable(); # Run a cascade now | |||||
# Hack cflags for better warnings (dev option) ####################### | # Hack cflags for better warnings (dev option) ####################### | ||||
# "Stringify" the C and C++ flags string. This permits it to be made part of | # "Stringify" the C and C++ flags string. This permits it to be made part of | ||||
# a string and works as well on command lines. | # a string and works as well on command lines. | ||||
$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } | $config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } | ||||
@{$config{cflags}} ]; | @{$config{cflags}} ]; | ||||
$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } | $config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x } | ||||
@{$config{cxxflags}} ] if $config{CXX}; | @{$config{cxxflags}} ] if $config{CXX}; | ||||
if (defined($config{api})) { | $config{openssl_api_defines} = [ | ||||
$config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; | "OPENSSL_CONFIGURED_API=".$config{api}, | ||||
my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}}); | ]; | ||||
push @{$config{defines}}, $apiflag; | |||||
} | |||||
my @strict_warnings_collection=(); | my @strict_warnings_collection=(); | ||||
if ($strict_warnings) | if ($strict_warnings) | ||||
{ | { | ||||
my $wopt; | my $wopt; | ||||
my $gccver = $predefined_C{__GNUC__} // -1; | my $gccver = $predefined_C{__GNUC__} // -1; | ||||
if ($gccver >= 4) | if ($gccver >= 4) | ||||
Show All 12 Lines | if ($strict_warnings) | ||||
} | } | ||||
} | } | ||||
$config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings' | $config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings' | ||||
? @strict_warnings_collection | ? @strict_warnings_collection | ||||
: ( $_ ) } | : ( $_ ) } | ||||
@{$config{CFLAGS}} ]; | @{$config{CFLAGS}} ]; | ||||
unless ($disabled{"crypto-mdebug-backtrace"}) | |||||
{ | |||||
foreach my $wopt (split /\s+/, $memleak_devteam_backtrace) | |||||
{ | |||||
push @{$config{cflags}}, $wopt | |||||
unless grep { $_ eq $wopt } @{$config{cflags}}; | |||||
} | |||||
if ($target =~ /^BSD-/) | |||||
{ | |||||
push @{$config{ex_libs}}, "-lexecinfo"; | |||||
} | |||||
} | |||||
unless ($disabled{afalgeng}) { | unless ($disabled{afalgeng}) { | ||||
$config{afalgeng}=""; | $config{afalgeng}=""; | ||||
if (grep { $_ eq 'afalgeng' } @{$target{enable}}) { | if (grep { $_ eq 'afalgeng' } @{$target{enable}}) { | ||||
my $minver = 4*10000 + 1*100 + 0; | my $minver = 4*10000 + 1*100 + 0; | ||||
if ($config{CROSS_COMPILE} eq "") { | if ($config{CROSS_COMPILE} eq "") { | ||||
my $verstr = `uname -r`; | my $verstr = `uname -r`; | ||||
my ($ma, $mi1, $mi2) = split("\\.", $verstr); | my ($ma, $mi1, $mi2) = split("\\.", $verstr); | ||||
($mi2) = $mi2 =~ /(\d+)/; | ($mi2) = $mi2 =~ /(\d+)/; | ||||
Show All 21 Lines | if ($target =~ m/^BSD/) { | ||||
my ($ma, $mi, @rest) = split m|\.|, $verstr; | my ($ma, $mi, @rest) = split m|\.|, $verstr; | ||||
my $ver = $ma*100 + $mi; | my $ver = $ma*100 + $mi; | ||||
if ($sysstr eq 'OpenBSD' && $ver >= $maxver) { | if ($sysstr eq 'OpenBSD' && $ver >= $maxver) { | ||||
disable('too-new-kernel', 'devcryptoeng'); | disable('too-new-kernel', 'devcryptoeng'); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
unless ($disabled{ktls}) { | |||||
$config{ktls}=""; | |||||
my $cc = $config{CROSS_COMPILE}.$config{CC}; | |||||
if ($target =~ m/^linux/) { | |||||
system("printf '#include <sys/types.h>\n#include <linux/tls.h>' | $cc -E - >/dev/null 2>&1"); | |||||
if ($? != 0) { | |||||
disable('too-old-kernel', 'ktls'); | |||||
} | |||||
} elsif ($target =~ m/^BSD/) { | |||||
system("printf '#include <sys/types.h>\n#include <sys/ktls.h>' | $cc -E - >/dev/null 2>&1"); | |||||
if ($? != 0) { | |||||
disable('too-old-freebsd', 'ktls'); | |||||
} | |||||
} else { | |||||
disable('not-linux-or-freebsd', 'ktls'); | |||||
} | |||||
} | |||||
push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); | |||||
# Get the extra flags used when building shared libraries and modules. We | # Get the extra flags used when building shared libraries and modules. We | ||||
# do this late because some of them depend on %disabled. | # do this late because some of them depend on %disabled. | ||||
# Make the flags to build DSOs the same as for shared libraries unless they | # Make the flags to build DSOs the same as for shared libraries unless they | ||||
# are already defined | # are already defined | ||||
$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags}; | $target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags}; | ||||
$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags}; | $target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags}; | ||||
$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags}; | $target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags}; | ||||
Show All 27 Lines | if (defined $si) { | ||||
? add($si->{$_})->($target{$_}) | ? add($si->{$_})->($target{$_}) | ||||
: $si->{$_}; | : $si->{$_}; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON | # ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON | ||||
###################################################################### | |||||
# Build up information for skipping certain directories depending on disabled | |||||
# features, as well as setting up macros for disabled features. | |||||
# This is a tentative database of directories to skip. Some entries may not | |||||
# correspond to anything real, but that's ok, they will simply be ignored. | |||||
# The actual processing of these entries is done in the build.info lookup | |||||
# loop further down. | |||||
# | |||||
# The key is a Unix formatted path in the source tree, the value is an index | |||||
# into %disabled_info, so any existing path gets added to a corresponding | |||||
# 'skipped' entry in there with the list of skipped directories. | |||||
my %skipdir = (); | |||||
my %disabled_info = (); # For configdata.pm | my %disabled_info = (); # For configdata.pm | ||||
foreach my $what (sort keys %disabled) { | foreach my $what (sort keys %disabled) { | ||||
# There are deprecated disablables that translate to themselves. | |||||
# They cause disabling cascades, but should otherwise not regiter. | |||||
next if $deprecated_disablables{$what}; | |||||
# The generated $disabled{"deprecated-x.y"} entries are special | |||||
# and treated properly elsewhere | |||||
next if $what =~ m|^deprecated-|; | |||||
$config{options} .= " no-$what"; | $config{options} .= " no-$what"; | ||||
if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic', | if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared', | ||||
'dynamic-engine', 'makedepend', | 'module', 'pic', 'dynamic-engine', 'makedepend', | ||||
'zlib-dynamic', 'zlib', 'sse2' )) { | 'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) { | ||||
(my $WHAT = uc $what) =~ s|-|_|g; | (my $WHAT = uc $what) =~ s|-|_|g; | ||||
my $skipdir = $what; | |||||
# Fix up C macro end names | |||||
$WHAT = "RMD160" if $what eq "ripemd"; | |||||
# fix-up crypto/directory name(s) | # fix-up crypto/directory name(s) | ||||
$what = "ripemd" if $what eq "rmd160"; | $skipdir = "ripemd" if $what eq "rmd160"; | ||||
$what = "whrlpool" if $what eq "whirlpool"; | $skipdir = "whrlpool" if $what eq "whirlpool"; | ||||
my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT"; | my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT"; | ||||
push @{$config{openssl_feature_defines}}, $macro; | |||||
if ((grep { $what eq $_ } @{$config{sdirs}}) | $skipdir{engines} = $what if $what eq 'engine'; | ||||
&& $what ne 'async' && $what ne 'err' && $what ne 'dso') { | $skipdir{"crypto/$skipdir"} = $what | ||||
@{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}}; | unless $what eq 'async' || $what eq 'err' || $what eq 'dso'; | ||||
$disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ]; | |||||
if ($what ne 'engine') { | |||||
push @{$config{openssl_algorithm_defines}}, $macro; | |||||
} else { | |||||
@{$config{dirs}} = grep !/^engines$/, @{$config{dirs}}; | |||||
push @{$disabled_info{engine}->{skipped}}, catdir('engines'); | |||||
push @{$config{openssl_other_defines}}, $macro; | |||||
} | } | ||||
} else { | |||||
push @{$config{openssl_other_defines}}, $macro; | |||||
} | } | ||||
} | |||||
} | |||||
if ($disabled{"dynamic-engine"}) { | if ($disabled{"dynamic-engine"}) { | ||||
push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; | push @{$config{openssl_feature_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; | ||||
} else { | } else { | ||||
push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE"; | push @{$config{openssl_feature_defines}}, "OPENSSL_NO_STATIC_ENGINE"; | ||||
} | } | ||||
# If we use the unified build, collect information from build.info files | # If we use the unified build, collect information from build.info files | ||||
my %unified_info = (); | my %unified_info = (); | ||||
my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO}); | my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO}); | ||||
if ($builder eq "unified") { | if ($builder eq "unified") { | ||||
use with_fallback qw(Text::Template); | use Text::Template 1.46; | ||||
sub cleandir { | sub cleandir { | ||||
my $base = shift; | my $base = shift; | ||||
my $dir = shift; | my $dir = shift; | ||||
my $relativeto = shift || "."; | my $relativeto = shift || "."; | ||||
$dir = catdir($base,$dir) unless isabsolute($dir); | $dir = catdir($base,$dir) unless isabsolute($dir); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | for $_ (@build_file_templates) { | ||||
$build_file_template = undef; | $build_file_template = undef; | ||||
} | } | ||||
if (!defined $build_file_template) { | if (!defined $build_file_template) { | ||||
die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n"; | die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n"; | ||||
} | } | ||||
$config{build_file_templates} | $config{build_file_templates} | ||||
= [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"), | = [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"), | ||||
$blddir), | $blddir), | ||||
$build_file_template, | $build_file_template ]; | ||||
cleanfile($srcdir, catfile("Configurations", "common.tmpl"), | |||||
$blddir) ]; | |||||
my @build_infos = ( [ ".", "build.info" ] ); | my @build_dirs = ( [ ] ); # current directory | ||||
foreach (@{$config{dirs}}) { | |||||
push @build_infos, [ $_, "build.info" ] | |||||
if (-f catfile($srcdir, $_, "build.info")); | |||||
} | |||||
foreach (@{$config{sdirs}}) { | |||||
push @build_infos, [ catdir("crypto", $_), "build.info" ] | |||||
if (-f catfile($srcdir, "crypto", $_, "build.info")); | |||||
} | |||||
foreach (@{$config{engdirs}}) { | |||||
push @build_infos, [ catdir("engines", $_), "build.info" ] | |||||
if (-f catfile($srcdir, "engines", $_, "build.info")); | |||||
} | |||||
foreach (@{$config{tdirs}}) { | |||||
push @build_infos, [ catdir("test", $_), "build.info" ] | |||||
if (-f catfile($srcdir, "test", $_, "build.info")); | |||||
} | |||||
$config{build_infos} = [ ]; | $config{build_infos} = [ ]; | ||||
# We want to detect configdata.pm in the source tree, so we | |||||
# don't use it if the build tree is different. | |||||
my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir); | |||||
# Any source file that we recognise is placed in this hash table, with | |||||
# the list of its intended destinations as value. When everything has | |||||
# been collected, there's a routine that checks that these source files | |||||
# exist, or if they are generated, that the generator exists. | |||||
my %check_exist = (); | |||||
my %check_generate = (); | |||||
my %ordinals = (); | my %ordinals = (); | ||||
foreach (@build_infos) { | while (@build_dirs) { | ||||
my $sourced = catdir($srcdir, $_->[0]); | my @curd = @{shift @build_dirs}; | ||||
my $buildd = catdir($blddir, $_->[0]); | my $sourced = catdir($srcdir, @curd); | ||||
my $buildd = catdir($blddir, @curd); | |||||
my $unixdir = join('/', @curd); | |||||
if (exists $skipdir{$unixdir}) { | |||||
my $what = $skipdir{$unixdir}; | |||||
push @{$disabled_info{$what}->{skipped}}, catdir(@curd); | |||||
next; | |||||
} | |||||
mkpath($buildd); | mkpath($buildd); | ||||
my $f = $_->[1]; | my $f = 'build.info'; | ||||
# The basic things we're trying to build | # The basic things we're trying to build | ||||
my @programs = (); | my @programs = (); | ||||
my @programs_install = (); | |||||
my @libraries = (); | my @libraries = (); | ||||
my @libraries_install = (); | my @modules = (); | ||||
my @engines = (); | |||||
my @engines_install = (); | |||||
my @scripts = (); | my @scripts = (); | ||||
my @scripts_install = (); | |||||
my @extra = (); | |||||
my @overrides = (); | |||||
my @intermediates = (); | |||||
my @rawlines = (); | |||||
my %sources = (); | my %sources = (); | ||||
my %shared_sources = (); | my %shared_sources = (); | ||||
my %includes = (); | my %includes = (); | ||||
my %defines = (); | |||||
my %depends = (); | my %depends = (); | ||||
my %renames = (); | |||||
my %sharednames = (); | |||||
my %generate = (); | my %generate = (); | ||||
my %imagedocs = (); | |||||
my %htmldocs = (); | |||||
my %mandocs = (); | |||||
# We want to detect configdata.pm in the source tree, so we | # Support for $variablename in build.info files. | ||||
# don't use it if the build tree is different. | # Embedded perl code is the ultimate master, still. If its output | ||||
my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir); | # contains a dollar sign, it had better be escaped, or it will be | ||||
# taken for a variable name prefix. | |||||
my %variables = (); | |||||
# Variable name syntax | |||||
my $variable_name_re = qr/(?P<VARIABLE>[[:alpha:]][[:alnum:]_]*)/; | |||||
# Value modifier syntaxes | |||||
my $variable_subst_re = qr/\/(?P<RE>(?:\\\/|.)*?)\/(?P<SUBST>.*?)/; | |||||
# Variable reference | |||||
my $variable_simple_re = qr/(?<!\\)\$${variable_name_re}/; | |||||
my $variable_w_mod_re = | |||||
qr/(?<!\\)\$\{${variable_name_re}(?P<MOD>(?:\\\/|.)*?)\}/; | |||||
# Tie it all together | |||||
my $variable_re = qr/${variable_simple_re}|${variable_w_mod_re}/; | |||||
my $expand_variables = sub { | |||||
my $value = ''; | |||||
my $value_rest = shift; | |||||
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { | |||||
print STDERR | |||||
"DEBUG[\$expand_variables] Parsed '$value_rest' ...\n" | |||||
} | |||||
while ($value_rest =~ /${variable_re}/) { | |||||
# We must save important regexp values, because the next | |||||
# regexp clears them | |||||
my $mod = $+{MOD}; | |||||
my $variable_value = $variables{$+{VARIABLE}}; | |||||
$value_rest = $'; | |||||
$value .= $`; | |||||
# Process modifier expressions, if present | |||||
if (defined $mod) { | |||||
if ($mod =~ /^${variable_subst_re}$/) { | |||||
my $re = $+{RE}; | |||||
my $subst = $+{SUBST}; | |||||
$variable_value =~ s/\Q$re\E/$subst/g; | |||||
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { | |||||
print STDERR | |||||
"DEBUG[\$expand_variables] ... and substituted ", | |||||
"'$re' with '$subst'\n"; | |||||
} | |||||
} | |||||
} | |||||
$value .= $variable_value; | |||||
} | |||||
if ($ENV{CONFIGURE_DEBUG_VARIABLE_EXPAND}) { | |||||
print STDERR | |||||
"DEBUG[\$expand_variables] ... into: '$value$value_rest'\n"; | |||||
} | |||||
return $value . $value_rest; | |||||
}; | |||||
# Support for attributes in build.info files | |||||
my %attributes = (); | |||||
my $handle_attributes = sub { | |||||
my $attr_str = shift; | |||||
my $ref = shift; | |||||
my @goals = @_; | |||||
return unless defined $attr_str; | |||||
my @a = tokenize($attr_str, qr|\s*,\s*|); | |||||
foreach my $a (@a) { | |||||
my $ac = 1; | |||||
my $ak = $a; | |||||
my $av = 1; | |||||
if ($a =~ m|^(!)?(.*?)\s* = \s*(.*?)$|x) { | |||||
$ac = ! $1; | |||||
$ak = $2; | |||||
$av = $3; | |||||
} | |||||
foreach my $g (@goals) { | |||||
if ($ac) { | |||||
$$ref->{$g}->{$ak} = $av; | |||||
} else { | |||||
delete $$ref->{$g}->{$ak}; | |||||
} | |||||
} | |||||
} | |||||
}; | |||||
# Support for pushing values on multiple indexes of a given hash | |||||
# array. | |||||
my $push_to = sub { | |||||
my $valueref = shift; | |||||
my $index_str = shift; # May be undef or empty | |||||
my $attrref = shift; # May be undef | |||||
my $attr_str = shift; | |||||
my @values = @_; | |||||
if (defined $index_str) { | |||||
my @indexes = ( '' ); | |||||
if ($index_str !~ m|^\s*$|) { | |||||
@indexes = tokenize($index_str); | |||||
} | |||||
foreach (@indexes) { | |||||
push @{$valueref->{$_}}, @values; | |||||
if (defined $attrref) { | |||||
$handle_attributes->($attr_str, \$$attrref->{$_}, | |||||
@values); | |||||
} | |||||
} | |||||
} else { | |||||
push @$valueref, @values; | |||||
$handle_attributes->($attr_str, $attrref, @values) | |||||
if defined $attrref; | |||||
} | |||||
}; | |||||
if ($buildinfo_debug) { | |||||
print STDERR "DEBUG: Reading ",catfile($sourced, $f),"\n"; | |||||
} | |||||
push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f); | push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f); | ||||
my $template = | my $template = | ||||
Text::Template->new(TYPE => 'FILE', | Text::Template->new(TYPE => 'FILE', | ||||
SOURCE => catfile($sourced, $f), | SOURCE => catfile($sourced, $f), | ||||
PREPEND => qq{use lib "$FindBin::Bin/util/perl";}); | PREPEND => qq{use lib "$FindBin::Bin/util/perl";}); | ||||
die "Something went wrong with $sourced/$f: $!\n" unless $template; | die "Something went wrong with $sourced/$f: $!\n" unless $template; | ||||
my @text = | my @text = | ||||
split /^/m, | split /^/m, | ||||
Show All 9 Lines | while (@build_dirs) { | ||||
# The top item of this stack has the following values | # The top item of this stack has the following values | ||||
# -2 positive already run and we found ELSE (following ELSIF should fail) | # -2 positive already run and we found ELSE (following ELSIF should fail) | ||||
# -1 positive already run (skip until ENDIF) | # -1 positive already run (skip until ENDIF) | ||||
# 0 negatives so far (if we're at a condition, check it) | # 0 negatives so far (if we're at a condition, check it) | ||||
# 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) | # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) | ||||
# 2 positive ELSE (following ELSIF should fail) | # 2 positive ELSE (following ELSIF should fail) | ||||
my @skip = (); | my @skip = (); | ||||
# A few useful generic regexps | |||||
my $index_re = qr/\[\s*(?P<INDEX>(?:\\.|.)*?)\s*\]/; | |||||
my $cond_re = qr/\[\s*(?P<COND>(?:\\.|.)*?)\s*\]/; | |||||
my $attribs_re = qr/(?:\{\s*(?P<ATTRIBS>(?:\\.|.)*?)\s*\})?/; | |||||
my $value_re = qr/(?P<VALUE>.*?)/; | |||||
collect_information( | collect_information( | ||||
collect_from_array([ @text ], | collect_from_array([ @text ], | ||||
qr/\\$/ => sub { my $l1 = shift; my $l2 = shift; | qr/\\$/ => sub { my $l1 = shift; my $l2 = shift; | ||||
$l1 =~ s/\\$//; $l1.$l2 }), | $l1 =~ s/\\$//; $l1.$l2 }), | ||||
# Info we're looking for | # Info we're looking for | ||||
qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/ | qr/^\s* IF ${cond_re} \s*$/x | ||||
=> sub { | => sub { | ||||
if (! @skip || $skip[$#skip] > 0) { | if (! @skip || $skip[$#skip] > 0) { | ||||
push @skip, !! $1; | push @skip, !! $expand_variables->($+{COND}); | ||||
} else { | } else { | ||||
push @skip, -1; | push @skip, -1; | ||||
} | } | ||||
}, | }, | ||||
qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/ | qr/^\s* ELSIF ${cond_re} \s*$/x | ||||
=> sub { die "ELSIF out of scope" if ! @skip; | => sub { die "ELSIF out of scope" if ! @skip; | ||||
die "ELSIF following ELSE" if abs($skip[$#skip]) == 2; | die "ELSIF following ELSE" if abs($skip[$#skip]) == 2; | ||||
$skip[$#skip] = -1 if $skip[$#skip] != 0; | $skip[$#skip] = -1 if $skip[$#skip] != 0; | ||||
$skip[$#skip] = !! $1 | $skip[$#skip] = !! $expand_variables->($+{COND}) | ||||
if $skip[$#skip] == 0; }, | if $skip[$#skip] == 0; }, | ||||
qr/^\s*ELSE\s*$/ | qr/^\s* ELSE \s*$/x | ||||
=> sub { die "ELSE out of scope" if ! @skip; | => sub { die "ELSE out of scope" if ! @skip; | ||||
$skip[$#skip] = -2 if $skip[$#skip] != 0; | $skip[$#skip] = -2 if $skip[$#skip] != 0; | ||||
$skip[$#skip] = 2 if $skip[$#skip] == 0; }, | $skip[$#skip] = 2 if $skip[$#skip] == 0; }, | ||||
qr/^\s*ENDIF\s*$/ | qr/^\s* ENDIF \s*$/x | ||||
=> sub { die "ENDIF out of scope" if ! @skip; | => sub { die "ENDIF out of scope" if ! @skip; | ||||
pop @skip; }, | pop @skip; }, | ||||
qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/ | qr/^\s* ${variable_re} \s* = \s* ${value_re} \s* $/x | ||||
=> sub { | => sub { | ||||
if (!@skip || $skip[$#skip] > 0) { | if (!@skip || $skip[$#skip] > 0) { | ||||
my $install = $1; | $variables{$+{VARIABLE}} = $expand_variables->($+{VALUE}); | ||||
my @x = tokenize($2); | |||||
push @programs, @x; | |||||
push @programs_install, @x unless $install; | |||||
} | } | ||||
}, | }, | ||||
qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/ | qr/^\s* SUBDIRS \s* = \s* ${value_re} \s* $/x | ||||
=> sub { | => sub { | ||||
if (!@skip || $skip[$#skip] > 0) { | if (!@skip || $skip[$#skip] > 0) { | ||||
my $install = $1; | foreach (tokenize($expand_variables->($+{VALUE}))) { | ||||
my @x = tokenize($2); | push @build_dirs, [ @curd, splitdir($_, 1) ]; | ||||
push @libraries, @x; | |||||
push @libraries_install, @x unless $install; | |||||
} | } | ||||
}, | |||||
qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/ | |||||
=> sub { | |||||
if (!@skip || $skip[$#skip] > 0) { | |||||
my $install = $1; | |||||
my @x = tokenize($2); | |||||
push @engines, @x; | |||||
push @engines_install, @x unless $install; | |||||
} | } | ||||
}, | }, | ||||
qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/ | qr/^\s* PROGRAMS ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
=> sub { | => sub { $push_to->(\@programs, undef, | ||||
if (!@skip || $skip[$#skip] > 0) { | \$attributes{programs}, $+{ATTRIBS}, | ||||
my $install = $1; | tokenize($expand_variables->($+{VALUE}))) | ||||
my @x = tokenize($2); | if !@skip || $skip[$#skip] > 0; }, | ||||
push @scripts, @x; | qr/^\s* LIBS ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
push @scripts_install, @x unless $install; | => sub { $push_to->(\@libraries, undef, | ||||
} | \$attributes{libraries}, $+{ATTRIBS}, | ||||
}, | tokenize($expand_variables->($+{VALUE}))) | ||||
qr/^\s*EXTRA\s*=\s*(.*)\s*$/ | if !@skip || $skip[$#skip] > 0; }, | ||||
=> sub { push @extra, tokenize($1) | qr/^\s* MODULES ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
if !@skip || $skip[$#skip] > 0 }, | => sub { $push_to->(\@modules, undef, | ||||
qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/ | \$attributes{modules}, $+{ATTRIBS}, | ||||
=> sub { push @overrides, tokenize($1) | tokenize($expand_variables->($+{VALUE}))) | ||||
if !@skip || $skip[$#skip] > 0 }, | if !@skip || $skip[$#skip] > 0; }, | ||||
qr/^\s* SCRIPTS ${attribs_re} \s* = \s* ${value_re} \s* $/x | |||||
qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/, | => sub { $push_to->(\@scripts, undef, | ||||
=> sub { push @{$ordinals{$1}}, tokenize($2) | \$attributes{scripts}, $+{ATTRIBS}, | ||||
if !@skip || $skip[$#skip] > 0 }, | tokenize($expand_variables->($+{VALUE}))) | ||||
qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | if !@skip || $skip[$#skip] > 0; }, | ||||
=> sub { push @{$sources{$1}}, tokenize($2) | qr/^\s* IMAGEDOCS ${index_re} \s* = \s* ${value_re} \s* $/x | ||||
if !@skip || $skip[$#skip] > 0 }, | => sub { $push_to->(\%imagedocs, $expand_variables->($+{INDEX}), | ||||
qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | undef, undef, | ||||
=> sub { push @{$shared_sources{$1}}, tokenize($2) | tokenize($expand_variables->($+{VALUE}))) | ||||
if !@skip || $skip[$#skip] > 0 }, | if !@skip || $skip[$#skip] > 0; }, | ||||
qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | qr/^\s* HTMLDOCS ${index_re} \s* = \s* ${value_re} \s* $/x | ||||
=> sub { push @{$includes{$1}}, tokenize($2) | => sub { $push_to->(\%htmldocs, $expand_variables->($+{INDEX}), | ||||
if !@skip || $skip[$#skip] > 0 }, | undef, undef, | ||||
qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/ | tokenize($expand_variables->($+{VALUE}))) | ||||
=> sub { push @{$depends{$1}}, tokenize($2) | if !@skip || $skip[$#skip] > 0; }, | ||||
if !@skip || $skip[$#skip] > 0 }, | qr/^\s* MANDOCS ${index_re} \s* = \s* ${value_re} \s* $/x | ||||
qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | => sub { $push_to->(\%mandocs, $expand_variables->($+{INDEX}), | ||||
=> sub { push @{$generate{$1}}, $2 | undef, undef, | ||||
if !@skip || $skip[$#skip] > 0 }, | tokenize($expand_variables->($+{VALUE}))) | ||||
qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | if !@skip || $skip[$#skip] > 0; }, | ||||
=> sub { push @{$renames{$1}}, tokenize($2) | qr/^\s* SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
if !@skip || $skip[$#skip] > 0 }, | => sub { $push_to->(\%sources, $expand_variables->($+{INDEX}), | ||||
qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ | \$attributes{sources}, $+{ATTRIBS}, | ||||
=> sub { push @{$sharednames{$1}}, tokenize($2) | tokenize($expand_variables->($+{VALUE}))) | ||||
if !@skip || $skip[$#skip] > 0 }, | if !@skip || $skip[$#skip] > 0; }, | ||||
qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/ | qr/^\s* SHARED_SOURCE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
=> sub { | => sub { $push_to->(\%shared_sources, $expand_variables->($+{INDEX}), | ||||
my $lineiterator = shift; | \$attributes{sources}, $+{ATTRIBS}, | ||||
my $target_kind = $1; | tokenize($expand_variables->($+{VALUE}))) | ||||
while (defined $lineiterator->()) { | if !@skip || $skip[$#skip] > 0; }, | ||||
s|\R$||; | qr/^\s* INCLUDE ${index_re} \s* = \s* ${value_re} \s* $/x | ||||
if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) { | => sub { $push_to->(\%includes, $expand_variables->($+{INDEX}), | ||||
die "ENDRAW doesn't match BEGINRAW" | undef, undef, | ||||
if $1 ne $target_kind; | tokenize($expand_variables->($+{VALUE}))) | ||||
last; | if !@skip || $skip[$#skip] > 0; }, | ||||
} | qr/^\s* DEFINE ${index_re} \s* = \s* ${value_re} \s* $/x | ||||
next if @skip && $skip[$#skip] <= 0; | => sub { $push_to->(\%defines, $expand_variables->($+{INDEX}), | ||||
push @rawlines, $_ | undef, undef, | ||||
if ($target_kind eq $config{build_file} | tokenize($expand_variables->($+{VALUE}))) | ||||
|| $target_kind eq $config{build_file}."(".$builder_platform.")"); | if !@skip || $skip[$#skip] > 0; }, | ||||
} | qr/^\s* DEPEND ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x | ||||
}, | => sub { $push_to->(\%depends, $expand_variables->($+{INDEX}), | ||||
qr/^\s*(?:#.*)?$/ => sub { }, | \$attributes{depends}, $+{ATTRIBS}, | ||||
tokenize($expand_variables->($+{VALUE}))) | |||||
if !@skip || $skip[$#skip] > 0; }, | |||||
qr/^\s* GENERATE ${index_re} ${attribs_re} \s* = \s* ${value_re} \s* $/x | |||||
=> sub { $push_to->(\%generate, $expand_variables->($+{INDEX}), | |||||
\$attributes{generate}, $+{ATTRIBS}, | |||||
$expand_variables->($+{VALUE})) | |||||
if !@skip || $skip[$#skip] > 0; }, | |||||
qr/^\s* (?:\#.*)? $/x => sub { }, | |||||
"OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }, | "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" }, | ||||
"BEFORE" => sub { | "BEFORE" => sub { | ||||
if ($buildinfo_debug) { | if ($buildinfo_debug) { | ||||
print STDERR "DEBUG: Parsing ",join(" ", @_),"\n"; | print STDERR "DEBUG: Parsing ",join(" ", @_),"\n"; | ||||
print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; | print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; | ||||
} | } | ||||
}, | }, | ||||
"AFTER" => sub { | "AFTER" => sub { | ||||
if ($buildinfo_debug) { | if ($buildinfo_debug) { | ||||
print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; | print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n"; | ||||
} | } | ||||
}, | }, | ||||
); | ); | ||||
die "runaway IF?" if (@skip); | die "runaway IF?" if (@skip); | ||||
foreach (keys %renames) { | if (grep { defined $attributes{modules}->{$_}->{engine} } keys %attributes | ||||
die "$_ renamed to more than one thing: " | and !$config{dynamic_engines}) { | ||||
,join(" ", @{$renames{$_}}),"\n" | die <<"EOF" | ||||
if scalar @{$renames{$_}} > 1; | |||||
my $dest = cleanfile($buildd, $_, $blddir); | |||||
my $to = cleanfile($buildd, $renames{$_}->[0], $blddir); | |||||
die "$dest renamed to more than one thing: " | |||||
,$unified_info{rename}->{$dest}, $to | |||||
unless !defined($unified_info{rename}->{$dest}) | |||||
or $unified_info{rename}->{$dest} eq $to; | |||||
$unified_info{rename}->{$dest} = $to; | |||||
} | |||||
foreach (@programs) { | |||||
my $program = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$program}) { | |||||
$program = $unified_info{rename}->{$program}; | |||||
} | |||||
$unified_info{programs}->{$program} = 1; | |||||
} | |||||
foreach (@programs_install) { | |||||
my $program = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$program}) { | |||||
$program = $unified_info{rename}->{$program}; | |||||
} | |||||
$unified_info{install}->{programs}->{$program} = 1; | |||||
} | |||||
foreach (@libraries) { | |||||
my $library = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$library}) { | |||||
$library = $unified_info{rename}->{$library}; | |||||
} | |||||
$unified_info{libraries}->{$library} = 1; | |||||
} | |||||
foreach (@libraries_install) { | |||||
my $library = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$library}) { | |||||
$library = $unified_info{rename}->{$library}; | |||||
} | |||||
$unified_info{install}->{libraries}->{$library} = 1; | |||||
} | |||||
die <<"EOF" if scalar @engines and !$config{dynamic_engines}; | |||||
ENGINES can only be used if configured with 'dynamic-engine'. | ENGINES can only be used if configured with 'dynamic-engine'. | ||||
This is usually a fault in a build.info file. | This is usually a fault in a build.info file. | ||||
EOF | EOF | ||||
foreach (@engines) { | |||||
my $library = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$library}) { | |||||
$library = $unified_info{rename}->{$library}; | |||||
} | } | ||||
$unified_info{engines}->{$library} = 1; | |||||
} | |||||
foreach (@engines_install) { | { | ||||
my $library = cleanfile($buildd, $_, $blddir); | my %infos = ( programs => [ @programs ], | ||||
if ($unified_info{rename}->{$library}) { | libraries => [ @libraries ], | ||||
$library = $unified_info{rename}->{$library}; | modules => [ @modules ], | ||||
} | scripts => [ @scripts ] ); | ||||
$unified_info{install}->{engines}->{$library} = 1; | foreach my $k (keys %infos) { | ||||
} | foreach (@{$infos{$k}}) { | ||||
my $item = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{$k}->{$item} = 1; | |||||
foreach (@scripts) { | # Fix up associated attributes | ||||
my $script = cleanfile($buildd, $_, $blddir); | $unified_info{attributes}->{$k}->{$item} = | ||||
if ($unified_info{rename}->{$script}) { | $attributes{$k}->{$_} | ||||
$script = $unified_info{rename}->{$script}; | if defined $attributes{$k}->{$_}; | ||||
} | } | ||||
$unified_info{scripts}->{$script} = 1; | |||||
} | } | ||||
foreach (@scripts_install) { | |||||
my $script = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$script}) { | |||||
$script = $unified_info{rename}->{$script}; | |||||
} | } | ||||
$unified_info{install}->{scripts}->{$script} = 1; | |||||
} | |||||
foreach (@extra) { | |||||
my $extra = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{extra}->{$extra} = 1; | |||||
} | |||||
foreach (@overrides) { | |||||
my $override = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{overrides}->{$override} = 1; | |||||
} | |||||
push @{$unified_info{rawlines}}, @rawlines; | |||||
unless ($disabled{shared}) { | |||||
# Check sharednames. | |||||
foreach (keys %sharednames) { | |||||
my $dest = cleanfile($buildd, $_, $blddir); | |||||
if ($unified_info{rename}->{$dest}) { | |||||
$dest = $unified_info{rename}->{$dest}; | |||||
} | |||||
die "shared_name for $dest with multiple values: " | |||||
,join(" ", @{$sharednames{$_}}),"\n" | |||||
if scalar @{$sharednames{$_}} > 1; | |||||
my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir); | |||||
die "shared_name found for a library $dest that isn't defined\n" | |||||
unless $unified_info{libraries}->{$dest}; | |||||
die "shared_name for $dest with multiple values: " | |||||
,$unified_info{sharednames}->{$dest}, ", ", $to | |||||
unless !defined($unified_info{sharednames}->{$dest}) | |||||
or $unified_info{sharednames}->{$dest} eq $to; | |||||
$unified_info{sharednames}->{$dest} = $to; | |||||
} | |||||
# Additionally, we set up sharednames for libraries that don't | |||||
# have any, as themselves. Only for libraries that aren't | |||||
# explicitly static. | |||||
foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) { | |||||
if (!defined $unified_info{sharednames}->{$_}) { | |||||
$unified_info{sharednames}->{$_} = $_ | |||||
} | |||||
} | |||||
# Check that we haven't defined any library as both shared and | # Check that we haven't defined any library as both shared and | ||||
# explicitly static. That is forbidden. | # explicitly static. That is forbidden. | ||||
my @doubles = (); | my @doubles = (); | ||||
foreach (grep /\.a$/, keys %{$unified_info{libraries}}) { | foreach (grep /\.a$/, keys %{$unified_info{libraries}}) { | ||||
(my $l = $_) =~ s/\.a$//; | (my $l = $_) =~ s/\.a$//; | ||||
push @doubles, $l if defined $unified_info{sharednames}->{$l}; | push @doubles, $l if defined $unified_info{libraries}->{$l}; | ||||
} | } | ||||
die "these libraries are both explicitly static and shared:\n ", | die "these libraries are both explicitly static and shared:\n ", | ||||
join(" ", @doubles), "\n" | join(" ", @doubles), "\n" | ||||
if @doubles; | if @doubles; | ||||
} | |||||
foreach (keys %sources) { | foreach (keys %sources) { | ||||
my $dest = $_; | my $dest = $_; | ||||
my $ddest = cleanfile($buildd, $_, $blddir); | my $ddest = cleanfile($buildd, $_, $blddir); | ||||
if ($unified_info{rename}->{$ddest}) { | |||||
$ddest = $unified_info{rename}->{$ddest}; | |||||
} | |||||
foreach (@{$sources{$dest}}) { | foreach (@{$sources{$dest}}) { | ||||
my $s = cleanfile($sourced, $_, $blddir); | my $s = cleanfile($sourced, $_, $blddir); | ||||
# If it isn't in the source tree, we assume it's generated | # If it's generated or we simply don't find it in the source | ||||
# in the build tree | # tree, we assume it's in the build tree. | ||||
if ($s eq $src_configdata || ! -f $s || $generate{$_}) { | if ($s eq $src_configdata || $generate{$_} || ! -f $s) { | ||||
$s = cleanfile($buildd, $_, $blddir); | $s = cleanfile($buildd, $_, $blddir); | ||||
} | } | ||||
my $o = $_; | |||||
# We recognise C++, C and asm files | # We recognise C++, C and asm files | ||||
if ($s =~ /\.(cc|cpp|c|s|S)$/) { | if ($s =~ /\.(cc|cpp|c|s|S)$/) { | ||||
my $o = $_; | push @{$check_exist{$s}}, $ddest; | ||||
$o =~ s/\.[csS]$/.o/; # C and assembler | $o =~ s/\.[csS]$/.o/; # C and assembler | ||||
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++ | $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ | ||||
$o = cleanfile($buildd, $o, $blddir); | $o = cleanfile($buildd, $o, $blddir); | ||||
$unified_info{sources}->{$ddest}->{$o} = 1; | $unified_info{sources}->{$ddest}->{$o} = -1; | ||||
$unified_info{sources}->{$o}->{$s} = 1; | $unified_info{sources}->{$o}->{$s} = -1; | ||||
} elsif ($s =~ /\.rc$/) { | } elsif ($s =~ /\.rc$/) { | ||||
# We also recognise resource files | # We also recognise resource files | ||||
my $o = $_; | push @{$check_exist{$s}}, $ddest; | ||||
$o =~ s/\.rc$/.res/; # Resource configuration | $o =~ s/\.rc$/.res/; # Resource configuration | ||||
my $o = cleanfile($buildd, $o, $blddir); | $o = cleanfile($buildd, $o, $blddir); | ||||
$unified_info{sources}->{$ddest}->{$o} = 1; | $unified_info{sources}->{$ddest}->{$o} = -1; | ||||
$unified_info{sources}->{$o}->{$s} = 1; | $unified_info{sources}->{$o}->{$s} = -1; | ||||
} else { | } else { | ||||
push @{$check_exist{$s}}, $ddest; | |||||
$unified_info{sources}->{$ddest}->{$s} = 1; | $unified_info{sources}->{$ddest}->{$s} = 1; | ||||
} | } | ||||
# Fix up associated attributes | |||||
if ($o ne $_) { | |||||
$unified_info{attributes}->{sources}->{$ddest}->{$o} = | |||||
$unified_info{attributes}->{sources}->{$o}->{$s} = | |||||
$attributes{sources}->{$dest}->{$_} | |||||
if defined $attributes{sources}->{$dest}->{$_}; | |||||
} else { | |||||
$unified_info{attributes}->{sources}->{$ddest}->{$s} = | |||||
$attributes{sources}->{$dest}->{$_} | |||||
if defined $attributes{sources}->{$dest}->{$_}; | |||||
} | } | ||||
} | } | ||||
} | |||||
foreach (keys %shared_sources) { | foreach (keys %shared_sources) { | ||||
my $dest = $_; | my $dest = $_; | ||||
my $ddest = cleanfile($buildd, $_, $blddir); | my $ddest = cleanfile($buildd, $_, $blddir); | ||||
if ($unified_info{rename}->{$ddest}) { | |||||
$ddest = $unified_info{rename}->{$ddest}; | |||||
} | |||||
foreach (@{$shared_sources{$dest}}) { | foreach (@{$shared_sources{$dest}}) { | ||||
my $s = cleanfile($sourced, $_, $blddir); | my $s = cleanfile($sourced, $_, $blddir); | ||||
# If it isn't in the source tree, we assume it's generated | # If it's generated or we simply don't find it in the source | ||||
# in the build tree | # tree, we assume it's in the build tree. | ||||
if ($s eq $src_configdata || ! -f $s || $generate{$_}) { | if ($s eq $src_configdata || $generate{$_} || ! -f $s) { | ||||
$s = cleanfile($buildd, $_, $blddir); | $s = cleanfile($buildd, $_, $blddir); | ||||
} | } | ||||
my $o = $_; | |||||
if ($s =~ /\.(cc|cpp|c|s|S)$/) { | if ($s =~ /\.(cc|cpp|c|s|S)$/) { | ||||
# We recognise C++, C and asm files | # We recognise C++, C and asm files | ||||
my $o = $_; | push @{$check_exist{$s}}, $ddest; | ||||
$o =~ s/\.[csS]$/.o/; # C and assembler | $o =~ s/\.[csS]$/.o/; # C and assembler | ||||
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++ | $o =~ s/\.(cc|cpp)$/_cc.o/; # C++ | ||||
$o = cleanfile($buildd, $o, $blddir); | $o = cleanfile($buildd, $o, $blddir); | ||||
$unified_info{shared_sources}->{$ddest}->{$o} = 1; | $unified_info{shared_sources}->{$ddest}->{$o} = -1; | ||||
$unified_info{sources}->{$o}->{$s} = 1; | $unified_info{sources}->{$o}->{$s} = -1; | ||||
} elsif ($s =~ /\.rc$/) { | } elsif ($s =~ /\.rc$/) { | ||||
# We also recognise resource files | # We also recognise resource files | ||||
my $o = $_; | push @{$check_exist{$s}}, $ddest; | ||||
$o =~ s/\.rc$/.res/; # Resource configuration | $o =~ s/\.rc$/.res/; # Resource configuration | ||||
my $o = cleanfile($buildd, $o, $blddir); | $o = cleanfile($buildd, $o, $blddir); | ||||
$unified_info{shared_sources}->{$ddest}->{$o} = 1; | $unified_info{shared_sources}->{$ddest}->{$o} = -1; | ||||
$unified_info{sources}->{$o}->{$s} = 1; | $unified_info{sources}->{$o}->{$s} = -1; | ||||
} elsif ($s =~ /\.(def|map|opt)$/) { | } elsif ($s =~ /\.ld$/) { | ||||
# We also recognise .def / .map / .opt files | # We also recognise linker scripts (or corresponding) | ||||
# We know they are generated files | # We know they are generated files | ||||
my $def = cleanfile($buildd, $s, $blddir); | push @{$check_exist{$s}}, $ddest; | ||||
$unified_info{shared_sources}->{$ddest}->{$def} = 1; | $o = cleanfile($buildd, $_, $blddir); | ||||
$unified_info{shared_sources}->{$ddest}->{$o} = 1; | |||||
} else { | } else { | ||||
die "unrecognised source file type for shared library: $s\n"; | die "unrecognised source file type for shared library: $s\n"; | ||||
} | } | ||||
# Fix up associated attributes | |||||
if ($o ne $_) { | |||||
$unified_info{attributes}->{shared_sources}->{$ddest}->{$o} = | |||||
$unified_info{attributes}->{sources}->{$o}->{$s} = | |||||
$attributes{sources}->{$dest}->{$_} | |||||
if defined $attributes{sources}->{$dest}->{$_}; | |||||
} else { | |||||
$unified_info{attributes}->{shared_sources}->{$ddest}->{$o} = | |||||
$attributes{sources}->{$dest}->{$_} | |||||
if defined $attributes{sources}->{$dest}->{$_}; | |||||
} | } | ||||
} | } | ||||
} | |||||
foreach (keys %generate) { | foreach (keys %generate) { | ||||
my $dest = $_; | my $dest = $_; | ||||
my $ddest = cleanfile($buildd, $_, $blddir); | my $ddest = cleanfile($buildd, $_, $blddir); | ||||
if ($unified_info{rename}->{$ddest}) { | |||||
$ddest = $unified_info{rename}->{$ddest}; | |||||
} | |||||
die "more than one generator for $dest: " | die "more than one generator for $dest: " | ||||
,join(" ", @{$generate{$_}}),"\n" | ,join(" ", @{$generate{$_}}),"\n" | ||||
if scalar @{$generate{$_}} > 1; | if scalar @{$generate{$_}} > 1; | ||||
my @generator = split /\s+/, $generate{$dest}->[0]; | my @generator = split /\s+/, $generate{$dest}->[0]; | ||||
$generator[0] = cleanfile($sourced, $generator[0], $blddir), | my $gen = $generator[0]; | ||||
$generator[0] = cleanfile($sourced, $gen, $blddir); | |||||
# If the generator is itself generated, it's in the build tree | |||||
if ($generate{$gen} || ! -f $generator[0]) { | |||||
$generator[0] = cleanfile($buildd, $gen, $blddir); | |||||
} | |||||
$check_generate{$ddest}->{$generator[0]}++; | |||||
$unified_info{generate}->{$ddest} = [ @generator ]; | $unified_info{generate}->{$ddest} = [ @generator ]; | ||||
# Fix up associated attributes | |||||
$unified_info{attributes}->{generate}->{$ddest} = | |||||
$attributes{generate}->{$dest}->{$gen} | |||||
if defined $attributes{generate}->{$dest}->{$gen}; | |||||
} | } | ||||
foreach (keys %depends) { | foreach (keys %depends) { | ||||
my $dest = $_; | my $dest = $_; | ||||
my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir); | my $ddest = $dest; | ||||
if ($dest =~ /^\|(.*)\|$/) { | |||||
# Collect the raw target | |||||
$unified_info{targets}->{$1} = 1; | |||||
$ddest = $1; | |||||
} elsif ($dest eq '') { | |||||
$ddest = ''; | |||||
} else { | |||||
$ddest = cleanfile($sourced, $_, $blddir); | |||||
# If the destination doesn't exist in source, it can only be | # If the destination doesn't exist in source, it can only be | ||||
# a generated file in the build tree. | # a generated file in the build tree. | ||||
if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) { | if ($ddest eq $src_configdata || ! -f $ddest) { | ||||
$ddest = cleanfile($buildd, $_, $blddir); | $ddest = cleanfile($buildd, $_, $blddir); | ||||
if ($unified_info{rename}->{$ddest}) { | |||||
$ddest = $unified_info{rename}->{$ddest}; | |||||
} | } | ||||
} | } | ||||
foreach (@{$depends{$dest}}) { | foreach (@{$depends{$dest}}) { | ||||
my $d = cleanfile($sourced, $_, $blddir); | my $d = cleanfile($sourced, $_, $blddir); | ||||
my $d2 = cleanfile($buildd, $_, $blddir); | |||||
# If we know it's generated, or assume it is because we can't | # If we know it's generated, or assume it is because we can't | ||||
# find it in the source tree, we set file we depend on to be | # find it in the source tree, we set file we depend on to be | ||||
# in the build tree rather than the source tree, and assume | # in the build tree rather than the source tree. | ||||
# and that there are lines to build it in a BEGINRAW..ENDRAW | |||||
# section or in the Makefile template. | |||||
if ($d eq $src_configdata | if ($d eq $src_configdata | ||||
|| ! -f $d | || (grep { $d2 eq $_ } | ||||
|| (grep { $d eq $_ } | keys %{$unified_info{generate}}) | ||||
map { cleanfile($srcdir, $_, $blddir) } | || ! -f $d) { | ||||
grep { /\.h$/ } keys %{$unified_info{generate}})) { | $d = $d2; | ||||
$d = cleanfile($buildd, $_, $blddir); | |||||
} | } | ||||
# Take note if the file to depend on is being renamed | |||||
# Take extra care with files ending with .a, they should | |||||
# be treated without that extension, and the extension | |||||
# should be added back after treatment. | |||||
$d =~ /(\.a)?$/; | |||||
my $e = $1 // ""; | |||||
$d = $`; | |||||
if ($unified_info{rename}->{$d}) { | |||||
$d = $unified_info{rename}->{$d}; | |||||
} | |||||
$d .= $e; | |||||
$unified_info{depends}->{$ddest}->{$d} = 1; | $unified_info{depends}->{$ddest}->{$d} = 1; | ||||
# Fix up associated attributes | |||||
$unified_info{attributes}->{depends}->{$ddest}->{$d} = | |||||
$attributes{depends}->{$dest}->{$_} | |||||
if defined $attributes{depends}->{$dest}->{$_}; | |||||
} | } | ||||
} | } | ||||
foreach (keys %includes) { | foreach (keys %includes) { | ||||
my $dest = $_; | my $dest = $_; | ||||
my $ddest = cleanfile($sourced, $_, $blddir); | my $ddest = cleanfile($sourced, $_, $blddir); | ||||
# If the destination doesn't exist in source, it can only be | # If the destination doesn't exist in source, it can only be | ||||
# a generated file in the build tree. | # a generated file in the build tree. | ||||
if ($ddest eq $src_configdata || ! -f $ddest) { | if ($ddest eq $src_configdata || ! -f $ddest) { | ||||
$ddest = cleanfile($buildd, $_, $blddir); | $ddest = cleanfile($buildd, $_, $blddir); | ||||
if ($unified_info{rename}->{$ddest}) { | |||||
$ddest = $unified_info{rename}->{$ddest}; | |||||
} | } | ||||
} | |||||
foreach (@{$includes{$dest}}) { | foreach (@{$includes{$dest}}) { | ||||
my $is = cleandir($sourced, $_, $blddir); | my $is = cleandir($sourced, $_, $blddir); | ||||
my $ib = cleandir($buildd, $_, $blddir); | my $ib = cleandir($buildd, $_, $blddir); | ||||
push @{$unified_info{includes}->{$ddest}->{source}}, $is | push @{$unified_info{includes}->{$ddest}->{source}}, $is | ||||
unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}}; | unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}}; | ||||
push @{$unified_info{includes}->{$ddest}->{build}}, $ib | push @{$unified_info{includes}->{$ddest}->{build}}, $ib | ||||
unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}}; | unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}}; | ||||
} | } | ||||
} | } | ||||
foreach my $dest (keys %defines) { | |||||
my $ddest; | |||||
if ($dest ne "") { | |||||
$ddest = cleanfile($sourced, $dest, $blddir); | |||||
# If the destination doesn't exist in source, it can only | |||||
# be a generated file in the build tree. | |||||
if (! -f $ddest) { | |||||
$ddest = cleanfile($buildd, $dest, $blddir); | |||||
} | } | ||||
} | |||||
foreach my $v (@{$defines{$dest}}) { | |||||
$v =~ m|^([^=]*)(=.*)?$|; | |||||
die "0 length macro name not permitted\n" if $1 eq ""; | |||||
if ($dest ne "") { | |||||
die "$1 defined more than once\n" | |||||
if defined $unified_info{defines}->{$ddest}->{$1}; | |||||
$unified_info{defines}->{$ddest}->{$1} = $2; | |||||
} else { | |||||
die "$1 defined more than once\n" | |||||
if grep { $v eq $_ } @{$config{defines}}; | |||||
push @{$config{defines}}, $v; | |||||
} | |||||
} | |||||
} | |||||
foreach my $section (keys %imagedocs) { | |||||
foreach (@{$imagedocs{$section}}) { | |||||
my $imagedocs = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{imagedocs}->{$section}->{$imagedocs} = 1; | |||||
} | |||||
} | |||||
foreach my $section (keys %htmldocs) { | |||||
foreach (@{$htmldocs{$section}}) { | |||||
my $htmldocs = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{htmldocs}->{$section}->{$htmldocs} = 1; | |||||
} | |||||
} | |||||
foreach my $section (keys %mandocs) { | |||||
foreach (@{$mandocs{$section}}) { | |||||
my $mandocs = cleanfile($buildd, $_, $blddir); | |||||
$unified_info{mandocs}->{$section}->{$mandocs} = 1; | |||||
} | |||||
} | |||||
} | |||||
my $ordinals_text = join(', ', sort keys %ordinals); | my $ordinals_text = join(', ', sort keys %ordinals); | ||||
warn <<"EOF" if $ordinals_text; | warn <<"EOF" if $ordinals_text; | ||||
WARNING: ORDINALS were specified for $ordinals_text | WARNING: ORDINALS were specified for $ordinals_text | ||||
They are ignored and should be replaced with a combination of GENERATE, | They are ignored and should be replaced with a combination of GENERATE, | ||||
DEPEND and SHARED_SOURCE. | DEPEND and SHARED_SOURCE. | ||||
EOF | EOF | ||||
# Massage the result | # Check that each generated file is only generated once | ||||
my $ambiguous_generation = 0; | |||||
foreach (sort keys %check_generate) { | |||||
my @generators = sort keys %{$check_generate{$_}}; | |||||
my $generators_txt = join(', ', @generators); | |||||
if (scalar @generators > 1) { | |||||
warn "$_ is GENERATEd by more than one generator ($generators_txt)\n"; | |||||
$ambiguous_generation++; | |||||
} | |||||
if ($check_generate{$_}->{$generators[0]} > 1) { | |||||
warn "INFO: $_ has more than one GENERATE declaration (same generator)\n" | |||||
} | |||||
} | |||||
die "There are ambiguous source file generations\n" | |||||
if $ambiguous_generation > 0; | |||||
# If the user configured no-shared, we allow no shared sources | # All given source files should exist, or if generated, their | ||||
if ($disabled{shared}) { | # generator should exist. This loop ensures this is true. | ||||
foreach (keys %{$unified_info{shared_sources}}) { | my $missing = 0; | ||||
foreach (keys %{$unified_info{shared_sources}->{$_}}) { | foreach my $orig (sort keys %check_exist) { | ||||
delete $unified_info{sources}->{$_}; | foreach my $dest (@{$check_exist{$orig}}) { | ||||
if ($orig ne $src_configdata) { | |||||
if ($orig =~ /\.a$/) { | |||||
# Static library names may be used as sources, so we | |||||
# need to detect those and give them special treatment. | |||||
unless (grep { $_ eq $orig } | |||||
keys %{$unified_info{libraries}}) { | |||||
warn "$orig is given as source for $dest, but no such library is built\n"; | |||||
$missing++; | |||||
} | } | ||||
} else { | |||||
# A source may be generated, and its generator may be | |||||
# generated as well. We therefore loop to dig out the | |||||
# first generator. | |||||
my $gen = $orig; | |||||
while (my @next = keys %{$check_generate{$gen}}) { | |||||
$gen = $next[0]; | |||||
} | } | ||||
$unified_info{shared_sources} = {}; | |||||
if (! -f $gen) { | |||||
if ($gen ne $orig) { | |||||
$missing++; | |||||
warn "$orig is given as source for $dest, but its generator (leading to $gen) is missing\n"; | |||||
} else { | |||||
$missing++; | |||||
warn "$orig is given as source for $dest, but is missing\n"; | |||||
} | } | ||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
die "There are files missing\n" if $missing > 0; | |||||
# Go through the sources of all libraries and check that the same basename | |||||
# doesn't appear more than once. Some static library archivers depend on | |||||
# them being unique. | |||||
{ | |||||
my $err = 0; | |||||
foreach my $prod (keys %{$unified_info{libraries}}) { | |||||
my @prod_sources = | |||||
map { keys %{$unified_info{sources}->{$_}} } | |||||
keys %{$unified_info{sources}->{$prod}}; | |||||
my %srccnt = (); | |||||
# Count how many times a given each source basename | |||||
# appears for each product. | |||||
foreach my $src (@prod_sources) { | |||||
$srccnt{basename $src}++; | |||||
} | |||||
foreach my $src (keys %srccnt) { | |||||
if ((my $cnt = $srccnt{$src}) > 1) { | |||||
print STDERR "$src appears $cnt times for the product $prod\n"; | |||||
$err++ | |||||
} | |||||
} | |||||
} | |||||
die if $err > 0; | |||||
} | |||||
# Massage the result | |||||
# If we depend on a header file or a perl module, add an inclusion of | # If we depend on a header file or a perl module, add an inclusion of | ||||
# its directory to allow smoothe inclusion | # its directory to allow smoothe inclusion | ||||
foreach my $dest (keys %{$unified_info{depends}}) { | foreach my $dest (keys %{$unified_info{depends}}) { | ||||
next if $dest eq ""; | next if $dest eq ""; | ||||
foreach my $d (keys %{$unified_info{depends}->{$dest}}) { | foreach my $d (keys %{$unified_info{depends}->{$dest}}) { | ||||
next unless $d =~ /\.(h|pm)$/; | next unless $d =~ /\.(h|pm)$/; | ||||
my $i = dirname($d); | my $i = dirname($d); | ||||
my $spot = | my $spot = | ||||
$d eq "configdata.pm" || defined($unified_info{generate}->{$d}) | $d eq "configdata.pm" || defined($unified_info{generate}->{$d}) | ||||
? 'build' : 'source'; | ? 'build' : 'source'; | ||||
push @{$unified_info{includes}->{$dest}->{$spot}}, $i | push @{$unified_info{includes}->{$dest}->{$spot}}, $i | ||||
unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}}; | unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}}; | ||||
} | } | ||||
} | } | ||||
# Trickle down includes placed on libraries, engines and programs to | # Go through all intermediary files and change their names to something that | ||||
# their sources (i.e. object files) | # reflects what they will be built for. Note that for some source files, | ||||
foreach my $dest (keys %{$unified_info{engines}}, | # this leads to duplicate object files because they are used multiple times. | ||||
keys %{$unified_info{libraries}}, | # the goal is to rename all object files according to this scheme: | ||||
keys %{$unified_info{programs}}) { | # {productname}-{midfix}-{origobjname}.[o|res] | ||||
foreach my $k (("source", "build")) { | # the {midfix} is a keyword indicating the type of product, which is mostly | ||||
next unless defined($unified_info{includes}->{$dest}->{$k}); | # valuable for libraries since they come in two forms. | ||||
my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}}; | # | ||||
foreach my $obj (grep /\.o$/, | # This also reorganises the {sources} and {shared_sources} so that the | ||||
(keys %{$unified_info{sources}->{$dest} // {}}, | # former only contains ALL object files that are supposed to end up in | ||||
keys %{$unified_info{shared_sources}->{$dest} // {}})) { | # static libraries and programs, while the latter contains ALL object files | ||||
foreach my $inc (@incs) { | # that are supposed to end up in shared libraries and DSOs. | ||||
unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc | # The main reason for having two different source structures is to allow | ||||
unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}}; | # the same name to be used for the static and the shared variants of a | ||||
# library. | |||||
{ | |||||
# Take copies so we don't get interference from added stuff | |||||
my %unified_copy = (); | |||||
foreach (('sources', 'shared_sources')) { | |||||
$unified_copy{$_} = { %{$unified_info{$_}} } | |||||
if defined($unified_info{$_}); | |||||
delete $unified_info{$_}; | |||||
} | } | ||||
foreach my $prodtype (('programs', 'libraries', 'modules', 'scripts')) { | |||||
# $intent serves multi purposes: | |||||
# - give a prefix for the new object files names | |||||
# - in the case of libraries, rearrange the object files so static | |||||
# libraries use the 'sources' structure exclusively, while shared | |||||
# libraries use the 'shared_sources' structure exclusively. | |||||
my $intent = { | |||||
programs => { bin => { src => [ 'sources' ], | |||||
dst => 'sources' } }, | |||||
libraries => { lib => { src => [ 'sources' ], | |||||
dst => 'sources' }, | |||||
shlib => { prodselect => | |||||
sub { grep !/\.a$/, @_ }, | |||||
src => [ 'sources', | |||||
'shared_sources' ], | |||||
dst => 'shared_sources' } }, | |||||
modules => { dso => { src => [ 'sources' ], | |||||
dst => 'sources' } }, | |||||
scripts => { script => { src => [ 'sources' ], | |||||
dst => 'sources' } } | |||||
} -> {$prodtype}; | |||||
foreach my $kind (keys %$intent) { | |||||
next if ($intent->{$kind}->{dst} eq 'shared_sources' | |||||
&& $disabled{shared}); | |||||
my @src = @{$intent->{$kind}->{src}}; | |||||
my $dst = $intent->{$kind}->{dst}; | |||||
my $prodselect = $intent->{$kind}->{prodselect} // sub { @_ }; | |||||
foreach my $prod ($prodselect->(keys %{$unified_info{$prodtype}})) { | |||||
# %prod_sources has all applicable objects as keys, and | |||||
# their corresponding sources as values | |||||
my %prod_sources = | |||||
map { $_ => [ keys %{$unified_copy{sources}->{$_}} ] } | |||||
map { keys %{$unified_copy{$_}->{$prod}} } | |||||
@src; | |||||
foreach (keys %prod_sources) { | |||||
# Only affect object files and resource files, | |||||
# the others simply get a new value | |||||
# (+1 instead of -1) | |||||
if ($_ =~ /\.(o|res)$/) { | |||||
(my $prodname = $prod) =~ s|\.a$||; | |||||
my $newobj = | |||||
catfile(dirname($_), | |||||
basename($prodname) | |||||
. '-' . $kind | |||||
. '-' . basename($_)); | |||||
$unified_info{$dst}->{$prod}->{$newobj} = 1; | |||||
foreach my $src (@{$prod_sources{$_}}) { | |||||
$unified_info{sources}->{$newobj}->{$src} = 1; | |||||
# Adjust source attributes | |||||
my $attrs = $unified_info{attributes}->{sources}; | |||||
if (defined $attrs->{$prod} | |||||
&& defined $attrs->{$prod}->{$_}) { | |||||
$attrs->{$prod}->{$newobj} = | |||||
$attrs->{$prod}->{$_}; | |||||
delete $attrs->{$prod}->{$_}; | |||||
} | } | ||||
foreach my $objsrc (keys %{$attrs->{$_} // {}}) { | |||||
$attrs->{$newobj}->{$objsrc} = | |||||
$attrs->{$_}->{$objsrc}; | |||||
delete $attrs->{$_}->{$objsrc}; | |||||
} | } | ||||
delete $unified_info{includes}->{$dest}; | |||||
} | } | ||||
# Adjust dependencies | |||||
foreach my $deps (keys %{$unified_info{depends}->{$_}}) { | |||||
$unified_info{depends}->{$_}->{$deps} = -1; | |||||
$unified_info{depends}->{$newobj}->{$deps} = 1; | |||||
} | |||||
# Adjust includes | |||||
foreach my $k (('source', 'build')) { | |||||
next unless | |||||
defined($unified_info{includes}->{$_}->{$k}); | |||||
my @incs = @{$unified_info{includes}->{$_}->{$k}}; | |||||
$unified_info{includes}->{$newobj}->{$k} = [ @incs ]; | |||||
} | |||||
} else { | |||||
$unified_info{$dst}->{$prod}->{$_} = 1; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
# At this point, we have a number of sources with the value -1. They | |||||
# aren't part of the local build and are probably meant for a different | |||||
# platform, and can therefore be cleaned away. That happens when making | |||||
# %unified_info more efficient below. | |||||
### Make unified_info a bit more efficient | ### Make unified_info a bit more efficient | ||||
# One level structures | # One level structures | ||||
foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) { | foreach (("programs", "libraries", "modules", "scripts", "targets")) { | ||||
$unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; | $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; | ||||
} | } | ||||
# Two level structures | # Two level structures | ||||
foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) { | foreach my $l1 (("sources", "shared_sources", "ldadd", "depends", | ||||
"imagedocs", "htmldocs", "mandocs")) { | |||||
foreach my $l2 (sort keys %{$unified_info{$l1}}) { | foreach my $l2 (sort keys %{$unified_info{$l1}}) { | ||||
$unified_info{$l1}->{$l2} = | my @items = | ||||
[ sort keys %{$unified_info{$l1}->{$l2}} ]; | sort | ||||
grep { $unified_info{$l1}->{$l2}->{$_} > 0 } | |||||
keys %{$unified_info{$l1}->{$l2}}; | |||||
if (@items) { | |||||
$unified_info{$l1}->{$l2} = [ @items ]; | |||||
} else { | |||||
delete $unified_info{$l1}->{$l2}; | |||||
} | } | ||||
} | } | ||||
} | |||||
# Defines | |||||
foreach my $dest (sort keys %{$unified_info{defines}}) { | |||||
$unified_info{defines}->{$dest} | |||||
= [ map { $_.$unified_info{defines}->{$dest}->{$_} } | |||||
sort keys %{$unified_info{defines}->{$dest}} ]; | |||||
} | |||||
# Includes | # Includes | ||||
foreach my $dest (sort keys %{$unified_info{includes}}) { | foreach my $dest (sort keys %{$unified_info{includes}}) { | ||||
if (defined($unified_info{includes}->{$dest}->{build})) { | if (defined($unified_info{includes}->{$dest}->{build})) { | ||||
my @source_includes = (); | my @source_includes = (); | ||||
@source_includes = ( @{$unified_info{includes}->{$dest}->{source}} ) | @source_includes = ( @{$unified_info{includes}->{$dest}->{source}} ) | ||||
if defined($unified_info{includes}->{$dest}->{source}); | if defined($unified_info{includes}->{$dest}->{source}); | ||||
$unified_info{includes}->{$dest} = | $unified_info{includes}->{$dest} = | ||||
[ @{$unified_info{includes}->{$dest}->{build}} ]; | [ @{$unified_info{includes}->{$dest}->{build}} ]; | ||||
foreach my $inc (@source_includes) { | foreach my $inc (@source_includes) { | ||||
push @{$unified_info{includes}->{$dest}}, $inc | push @{$unified_info{includes}->{$dest}}, $inc | ||||
unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}}; | unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}}; | ||||
} | } | ||||
} else { | } elsif (defined($unified_info{includes}->{$dest}->{source})) { | ||||
$unified_info{includes}->{$dest} = | $unified_info{includes}->{$dest} = | ||||
[ @{$unified_info{includes}->{$dest}->{source}} ]; | [ @{$unified_info{includes}->{$dest}->{source}} ]; | ||||
} else { | |||||
delete $unified_info{includes}->{$dest}; | |||||
} | } | ||||
} | } | ||||
# For convenience collect information regarding directories where | # For convenience collect information regarding directories where | ||||
# files are generated, those generated files and the end product | # files are generated, those generated files and the end product | ||||
# they end up in where applicable. Then, add build rules for those | # they end up in where applicable. Then, add build rules for those | ||||
# directories | # directories | ||||
my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], | my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ], | ||||
"dso" => [ @{$unified_info{engines}} ], | "dso" => [ @{$unified_info{modules}} ], | ||||
"bin" => [ @{$unified_info{programs}} ], | "bin" => [ @{$unified_info{programs}} ], | ||||
"script" => [ @{$unified_info{scripts}} ] ); | "script" => [ @{$unified_info{scripts}} ], | ||||
foreach my $type (keys %loopinfo) { | "docs" => [ (map { @{$unified_info{imagedocs}->{$_} // []} } | ||||
keys %{$unified_info{imagedocs} // {}}), | |||||
(map { @{$unified_info{htmldocs}->{$_} // []} } | |||||
keys %{$unified_info{htmldocs} // {}}), | |||||
(map { @{$unified_info{mandocs}->{$_} // []} } | |||||
keys %{$unified_info{mandocs} // {}}) ] ); | |||||
foreach my $type (sort keys %loopinfo) { | |||||
foreach my $product (@{$loopinfo{$type}}) { | foreach my $product (@{$loopinfo{$type}}) { | ||||
my %dirs = (); | my %dirs = (); | ||||
my $pd = dirname($product); | my $pd = dirname($product); | ||||
foreach (@{$unified_info{sources}->{$product} // []}, | foreach (@{$unified_info{sources}->{$product} // []}, | ||||
@{$unified_info{shared_sources}->{$product} // []}) { | @{$unified_info{shared_sources}->{$product} // []}) { | ||||
my $d = dirname($_); | my $d = dirname($_); | ||||
# We don't want to create targets for source directories | # We don't want to create targets for source directories | ||||
# when building out of source | # when building out of source | ||||
next if ($config{sourcedir} ne $config{builddir} | next if ($config{sourcedir} ne $config{builddir} | ||||
&& $d =~ m|^\Q$config{sourcedir}\E|); | && $d =~ m|^\Q$config{sourcedir}\E|); | ||||
# We already have a "test" target, and the current directory | # We already have a "test" target, and the current directory | ||||
# is just silly to make a target for | # is just silly to make a target for | ||||
next if $d eq "test" || $d eq "."; | next if $d eq "test" || $d eq "."; | ||||
$dirs{$d} = 1; | $dirs{$d} = 1; | ||||
push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ | push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ | ||||
if $d ne $pd; | if $d ne $pd; | ||||
} | } | ||||
foreach (keys %dirs) { | foreach (sort keys %dirs) { | ||||
push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, | push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, | ||||
$product; | $product; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
# For the schemes that need it, we provide the old *_obj configs | # For the schemes that need it, we provide the old *_obj configs | ||||
# from the *_asm_obj ones | # from the *_asm_obj ones | ||||
foreach (grep /_(asm|aux)_src$/, keys %target) { | foreach (grep /_(asm|aux)_src$/, keys %target) { | ||||
my $src = $_; | my $src = $_; | ||||
(my $obj = $_) =~ s/_(asm|aux)_src$/_obj/; | (my $obj = $_) =~ s/_(asm|aux)_src$/_obj/; | ||||
$target{$obj} = $target{$src}; | $target{$obj} = $target{$src}; | ||||
$target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler | $target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler | ||||
$target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++ | $target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++ | ||||
} | } | ||||
# Write down our configuration where it fits ######################### | # Write down our configuration where it fits ######################### | ||||
print "Creating configdata.pm\n"; | my %template_vars = ( | ||||
open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n"; | config => \%config, | ||||
print OUT <<"EOF"; | target => \%target, | ||||
#! $config{HASHBANGPERL} | disablables => \@disablables, | ||||
disablables_int => \@disablables_int, | |||||
package configdata; | disabled => \%disabled, | ||||
withargs => \%withargs, | |||||
use strict; | unified_info => \%unified_info, | ||||
use warnings; | tls => \@tls, | ||||
dtls => \@dtls, | |||||
use Exporter; | makevars => [ sort keys %user ], | ||||
#use vars qw(\@ISA \@EXPORT); | disabled_info => \%disabled_info, | ||||
our \@ISA = qw(Exporter); | user_crossable => \@user_crossable, | ||||
our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables); | |||||
EOF | |||||
print OUT "our %config = (\n"; | |||||
foreach (sort keys %config) { | |||||
if (ref($config{$_}) eq "ARRAY") { | |||||
print OUT " ", $_, " => [ ", join(", ", | |||||
map { quotify("perl", $_) } | |||||
@{$config{$_}}), " ],\n"; | |||||
} elsif (ref($config{$_}) eq "HASH") { | |||||
print OUT " ", $_, " => {"; | |||||
if (scalar keys %{$config{$_}} > 0) { | |||||
print OUT "\n"; | |||||
foreach my $key (sort keys %{$config{$_}}) { | |||||
print OUT " ", | |||||
join(" => ", | |||||
quotify("perl", $key), | |||||
defined $config{$_}->{$key} | |||||
? quotify("perl", $config{$_}->{$key}) | |||||
: "undef"); | |||||
print OUT ",\n"; | |||||
} | |||||
print OUT " "; | |||||
} | |||||
print OUT "},\n"; | |||||
} else { | |||||
print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n" | |||||
} | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | ); | ||||
my $configdata_outname = 'configdata.pm'; | |||||
open CONFIGDATA, ">$configdata_outname.new" | |||||
or die "Trying to create $configdata_outname.new: $!"; | |||||
my $configdata_tmplname = cleanfile($srcdir, "configdata.pm.in", $blddir); | |||||
my $configdata_tmpl = | |||||
OpenSSL::Template->new(TYPE => 'FILE', SOURCE => $configdata_tmplname); | |||||
$configdata_tmpl->fill_in( | |||||
FILENAME => $configdata_tmplname, | |||||
OUTPUT => \*CONFIGDATA, | |||||
HASH => { %template_vars, | |||||
autowarntext => [ | |||||
'WARNING: do not edit!', | |||||
"Generated by Configure from $configdata_tmplname", | |||||
] } | |||||
) or die $Text::Template::ERROR; | |||||
close CONFIGDATA; | |||||
EOF | rename "$configdata_outname.new", $configdata_outname; | ||||
print OUT "our %target = (\n"; | |||||
foreach (sort keys %target) { | |||||
if (ref($target{$_}) eq "ARRAY") { | |||||
print OUT " ", $_, " => [ ", join(", ", | |||||
map { quotify("perl", $_) } | |||||
@{$target{$_}}), " ],\n"; | |||||
} else { | |||||
print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n" | |||||
} | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
print OUT "our \%available_protocols = (\n"; | |||||
print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n"; | |||||
print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n"; | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
print OUT "our \@disablables = (\n"; | |||||
foreach (@disablables) { | |||||
print OUT " ", quotify("perl", $_), ",\n"; | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
print OUT "our \%disabled = (\n"; | |||||
foreach (sort keys %disabled) { | |||||
print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n"; | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
print OUT "our %withargs = (\n"; | |||||
foreach (sort keys %withargs) { | |||||
if (ref($withargs{$_}) eq "ARRAY") { | |||||
print OUT " ", $_, " => [ ", join(", ", | |||||
map { quotify("perl", $_) } | |||||
@{$withargs{$_}}), " ],\n"; | |||||
} else { | |||||
print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n" | |||||
} | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
if ($builder eq "unified") { | |||||
my $recurse; | |||||
$recurse = sub { | |||||
my $indent = shift; | |||||
foreach (@_) { | |||||
if (ref $_ eq "ARRAY") { | |||||
print OUT " "x$indent, "[\n"; | |||||
foreach (@$_) { | |||||
$recurse->($indent + 4, $_); | |||||
} | |||||
print OUT " "x$indent, "],\n"; | |||||
} elsif (ref $_ eq "HASH") { | |||||
my %h = %$_; | |||||
print OUT " "x$indent, "{\n"; | |||||
foreach (sort keys %h) { | |||||
if (ref $h{$_} eq "") { | |||||
print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n"; | |||||
} else { | |||||
print OUT " "x($indent + 4), quotify("perl", $_), " =>\n"; | |||||
$recurse->($indent + 8, $h{$_}); | |||||
} | |||||
} | |||||
print OUT " "x$indent, "},\n"; | |||||
} else { | |||||
print OUT " "x$indent, quotify("perl", $_), ",\n"; | |||||
} | |||||
} | |||||
}; | |||||
print OUT "our %unified_info = (\n"; | |||||
foreach (sort keys %unified_info) { | |||||
if (ref $unified_info{$_} eq "") { | |||||
print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n"; | |||||
} else { | |||||
print OUT " "x4, quotify("perl", $_), " =>\n"; | |||||
$recurse->(8, $unified_info{$_}); | |||||
} | |||||
} | |||||
print OUT <<"EOF"; | |||||
); | |||||
EOF | |||||
} | |||||
print OUT | |||||
"# The following data is only used when this files is use as a script\n"; | |||||
print OUT "my \@makevars = (\n"; | |||||
foreach (sort keys %user) { | |||||
print OUT " '",$_,"',\n"; | |||||
} | |||||
print OUT ");\n"; | |||||
print OUT "my \%disabled_info = (\n"; | |||||
foreach my $what (sort keys %disabled_info) { | |||||
print OUT " '$what' => {\n"; | |||||
foreach my $info (sort keys %{$disabled_info{$what}}) { | |||||
if (ref $disabled_info{$what}->{$info} eq 'ARRAY') { | |||||
print OUT " $info => [ ", | |||||
join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}), | |||||
" ],\n"; | |||||
} else { | |||||
print OUT " $info => '", $disabled_info{$what}->{$info}, | |||||
"',\n"; | |||||
} | |||||
} | |||||
print OUT " },\n"; | |||||
} | |||||
print OUT ");\n"; | |||||
print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n"; | |||||
print OUT << 'EOF'; | |||||
# If run directly, we can give some answers, and even reconfigure | |||||
unless (caller) { | |||||
use Getopt::Long; | |||||
use File::Spec::Functions; | |||||
use File::Basename; | |||||
use Pod::Usage; | |||||
my $here = dirname($0); | |||||
my $dump = undef; | |||||
my $cmdline = undef; | |||||
my $options = undef; | |||||
my $target = undef; | |||||
my $envvars = undef; | |||||
my $makevars = undef; | |||||
my $buildparams = undef; | |||||
my $reconf = undef; | |||||
my $verbose = undef; | |||||
my $help = undef; | |||||
my $man = undef; | |||||
GetOptions('dump|d' => \$dump, | |||||
'command-line|c' => \$cmdline, | |||||
'options|o' => \$options, | |||||
'target|t' => \$target, | |||||
'environment|e' => \$envvars, | |||||
'make-variables|m' => \$makevars, | |||||
'build-parameters|b' => \$buildparams, | |||||
'reconfigure|reconf|r' => \$reconf, | |||||
'verbose|v' => \$verbose, | |||||
'help' => \$help, | |||||
'man' => \$man) | |||||
or die "Errors in command line arguments\n"; | |||||
unless ($dump || $cmdline || $options || $target || $envvars || $makevars | |||||
|| $buildparams || $reconf || $verbose || $help || $man) { | |||||
print STDERR <<"_____"; | |||||
You must give at least one option. | |||||
For more information, do '$0 --help' | |||||
_____ | |||||
exit(2); | |||||
} | |||||
if ($help) { | |||||
pod2usage(-exitval => 0, | |||||
-verbose => 1); | |||||
} | |||||
if ($man) { | |||||
pod2usage(-exitval => 0, | |||||
-verbose => 2); | |||||
} | |||||
if ($dump || $cmdline) { | |||||
print "\nCommand line (with current working directory = $here):\n\n"; | |||||
print ' ',join(' ', | |||||
$config{PERL}, | |||||
catfile($config{sourcedir}, 'Configure'), | |||||
@{$config{perlargv}}), "\n"; | |||||
print "\nPerl information:\n\n"; | |||||
print ' ',$config{perl_cmd},"\n"; | |||||
print ' ',$config{perl_version},' for ',$config{perl_archname},"\n"; | |||||
} | |||||
if ($dump || $options) { | |||||
my $longest = 0; | |||||
my $longest2 = 0; | |||||
foreach my $what (@disablables) { | |||||
$longest = length($what) if $longest < length($what); | |||||
$longest2 = length($disabled{$what}) | |||||
if $disabled{$what} && $longest2 < length($disabled{$what}); | |||||
} | |||||
print "\nEnabled features:\n\n"; | |||||
foreach my $what (@disablables) { | |||||
print " $what\n" | |||||
unless grep { $_ =~ /^${what}$/ } keys %disabled; | |||||
} | |||||
print "\nDisabled features:\n\n"; | |||||
foreach my $what (@disablables) { | |||||
my @what2 = grep { $_ =~ /^${what}$/ } keys %disabled; | |||||
my $what3 = $what2[0]; | |||||
if ($what3) { | |||||
print " $what3", ' ' x ($longest - length($what3) + 1), | |||||
"[$disabled{$what3}]", ' ' x ($longest2 - length($disabled{$what3}) + 1); | |||||
print $disabled_info{$what3}->{macro} | |||||
if $disabled_info{$what3}->{macro}; | |||||
print ' (skip ', | |||||
join(', ', @{$disabled_info{$what3}->{skipped}}), | |||||
')' | |||||
if $disabled_info{$what3}->{skipped}; | |||||
print "\n"; | |||||
} | |||||
} | |||||
} | |||||
if ($dump || $target) { | |||||
print "\nConfig target attributes:\n\n"; | |||||
foreach (sort keys %target) { | |||||
next if $_ =~ m|^_| || $_ eq 'template'; | |||||
my $quotify = sub { | |||||
map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_; | |||||
}; | |||||
print ' ', $_, ' => '; | |||||
if (ref($target{$_}) eq "ARRAY") { | |||||
print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n"; | |||||
} else { | |||||
print $quotify->($target{$_}), ",\n" | |||||
} | |||||
} | |||||
} | |||||
if ($dump || $envvars) { | |||||
print "\nRecorded environment:\n\n"; | |||||
foreach (sort keys %{$config{perlenv}}) { | |||||
print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n"; | |||||
} | |||||
} | |||||
if ($dump || $makevars) { | |||||
print "\nMakevars:\n\n"; | |||||
foreach my $var (@makevars) { | |||||
my $prefix = ''; | |||||
$prefix = $config{CROSS_COMPILE} | |||||
if grep { $var eq $_ } @user_crossable; | |||||
$prefix //= ''; | |||||
print ' ',$var,' ' x (16 - length $var),'= ', | |||||
(ref $config{$var} eq 'ARRAY' | |||||
? join(' ', @{$config{$var}}) | |||||
: $prefix.$config{$var}), | |||||
"\n" | |||||
if defined $config{$var}; | |||||
} | |||||
my @buildfile = ($config{builddir}, $config{build_file}); | |||||
unshift @buildfile, $here | |||||
unless file_name_is_absolute($config{builddir}); | |||||
my $buildfile = canonpath(catdir(@buildfile)); | |||||
print <<"_____"; | |||||
NOTE: These variables only represent the configuration view. The build file | |||||
template may have processed these variables further, please have a look at the | |||||
build file for more exact data: | |||||
$buildfile | |||||
_____ | |||||
} | |||||
if ($dump || $buildparams) { | |||||
my @buildfile = ($config{builddir}, $config{build_file}); | |||||
unshift @buildfile, $here | |||||
unless file_name_is_absolute($config{builddir}); | |||||
print "\nbuild file:\n\n"; | |||||
print " ", canonpath(catfile(@buildfile)),"\n"; | |||||
print "\nbuild file templates:\n\n"; | |||||
foreach (@{$config{build_file_templates}}) { | |||||
my @tmpl = ($_); | |||||
unshift @tmpl, $here | |||||
unless file_name_is_absolute($config{sourcedir}); | |||||
print ' ',canonpath(catfile(@tmpl)),"\n"; | |||||
} | |||||
} | |||||
if ($reconf) { | |||||
if ($verbose) { | |||||
print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n"; | |||||
foreach (sort keys %{$config{perlenv}}) { | |||||
print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n"; | |||||
} | |||||
} | |||||
chdir $here; | |||||
exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf'; | |||||
} | |||||
} | |||||
1; | |||||
__END__ | |||||
=head1 NAME | |||||
configdata.pm - configuration data for OpenSSL builds | |||||
=head1 SYNOPSIS | |||||
Interactive: | |||||
perl configdata.pm [options] | |||||
As data bank module: | |||||
use configdata; | |||||
=head1 DESCRIPTION | |||||
This module can be used in two modes, interactively and as a module containing | |||||
all the data recorded by OpenSSL's Configure script. | |||||
When used interactively, simply run it as any perl script, with at least one | |||||
option, and you will get the information you ask for. See L</OPTIONS> below. | |||||
When loaded as a module, you get a few databanks with useful information to | |||||
perform build related tasks. The databanks are: | |||||
%config Configured things. | |||||
%target The OpenSSL config target with all inheritances | |||||
resolved. | |||||
%disabled The features that are disabled. | |||||
@disablables The list of features that can be disabled. | |||||
%withargs All data given through --with-THING options. | |||||
%unified_info All information that was computed from the build.info | |||||
files. | |||||
=head1 OPTIONS | |||||
=over 4 | |||||
=item B<--help> | |||||
Print a brief help message and exit. | |||||
=item B<--man> | |||||
Print the manual page and exit. | |||||
=item B<--dump> | B<-d> | |||||
Print all relevant configuration data. This is equivalent to B<--command-line> | |||||
B<--options> B<--target> B<--environment> B<--make-variables> | |||||
B<--build-parameters>. | |||||
=item B<--command-line> | B<-c> | |||||
Print the current configuration command line. | |||||
=item B<--options> | B<-o> | |||||
Print the features, both enabled and disabled, and display defined macro and | |||||
skipped directories where applicable. | |||||
=item B<--target> | B<-t> | |||||
Print the config attributes for this config target. | |||||
=item B<--environment> | B<-e> | |||||
Print the environment variables and their values at the time of configuration. | |||||
=item B<--make-variables> | B<-m> | |||||
Print the main make variables generated in the current configuration | |||||
=item B<--build-parameters> | B<-b> | |||||
Print the build parameters, i.e. build file and build file templates. | |||||
=item B<--reconfigure> | B<--reconf> | B<-r> | |||||
Redo the configuration. | |||||
=item B<--verbose> | B<-v> | |||||
Verbose output. | |||||
=back | |||||
=cut | |||||
EOF | |||||
close(OUT); | |||||
if ($builder_platform eq 'unix') { | if ($builder_platform eq 'unix') { | ||||
my $mode = (0755 & ~umask); | my $mode = (0755 & ~umask); | ||||
chmod $mode, 'configdata.pm' | chmod $mode, 'configdata.pm' | ||||
or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!); | or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!); | ||||
} | } | ||||
print "Created $configdata_outname\n"; | |||||
my %builders = ( | print "Running $configdata_outname\n"; | ||||
unified => sub { | my $perlcmd = (quotify("maybeshell", $config{PERL}))[0]; | ||||
print 'Creating ',$config{build_file},"\n"; | my $cmd = "$perlcmd $configdata_outname"; | ||||
run_dofile(catfile($blddir, $config{build_file}), | #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; | ||||
@{$config{build_file_templates}}); | system($cmd); | ||||
}, | exit 1 if $? != 0; | ||||
); | |||||
$builders{$builder}->($builder_platform, @builder_opts); | |||||
$SIG{__DIE__} = $orig_death_handler; | $SIG{__DIE__} = $orig_death_handler; | ||||
print <<"EOF" if ($disabled{threads} eq "unavailable"); | print <<"EOF" if ($disabled{threads} eq "unavailable"); | ||||
The library could not be configured for supporting multi-threaded | The library could not be configured for supporting multi-threaded | ||||
applications as the compiler options required on this system are not known. | applications as the compiler options required on this system are not known. | ||||
See file INSTALL for details if you need multi-threading. | See file INSTALL.md for details if you need multi-threading. | ||||
EOF | EOF | ||||
print <<"EOF" if ($no_shared_warn); | print <<"EOF" if ($no_shared_warn); | ||||
The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this | The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this | ||||
platform, so we will pretend you gave the option 'no-pic', which also disables | platform, so we will pretend you gave the option 'no-pic', which also disables | ||||
'shared' and 'dynamic-engine'. If you know how to implement shared libraries | 'shared' and 'dynamic-engine'. If you know how to implement shared libraries | ||||
or position independent code, please let us know (but please first make sure | or position independent code, please let us know (but please first make sure | ||||
you have tried with a current version of OpenSSL). | you have tried with a current version of OpenSSL). | ||||
EOF | EOF | ||||
print <<"EOF"; | print $banner; | ||||
********************************************************************** | |||||
*** *** | |||||
*** OpenSSL has been successfully configured *** | |||||
*** *** | |||||
*** If you encounter a problem while building, please open an *** | |||||
*** issue on GitHub <https://github.com/openssl/openssl/issues> *** | |||||
*** and include the output from the following command: *** | |||||
*** *** | |||||
*** perl configdata.pm --dump *** | |||||
*** *** | |||||
*** (If you are new to OpenSSL, you might want to consult the *** | |||||
*** 'Troubleshooting' section in the INSTALL file first) *** | |||||
*** *** | |||||
********************************************************************** | |||||
EOF | |||||
exit(0); | exit(0); | ||||
###################################################################### | ###################################################################### | ||||
# | # | ||||
# Helpers and utility functions | # Helpers and utility functions | ||||
# | # | ||||
# Death handler, to print a helpful message in case of failure ####### | # Death handler, to print a helpful message in case of failure ####### | ||||
# | # | ||||
sub death_handler { | sub death_handler { | ||||
die @_ if $^S; # To prevent the added message in eval blocks | die @_ if $^S; # To prevent the added message in eval blocks | ||||
my $build_file = $config{build_file} // "build file"; | my $build_file = $config{build_file} // "build file"; | ||||
my @message = ( <<"_____", @_ ); | my @message = ( <<"_____", @_ ); | ||||
Failure! $build_file wasn't produced. | Failure! $build_file wasn't produced. | ||||
Please read INSTALL and associated NOTES files. You may also have to look over | Please read INSTALL.md and associated NOTES-* files. You may also have to | ||||
your available compiler tool chain or change your configuration. | look over your available compiler tool chain or change your configuration. | ||||
_____ | _____ | ||||
# Dying is terminal, so it's ok to reset the signal handler here. | # Dying is terminal, so it's ok to reset the signal handler here. | ||||
$SIG{__DIE__} = $orig_death_handler; | $SIG{__DIE__} = $orig_death_handler; | ||||
die @message; | die @message; | ||||
} | } | ||||
# Configuration file reading ######################################### | # Configuration file reading ######################################### | ||||
# Note: All of the helper functions are for lazy evaluation. They all | # Note: All of the helper functions are for lazy evaluation. They all | ||||
# return a CODE ref, which will return the intended value when evaluated. | # return a CODE ref, which will return the intended value when evaluated. | ||||
# Thus, whenever there's mention of a returned value, it's about that | # Thus, whenever there's mention of a returned value, it's about that | ||||
# intended value. | # intended value. | ||||
# Helper function to implement conditional inheritance depending on the | |||||
# value of $disabled{asm}. Used in inherit_from values as follows: | |||||
# | |||||
# inherit_from => [ "template", asm("asm_tmpl") ] | |||||
# | |||||
sub asm { | |||||
my @x = @_; | |||||
sub { | |||||
$disabled{asm} ? () : @x; | |||||
} | |||||
} | |||||
# Helper function to implement conditional value variants, with a default | # Helper function to implement conditional value variants, with a default | ||||
# plus additional values based on the value of $config{build_type}. | # plus additional values based on the value of $config{build_type}. | ||||
# Arguments are given in hash table form: | # Arguments are given in hash table form: | ||||
# | # | ||||
# picker(default => "Basic string: ", | # picker(default => "Basic string: ", | ||||
# debug => "debug", | # debug => "debug", | ||||
# release => "release") | # release => "release") | ||||
# | # | ||||
▲ Show 20 Lines • Show All 301 Lines • ▼ Show 20 Lines | sub usage | ||||
$k += length($i) + 1; | $k += length($i) + 1; | ||||
if ($k > 78) | if ($k > 78) | ||||
{ | { | ||||
print STDERR "\n"; | print STDERR "\n"; | ||||
$k=length($i); | $k=length($i); | ||||
} | } | ||||
print STDERR $i . " "; | print STDERR $i . " "; | ||||
} | } | ||||
print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n"; | |||||
exit(1); | exit(1); | ||||
} | } | ||||
sub run_dofile | |||||
{ | |||||
my $out = shift; | |||||
my @templates = @_; | |||||
unlink $out || warn "Can't remove $out, $!" | |||||
if -f $out; | |||||
foreach (@templates) { | |||||
die "Can't open $_, $!" unless -f $_; | |||||
} | |||||
my $perlcmd = (quotify("maybeshell", $config{PERL}))[0]; | |||||
my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; | |||||
#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; | |||||
system($cmd); | |||||
exit 1 if $? != 0; | |||||
rename("$out.new", $out) || die "Can't rename $out.new, $!"; | |||||
} | |||||
sub compiler_predefined { | sub compiler_predefined { | ||||
state %predefined; | state %predefined; | ||||
my $cc = shift; | my $cc = shift; | ||||
return () if $^O eq 'VMS'; | return () if $^O eq 'VMS'; | ||||
die 'compiler_predefined called without a compiler command' | die 'compiler_predefined called without a compiler command' | ||||
unless $cc; | unless $cc; | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | sub print_table_entry | ||||
my @sequence = ( | my @sequence = ( | ||||
"sys_id", | "sys_id", | ||||
"cpp", | "cpp", | ||||
"cppflags", | "cppflags", | ||||
"defines", | "defines", | ||||
"includes", | "includes", | ||||
"cc", | "cc", | ||||
"cflags", | "cflags", | ||||
"unistd", | |||||
"ld", | "ld", | ||||
"lflags", | "lflags", | ||||
"loutflag", | "loutflag", | ||||
"ex_libs", | "ex_libs", | ||||
"bn_ops", | "bn_ops", | ||||
"apps_aux_src", | "enable", | ||||
"cpuid_asm_src", | "disable", | ||||
"uplink_aux_src", | |||||
"bn_asm_src", | |||||
"ec_asm_src", | |||||
"des_asm_src", | |||||
"aes_asm_src", | |||||
"bf_asm_src", | |||||
"md5_asm_src", | |||||
"cast_asm_src", | |||||
"sha1_asm_src", | |||||
"rc4_asm_src", | |||||
"rmd160_asm_src", | |||||
"rc5_asm_src", | |||||
"wp_asm_src", | |||||
"cmll_asm_src", | |||||
"modes_asm_src", | |||||
"padlock_asm_src", | |||||
"chacha_asm_src", | |||||
"poly1035_asm_src", | "poly1035_asm_src", | ||||
"thread_scheme", | "thread_scheme", | ||||
"perlasm_scheme", | "perlasm_scheme", | ||||
"dso_scheme", | "dso_scheme", | ||||
"shared_target", | "shared_target", | ||||
"shared_cflag", | "shared_cflag", | ||||
"shared_defines", | "shared_defines", | ||||
"shared_ldflag", | "shared_ldflag", | ||||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Lines | while(defined($_ = $lineiterator->())) { | ||||
} | } | ||||
if ($collectors{"AFTER"}) { | if ($collectors{"AFTER"}) { | ||||
$collectors{"AFTER"}->($_); | $collectors{"AFTER"}->($_); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
# tokenize($line) | # tokenize($line) | ||||
# tokenize($line,$separator) | |||||
# $line is a line of text to split up into tokens | # $line is a line of text to split up into tokens | ||||
# returns a list of tokens | # $separator [optional] is a regular expression that separates the tokens, | ||||
# the default being spaces. Do not use quotes of any kind as separators, | |||||
# that will give undefined results. | |||||
# Returns a list of tokens. | |||||
# | # | ||||
# Tokens are divided by spaces. If the tokens include spaces, they | # Tokens are divided by separator (spaces by default). If the tokens include | ||||
# have to be quoted with single or double quotes. Double quotes | # the separators, they have to be quoted with single or double quotes. | ||||
# inside a double quoted token must be escaped. Escaping is done | # Double quotes inside a double quoted token must be escaped. Escaping is done | ||||
# with backslash. | # with backslash. | ||||
# Basically, the same quoting rules apply for " and ' as in any | # Basically, the same quoting rules apply for " and ' as in any | ||||
# Unix shell. | # Unix shell. | ||||
sub tokenize { | sub tokenize { | ||||
my $line = my $debug_line = shift; | my $line = my $debug_line = shift; | ||||
my $separator = shift // qr|\s+|; | |||||
my @result = (); | my @result = (); | ||||
while ($line =~ s|^\s+||, $line ne "") { | if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { | ||||
print STDERR "DEBUG[tokenize]: \$separator = $separator\n"; | |||||
} | |||||
while ($line =~ s|^${separator}||, $line ne "") { | |||||
my $token = ""; | my $token = ""; | ||||
while ($line ne "" && $line !~ m|^\s|) { | again: | ||||
$line =~ m/^(.*?)(${separator}|"|'|$)/; | |||||
$token .= $1; | |||||
$line = $2.$'; | |||||
if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { | if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) { | ||||
$token .= $1; | $token .= $1; | ||||
$line = $'; | $line = $'; | ||||
goto again; | |||||
} elsif ($line =~ m/^'([^']*)'/) { | } elsif ($line =~ m/^'([^']*)'/) { | ||||
$token .= $1; | $token .= $1; | ||||
$line = $'; | $line = $'; | ||||
} elsif ($line =~ m/^(\S+)/) { | goto again; | ||||
$token .= $1; | |||||
$line = $'; | |||||
} | |||||
} | } | ||||
push @result, $token; | push @result, $token; | ||||
} | } | ||||
if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { | if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) { | ||||
print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n"; | print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n"; | ||||
print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n"; | print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n"; | ||||
} | } | ||||
return @result; | return @result; | ||||
} | } |