VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.2/Configure

最後變更 在這個檔案是 108206,由 vboxsync 提交於 4 週 前

openssl-3.3.2: Exported all files to OSE and removed .scm-settings ​bugref:10757

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette