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