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