| #! /usr/bin/env perl |
| # -*- mode: perl; -*- |
| |
| ## |
| ## Configure -- OpenSSL source tree configuration script |
| ## If editing this file, run this command before committing |
| ## make -f Makefile.in TABLE |
| ## |
| |
| require 5.000; |
| use strict; |
| use File::Basename; |
| use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/; |
| use File::Path qw/make_path/; |
| use Cwd qw/:DEFAULT realpath/; |
| |
| # see INSTALL for instructions. |
| |
| my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n"; |
| |
| # Options: |
| # |
| # --config add the given configuration file, which will be read after |
| # any "Configurations*" files that are found in the same |
| # directory as this script. |
| # --prefix prefix for the OpenSSL installation, which includes the |
| # directories bin, lib, include, share/man, share/doc/openssl |
| # This becomes the value of INSTALLTOP in Makefile |
| # (Default: /usr/local) |
| # --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys. |
| # If it's a relative directory, it will be added on the directory |
| # given with --prefix. |
| # This becomes the value of OPENSSLDIR in Makefile and in C. |
| # (Default: PREFIX/ssl) |
| # |
| # --install_prefix Additional prefix for package builders (empty by |
| # default). This needn't be set in advance, you can |
| # just as well use "make INSTALL_PREFIX=/whatever install". |
| # |
| # --cross-compile-prefix Add specified prefix to binutils components. |
| # |
| # --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for |
| # interfaces deprecated as of the specified OpenSSL version. |
| # |
| # no-hw-xxx do not compile support for specific crypto hardware. |
| # Generic OpenSSL-style methods relating to this support |
| # are always compiled but return NULL if the hardware |
| # support isn't compiled. |
| # no-hw do not compile support for any crypto hardware. |
| # [no-]threads [don't] try to create a library that is suitable for |
| # multithreaded applications (default is "threads" if we |
| # know how to do it) |
| # [no-]shared [don't] try to create shared libraries when supported. |
| # no-asm do not use assembler |
| # no-dso do not compile in any native shared-library methods. This |
| # will ensure that all methods just return NULL. |
| # no-egd do not compile support for the entropy-gathering daemon APIs |
| # [no-]zlib [don't] compile support for zlib compression. |
| # zlib-dynamic Like "zlib", but the zlib library is expected to be a shared |
| # library and will be loaded in run-time by the OpenSSL library. |
| # sctp include SCTP support |
| # 386 generate 80386 code |
| # no-sse2 disables IA-32 SSE2 code, above option implies no-sse2 |
| # no-<cipher> build without specified algorithm (rsa, idea, rc5, ...) |
| # -<xxx> +<xxx> compiler options are passed through |
| # |
| # DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items |
| # provided to stack calls. Generates unique stack functions for |
| # each possible stack type. |
| # BN_LLONG use the type 'long long' in crypto/bn/bn.h |
| # RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h |
| # Following are set automatically by this script |
| # |
| # MD5_ASM use some extra md5 assember, |
| # SHA1_ASM use some extra sha1 assember, must define L_ENDIAN for x86 |
| # RMD160_ASM use some extra ripemd160 assember, |
| # SHA256_ASM sha256_block is implemented in assembler |
| # SHA512_ASM sha512_block is implemented in assembler |
| # AES_ASM ASE_[en|de]crypt is implemented in assembler |
| |
| # Minimum warning options... any contributions to OpenSSL should at least get |
| # past these. |
| |
| my $gcc_devteam_warn = "-Wall -pedantic -DPEDANTIC -Wno-long-long -Wsign-compare -Wmissing-prototypes -Wshadow -Wformat -Wtype-limits -Werror -DREF_CHECK -DDEBUG_UNUSED"; |
| |
| # These are used in addition to $gcc_devteam_warn when the compiler is clang. |
| # TODO(openssl-team): fix problems and investigate if (at least) the |
| # following warnings can also be enabled: |
| # -Wswitch-enum, -Wunused-macros, -Wmissing-field-initializers, |
| # -Wcast-align, |
| # -Wunreachable-code -Wunused-parameter -Wlanguage-extension-token |
| # -Wextended-offsetof |
| my $clang_devteam_warn = "-Wno-unused-parameter -Wno-missing-field-initializers -Wno-language-extension-token -Wno-extended-offsetof -Wconditional-uninitialized -Qunused-arguments -Wincompatible-pointer-types-discards-qualifiers -Wmissing-variable-declarations"; |
| |
| # Warn that "make depend" should be run? |
| my $warn_make_depend = 0; |
| |
| # These are used in addition to $gcc_devteam_warn unless this is a mingw build. |
| # This adds backtrace information to the memory leak info. |
| my $memleak_devteam_backtrace = "-rdynamic -DCRYPTO_MDEBUG_BACKTRACE"; |
| |
| my $strict_warnings = 0; |
| |
| # As for $BSDthreads. Idea is to maintain "collective" set of flags, |
| # which would cover all BSD flavors. -pthread applies to them all, |
| # but is treated differently. OpenBSD expands is as -D_POSIX_THREAD |
| # -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r, |
| # which has to be accompanied by explicit -D_THREAD_SAFE and |
| # sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which |
| # seems to be sufficient? |
| my $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT"; |
| |
| # |
| # API compability name to version number mapping. |
| # |
| my $maxapi = "1.1.0"; # API for "no-deprecated" builds |
| my $apitable = { |
| "1.1.0" => "0x10100000L", |
| "1.0.0" => "0x10000000L", |
| "0.9.8" => "0x00908000L", |
| }; |
| |
| my $base_target = "BASE"; # The template that all other inherit from |
| our %table = (); |
| our %config = (); |
| |
| # Forward declarations ############################################### |
| |
| # read_config(filename) |
| # |
| # Reads a configuration file and populates %table with the contents |
| # (which the configuration file places in %targets). |
| sub read_config; |
| |
| # resolve_config(target) |
| # |
| # Resolves all the late evalutations, inheritances and so on for the |
| # chosen target and any target it inherits from. |
| sub resolve_config; |
| |
| |
| # Information collection ############################################# |
| |
| # Unified build supports separate build dir |
| my $srcdir = catdir(realpath(dirname($0))); # catdir ensures local syntax |
| my $blddir = catdir(realpath(".")); # catdir ensures local syntax |
| my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl")); |
| |
| $config{sourcedir} = abs2rel($srcdir); |
| $config{builddir} = abs2rel($blddir); |
| |
| # Collect version numbers |
| $config{version} = "unknown"; |
| $config{version_num} = "unknown"; |
| $config{shlib_version_number} = "unknown"; |
| $config{shlib_version_history} = "unknown"; |
| |
| collect_information( |
| collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')), |
| qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; }, |
| qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 }, |
| qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 }, |
| qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 } |
| ); |
| if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; } |
| |
| ($config{major}, $config{minor}) |
| = ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/); |
| ($config{shlib_major}, $config{shlib_minor}) |
| = ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/); |
| die "erroneous version information in opensslv.h: ", |
| "$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n" |
| if ($config{major} eq "" || $config{minor} eq "" |
| || $config{shlib_major} eq "" || $config{shlib_minor} eq ""); |
| |
| # Collect target configurations |
| |
| my $pattern = catfile(dirname($0), "Configurations", "*.conf"); |
| foreach (sort glob($pattern) ) { |
| &read_config($_); |
| } |
| |
| |
| print "Configuring OpenSSL version $config{version} (0x$config{version_num})\n"; |
| |
| $config{perl}; |
| $config{prefix}=""; |
| $config{openssldir}=""; |
| $config{processor}=""; |
| $config{libdir}=""; |
| $config{install_prefix}= "$ENV{'INSTALL_PREFIX'}"; |
| $config{cross_compile_prefix}=""; |
| $config{fipslibdir}="/usr/local/ssl/fips-2.0/lib/"; |
| my $nofipscanistercheck=0; |
| $config{baseaddr}="0xFB00000"; |
| my $no_threads=0; |
| my $threads=0; |
| $config{no_shared}=0; # but "no-shared" is default |
| my $zlib=1; # but "no-zlib" is default |
| my $no_rfc3779=0; |
| my $no_asm=0; |
| my $no_dso=0; |
| my $default_ranlib; |
| $config{fips}=0; |
| |
| # Top level directories to build |
| $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "tools" ]; |
| # crypto/ subdirectories to build |
| $config{sdirs} = [ |
| "objects", |
| "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", |
| "des", "aes", "rc2", "rc4", "rc5", "idea", "bf", "cast", "camellia", "seed", "chacha", "modes", |
| "bn", "ec", "rsa", "dsa", "dh", "dso", "engine", |
| "buffer", "bio", "stack", "lhash", "rand", "err", |
| "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", |
| "cms", "ts", "jpake", "srp", "store", "cmac", "ct", "async", "kdf" |
| ]; |
| |
| # Known TLS and DTLS protocols |
| my @tls = qw(ssl3 tls1 tls1_1 tls1_2); |
| my @dtls = qw(dtls1 dtls1_2); |
| |
| # Explicitelly known options that are possible to disable. They can |
| # be regexps, and will be used like this: /^no-${option}$/ |
| # For developers: keep it sorted alphabetically |
| |
| my @disablables = ( |
| "aes", |
| "asm", |
| "async", |
| "bf", |
| "camellia", |
| "capieng", |
| "cast", |
| "chacha", |
| "cmac", |
| "cms", |
| "comp", |
| "crypto-mdebug", |
| "ct", |
| "deprecated", |
| "des", |
| "dgram", |
| "dh", |
| "dsa", |
| "dso", |
| "dtls", |
| "dynamic[-_]engine", |
| "ec", |
| "ec2m", |
| "ecdh", |
| "ecdsa", |
| "ec_nistp_64_gcc_128", |
| "egd", |
| "engine", |
| "err", # Really??? |
| "heartbeats", |
| "hmac", |
| "hw(-.+)?", |
| "idea", |
| "jpake", |
| "locking", # Really??? |
| "md2", |
| "md4", |
| "md5", |
| "mdc2", |
| "md[-_]ghost94", |
| "nextprotoneg", |
| "ocb", |
| "ocsp", |
| "poly1305", |
| "posix-io", |
| "psk", |
| "rc2", |
| "rc4", |
| "rc5", |
| "rdrand", |
| "rfc3779", |
| "rijndael", # Old AES name |
| "rmd160", |
| "rsa", |
| "scrypt", |
| "sct", |
| "sctp", |
| "seed", |
| "sha", |
| "shared", |
| "sock", |
| "srp", |
| "srtp", |
| "sse2", |
| "ssl", |
| "ssl-trace", |
| "static-engine", |
| "stdio", |
| "store", |
| "threads", |
| "tls", |
| "unit-test", |
| "whirlpool", |
| "zlib", |
| "zlib-dynamic", |
| ); |
| foreach my $proto ((@tls, @dtls)) |
| { |
| push(@disablables, $proto); |
| push(@disablables, "$proto-method"); |
| } |
| |
| # All of the following is disabled by default (RC5 was enabled before 0.9.8): |
| |
| my %disabled = ( # "what" => "comment" [or special keyword "experimental"] |
| "ec_nistp_64_gcc_128" => "default", |
| "egd" => "default", |
| "jpake" => "experimental", |
| "md2" => "default", |
| "rc5" => "default", |
| "sctp" => "default", |
| "shared" => "default", |
| "ssl-trace" => "default", |
| "store" => "experimental", |
| "unit-test" => "default", |
| "zlib" => "default", |
| "zlib-dynamic" => "default", |
| "crypto-mdebug" => "default", |
| ); |
| my @experimental = (); |
| |
| # Note: => pair form used for aesthetics, not to truly make a hash table |
| my @disable_cascades = ( |
| # "what" => [ "cascade", ... ] |
| sub { $config{processor} eq "386" } |
| => [ "sse2" ], |
| "ssl" => [ "ssl3" ], |
| "ssl3-method" => [ "ssl3" ], |
| "zlib" => [ "zlib-dynamic" ], |
| "rijndael" => [ "aes" ], |
| "des" => [ "mdc2" ], |
| "ec" => [ "ecdsa", "ecdh" ], |
| "psk" => [ "jpake" ], |
| |
| "dgram" => [ "dtls" ], |
| "dtls" => [ @dtls ], |
| |
| # SSL 3.0, (D)TLS 1.0 and TLS 1.1 require MD5 and SHA |
| "md5" => [ "ssl", "tls1", "tls1_1", "dtls1" ], |
| "sha" => [ "ssl", "tls1", "tls1_1", "dtls1" ], |
| |
| # Additionally, SSL 3.0 requires either RSA or DSA+DH |
| sub { $disabled{rsa} |
| && ($disabled{dsa} || $disabled{dh}); } |
| => [ "ssl" ], |
| |
| # (D)TLS 1.0 and TLS 1.1 also require either RSA or DSA+DH |
| # or ECDSA + ECDH. (D)TLS 1.2 has this requirement as well. |
| # (XXX: We don't support PSK-only builds). |
| sub { $disabled{rsa} |
| && ($disabled{dsa} || $disabled{dh}) |
| && ($disabled{ecdsa} || $disabled{ecdh}); } |
| => [ "tls1", "tls1_1", "tls1_2", |
| "dtls1", "dtls1_2" ], |
| |
| "tls" => [ @tls ], |
| |
| # SRP and HEARTBEATS require TLSEXT |
| "tlsext" => [ "srp", "heartbeats" ], |
| ); |
| |
| # Avoid protocol support holes. Also disable all versions below N, if version |
| # N is disabled while N+1 is enabled. |
| # |
| my @list = (reverse @tls); |
| while ((my $first, my $second) = (shift @list, shift @list)) { |
| last unless @list; |
| push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } |
| => [ @list ] ); |
| unshift @list, $second; |
| } |
| my @list = (reverse @dtls); |
| while ((my $first, my $second) = (shift @list, shift @list)) { |
| last unless @list; |
| push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} } |
| => [ @list ] ); |
| unshift @list, $second; |
| } |
| |
| # Construct the string of what $config{depflags} should look like with the defaults |
| # from %disabled above. (we need this to see if we should advise the user |
| # to run "make depend"): |
| my $default_depflags = join(" ", |
| map { my $x = $_; $x =~ tr{[a-z]-}{[A-Z]_}; "-DOPENSSL_NO_$x"; } |
| grep { $disabled{$_} !~ /\(no-depflags\)$/ } |
| sort keys %disabled); |
| |
| # Explicit "no-..." options will be collected in %disabled along with the defaults. |
| # To remove something from %disabled, use "enable-foo" (unless it's experimental). |
| # For symmetry, "disable-foo" is a synonym for "no-foo". |
| |
| # For features called "experimental" here, a more explicit "experimental-foo" is needed to enable. |
| # We will collect such requests in @experimental. |
| # To avoid accidental use of experimental features, applications will have to use -DOPENSSL_EXPERIMENTAL_FOO. |
| |
| |
| my $no_sse2=0; |
| |
| &usage if ($#ARGV < 0); |
| |
| my $flags=""; |
| $config{depflags}=""; |
| $config{openssl_experimental_defines}=[]; |
| $config{openssl_api_defines}=[]; |
| $config{openssl_algorithm_defines}=[]; |
| $config{openssl_thread_defines}=[]; |
| $config{openssl_sys_defines}=[]; |
| $config{openssl_other_defines}=[]; |
| my $libs=""; |
| my $target=""; |
| $config{options}=""; |
| my $make_depend=0; |
| my %withargs=(); |
| my $build_prefix = "release_"; |
| |
| my @argvcopy=@ARGV; |
| |
| if (grep /^reconf(igure)?$/, @argvcopy) { |
| if (-f "./configdata.pm") { |
| my $file = "./configdata.pm"; |
| unless (my $return = do $file) { |
| die "couldn't parse $file: $@" if $@; |
| die "couldn't do $file: $!" unless defined $return; |
| die "couldn't run $file" unless $return; |
| } |
| |
| @argvcopy = defined($configdata::config{perlargv}) ? |
| @{$configdata::config{perlargv}} : (); |
| die "Incorrect data to reconfigure, please do a normal configuration\n" |
| if (grep(/^reconf/,@argvcopy)); |
| $ENV{CROSS_COMPILE} = $configdata::config{cross_compile_prefix} |
| if defined($configdata::config{cross_compile_prefix}); |
| $ENV{CROSS_COMPILE} = $configdata::config{cc} |
| if defined($configdata::config{cc}); |
| |
| print "Reconfiguring with: ", join(" ",@argvcopy), "\n"; |
| print " CROSS_COMPILE = ",$ENV{CROSS_COMPILE},"\n" |
| if $ENV{CROSS_COMPILE}; |
| print " CC = ",$ENV{CC},"\n" if $ENV{CC}; |
| } elsif (open IN, "<Makefile") { |
| # |
| # THIS SECTION IS TEMPORARY, it helps transitioning from Makefile |
| # centered information gathering the reading configdata.pm |
| # |
| while (<IN>) { |
| chomp; |
| if (/^CONFIGURE_ARGS=\s*(.*)\s*/) { |
| # Older form, we split the string and hope for the best |
| @argvcopy = split /\s+/, $_; |
| die "Incorrect data to reconfigure, please do a normal configuration\n" |
| if (grep(/^reconf/,@argvcopy)); |
| } elsif (/^CROSS_COMPILE=\s*(.*)/) { |
| $ENV{CROSS_COMPILE}=$1; |
| } elsif (/^CC=\s*(?:\$\(CROSS_COMPILE\))?(.*?)$/) { |
| $ENV{CC}=$1; |
| } |
| } |
| # |
| # END OF TEMPORARY SECTION |
| # |
| } else { |
| die "Insufficient data to reconfigure, please do a normal configuration\n"; |
| } |
| } |
| |
| $config{perlargv} = [ @argvcopy ]; |
| |
| my %unsupported_options = (); |
| foreach (@argvcopy) |
| { |
| s /^-no-/no-/; # some people just can't read the instructions |
| |
| # rewrite some options in "enable-..." form |
| s /^-?-?shared$/enable-shared/; |
| s /^sctp$/enable-sctp/; |
| s /^threads$/enable-threads/; |
| s /^zlib$/enable-zlib/; |
| s /^zlib-dynamic$/enable-zlib-dynamic/; |
| |
| if (/^(no|disable|enable|experimental)-(.+)$/) |
| { |
| my $word = $2; |
| if (!grep { $word =~ /^${_}$/ } @disablables) |
| { |
| $unsupported_options{$_} = 1; |
| next; |
| } |
| } |
| if (/^no-(.+)$/ || /^disable-(.+)$/) |
| { |
| if (!($disabled{$1} eq "experimental")) |
| { |
| foreach my $proto ((@tls, @dtls)) |
| { |
| if ($1 eq "$proto-method") |
| { |
| $disabled{"$proto"} = "option($proto-method)"; |
| last; |
| } |
| } |
| if ($1 eq "dtls") |
| { |
| foreach my $proto (@dtls) |
| { |
| $disabled{$proto} = "option(dtls)"; |
| } |
| } |
| elsif ($1 eq "ssl") |
| { |
| # Last one of its kind |
| $disabled{"ssl3"} = "option(ssl)"; |
| } |
| elsif ($1 eq "tls") |
| { |
| # XXX: Tests will fail if all SSL/TLS |
| # protocols are disabled. |
| foreach my $proto (@tls) |
| { |
| $disabled{$proto} = "option(tls)"; |
| } |
| } |
| else |
| { |
| $disabled{$1} = "option"; |
| } |
| } |
| } |
| elsif (/^enable-(.+)$/ || /^experimental-(.+)$/) |
| { |
| my $algo = $1; |
| if ($disabled{$algo} eq "experimental") |
| { |
| die "You are requesting an experimental feature; please say 'experimental-$algo' if you are sure\n" |
| unless (/^experimental-/); |
| push @experimental, $algo; |
| } |
| delete $disabled{$algo}; |
| |
| $threads = 1 if ($algo eq "threads"); |
| } |
| elsif (/^--strict-warnings$/) |
| { |
| $strict_warnings = 1; |
| } |
| elsif (/^--debug$/) |
| { |
| $build_prefix = "debug_"; |
| } |
| elsif (/^--release$/) |
| { |
| $build_prefix = "release_"; |
| } |
| elsif (/^386$/) |
| { $config{processor}=386; } |
| elsif (/^fips$/) |
| { |
| $config{fips}=1; |
| } |
| elsif (/^rsaref$/) |
| { |
| # No RSAref support any more since it's not needed. |
| # The check for the option is there so scripts aren't |
| # broken |
| } |
| elsif (/^nofipscanistercheck$/) |
| { |
| $config{fips} = 1; |
| $nofipscanistercheck = 1; |
| } |
| elsif (/^[-+]/) |
| { |
| if (/^--prefix=(.*)$/) |
| { |
| $config{prefix}=$1; |
| } |
| elsif (/^--api=(.*)$/) |
| { |
| $config{api}=$1; |
| } |
| elsif (/^--libdir=(.*)$/) |
| { |
| $config{libdir}=$1; |
| } |
| elsif (/^--openssldir=(.*)$/) |
| { |
| $config{openssldir}=$1; |
| } |
| elsif (/^--install.prefix=(.*)$/) |
| { |
| $config{install_prefix}=$1; |
| } |
| elsif (/^--with-zlib-lib=(.*)$/) |
| { |
| $withargs{zlib_lib}=$1; |
| } |
| elsif (/^--with-zlib-include=(.*)$/) |
| { |
| $withargs{zlib_include}="-I$1"; |
| } |
| elsif (/^--with-fipslibdir=(.*)$/) |
| { |
| $config{fipslibdir}="$1/"; |
| } |
| elsif (/^--with-baseaddr=(.*)$/) |
| { |
| $config{baseaddr}="$1"; |
| } |
| elsif (/^--cross-compile-prefix=(.*)$/) |
| { |
| $config{cross_compile_prefix}=$1; |
| } |
| elsif (/^--config=(.*)$/) |
| { |
| read_config $1; |
| } |
| elsif (/^-[lL](.*)$/ or /^-Wl,/) |
| { |
| $libs.=$_." "; |
| } |
| else # common if (/^[-+]/), just pass down... |
| { |
| $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei; |
| $flags.=$_." "; |
| } |
| } |
| elsif ($_ =~ /^([^:]+):(.+)$/) |
| { |
| eval "\$table{\$1} = \"$2\""; # allow $xxx constructs in the string |
| $target=$1; |
| } |
| else |
| { |
| die "target already defined - $target (offending arg: $_)\n" if ($target ne ""); |
| $target=$_; |
| } |
| unless ($_ eq $target || /^no-/ || /^disable-/) |
| { |
| # "no-..." follows later after implied disactivations |
| # have been derived. (Don't take this too seroiusly, |
| # we really only write OPTIONS to the Makefile out of |
| # nostalgia.) |
| |
| if ($config{options} eq "") |
| { $config{options} = $_; } |
| else |
| { $config{options} .= " ".$_; } |
| } |
| |
| if (defined($config{api}) && !exists $apitable->{$config{api}}) { |
| die "***** Unsupported api compatibility level: $config{api}\n", |
| } |
| |
| if (keys %unsupported_options) |
| { |
| die "***** Unsupported options: ", |
| join(", ", keys %unsupported_options), "\n"; |
| } |
| } |
| |
| if ($config{fips}) |
| { |
| delete $disabled{"shared"} if ($disabled{"shared"} =~ /^default/); |
| } |
| else |
| { |
| @{$config{dirs}} = grep !/^fips$/, @{$config{dirs}}; |
| } |
| |
| my @tocheckfor = (keys %disabled); |
| while (@tocheckfor) { |
| my %new_tocheckfor = (); |
| my @cascade_copy = (@disable_cascades); |
| while (@cascade_copy) { |
| my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy); |
| if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) { |
| map { |
| $new_tocheckfor{$_} => 1; $disabled{$_} = "forced"; |
| } grep { !defined($disabled{$_}) } @$descendents; |
| } |
| } |
| @tocheckfor = (keys %new_tocheckfor); |
| } |
| |
| if ($target eq "TABLE") { |
| foreach (sort keys %table) { |
| print_table_entry($_, "TABLE"); |
| } |
| exit 0; |
| } |
| |
| if ($target eq "LIST") { |
| foreach (sort keys %table) { |
| print $_,"\n" unless $table{$_}->{template}; |
| } |
| exit 0; |
| } |
| |
| if ($target eq "HASH") { |
| print "%table = (\n"; |
| foreach (sort keys %table) { |
| print_table_entry($_, "HASH"); |
| } |
| exit 0; |
| } |
| |
| # Backward compatibility? |
| if ($target =~ m/^CygWin32(-.*)$/) { |
| $target = "Cygwin".$1; |
| } |
| |
| foreach (sort (keys %disabled)) |
| { |
| $config{options} .= " no-$_"; |
| |
| printf " no-%-12s %-10s", $_, "[$disabled{$_}]"; |
| |
| if (/^dso$/) |
| { $no_dso = 1; } |
| elsif (/^threads$/) |
| { $no_threads = 1; } |
| elsif (/^shared$/) |
| { $config{no_shared} = 1; } |
| elsif (/^zlib$/) |
| { $zlib = 0; } |
| elsif (/^static-engine$/) |
| { } |
| elsif (/^zlib-dynamic$/) |
| { } |
| elsif (/^sse2$/) |
| { $no_sse2 = 1; } |
| elsif (/^engine$/) |
| { @{$config{dirs}} = grep !/^engine$/, @{$config{dirs}}; } |
| else |
| { |
| my ($ALGO, $algo); |
| ($ALGO = $algo = $_) =~ tr/[\-a-z]/[_A-Z]/; |
| |
| if (/^asm$/ || /^err$/ || /^hw$/ || /^hw-/ || /^async$/) |
| { |
| push @{$config{openssl_other_defines}}, "OPENSSL_NO_$ALGO"; |
| print " OPENSSL_NO_$ALGO"; |
| |
| if (/^err$/) { $flags .= "-DOPENSSL_NO_ERR "; } |
| elsif (/^asm$/) { $no_asm = 1; } |
| } |
| else |
| { |
| ($ALGO,$algo) = ("RMD160","rmd160") if ($algo eq "ripemd"); |
| |
| push @{$config{openssl_algorithm_defines}}, "OPENSSL_NO_$ALGO"; |
| $config{depflags} .= " -DOPENSSL_NO_$ALGO"; |
| print " OPENSSL_NO_$ALGO"; |
| |
| # fix-up crypto/directory name(s) |
| $algo="whrlpool" if $algo eq "whirlpool"; |
| $algo="ripemd" if $algo eq "rmd160"; |
| @{$config{sdirs}} = grep { $_ ne $algo} @{$config{sdirs}}; |
| |
| print " (skip dir)"; |
| } |
| } |
| |
| print "\n"; |
| } |
| |
| my $exp_cflags = ""; |
| |
| foreach (sort @experimental) |
| { |
| my $ALGO; |
| ($ALGO = $_) =~ tr/[a-z]/[A-Z]/; |
| |
| # opensslconf.h will set OPENSSL_NO_... unless OPENSSL_EXPERIMENTAL_... is defined |
| push @{$config{openssl_experimental_defines}}, "OPENSSL_NO_$ALGO"; |
| $exp_cflags .= " -DOPENSSL_EXPERIMENTAL_$ALGO"; |
| } |
| |
| print "Configuring for $target\n"; |
| |
| # Support for legacy targets having a name starting with 'debug-' |
| my ($d, $t) = $target =~ m/^(debug-)?(.*)$/; |
| if ($d) { |
| $build_prefix = "debug_"; |
| |
| # If we do not find debug-foo in the table, the target is set to foo. |
| if (!$table{$target}) { |
| $target = $t; |
| } |
| } |
| $config{target} = $target; |
| delete $table{$base_target}->{template}; # or the next test will fail. |
| my %target = ( %{$table{$base_target}}, resolve_config($target) ); |
| |
| &usage if (!%target || $target{template}); |
| |
| $target{exe_extension}=""; |
| $target{exe_extension}=".exe" if ($config{target} eq "Cygwin" || $config{target} eq "DJGPP" || $config{target} =~ /^mingw/); |
| $target{exe_extension}=".nlm" if ($config{target} =~ /netware/); |
| $target{exe_extension}=".pm" if ($config{target} =~ /vos/); |
| |
| $default_ranlib = which("ranlib") || "true"; |
| $config{perl} = $ENV{'PERL'} || which("perl5") || which("perl") || "perl"; |
| my $make = $ENV{'MAKE'} || "make"; |
| |
| $config{cross_compile_prefix} = $ENV{'CROSS_COMPILE'} |
| if $config{cross_compile_prefix} eq ""; |
| |
| $config{prefix} = "/usr/local" if !$config{prefix}; |
| $config{openssldir} = "ssl" if !$config{openssldir}; |
| $config{openssldir} = catdir($config{prefix}, $config{openssldir}) |
| unless file_name_is_absolute($config{openssldir}); |
| |
| # Allow environment CC to override compiler... |
| $target{cc} = $ENV{CC} || $target{cc}; |
| |
| # For cflags, lflags and ex_libs, add the debug_ or release_ attributes |
| # Do it in such a way that no spurious space is appended (hence the grep). |
| $config{cflags} = join(" ", |
| grep { $_ ne "" } ($target{cflags}, |
| $target{$build_prefix."cflags"})); |
| $config{lflags} = join(" ", |
| grep { $_ ne "" } ($target{lflags}, |
| $target{$build_prefix."lflags"})); |
| $config{ex_libs} = join(" ", |
| grep { $_ ne "" } ($target{ex_libs}, |
| $target{$build_prefix."ex_libs"})); |
| |
| $target{ranlib} = $ENV{'RANLIB'} || $target{ranlib} || $default_ranlib; |
| $target{ar} = $ENV{'AR'} || "ar"; |
| $target{arflags} = "" if !defined($target{arflags}); |
| $target{nm} = "nm"; |
| # Make sure build_scheme is consistent. |
| $target{build_scheme} = [ $target{build_scheme} ] |
| if ref($target{build_scheme}) ne "ARRAY"; |
| |
| # if $config{prefix}/lib$target{multilib} is not an existing directory, then |
| # assume that it's not searched by linker automatically, in |
| # which case adding $target{multilib} suffix causes more grief than |
| # we're ready to tolerate, so don't... |
| $target{multilib}="" if !-d "$config{prefix}/lib$target{multilib}"; |
| |
| $config{libdir}="lib$target{multilib}" if $config{libdir} eq ""; |
| $config{enginesdir}=$config{prefix} . "/" . $config{libdir} . "/engines"; |
| |
| $config{cflags} .= "$exp_cflags"; |
| |
| if ($target =~ /^mingw/ && `$target{cc} --target-help 2>&1` !~ m/-mno-cygwin/m) |
| { |
| $config{cflags} =~ s/-mno-cygwin\s*//; |
| $target{shared_ldflag} =~ s/-mno-cygwin\s*//; |
| } |
| |
| if ($target =~ /linux.*-mips/ && !$no_asm && $flags !~ /-m(ips|arch=)/) { |
| # minimally required architecture flags for assembly modules |
| $config{cflags}="-mips2 $config{cflags}" if ($target =~ /mips32/); |
| $config{cflags}="-mips3 $config{cflags}" if ($target =~ /mips64/); |
| } |
| |
| my $no_shared_warn=0; |
| my $no_user_cflags=0; |
| |
| if ($flags ne "") { $config{cflags}="$flags$config{cflags}"; } |
| else { $no_user_cflags=1; } |
| |
| # The DSO code currently always implements all functions so that no |
| # applications will have to worry about that from a compilation point |
| # of view. However, the "method"s may return zero unless that platform |
| # has support compiled in for them. Currently each method is enabled |
| # by a define "DSO_<name>" ... we translate the "dso_scheme" config |
| # string entry into using the following logic; |
| my $dso_cflags; |
| if (!$no_dso && $target{dso_scheme} ne "") |
| { |
| $target{dso_scheme} =~ tr/[a-z]/[A-Z]/; |
| if ($target{dso_scheme} eq "DLFCN") |
| { |
| $dso_cflags = "-DDSO_DLFCN -DHAVE_DLFCN_H"; |
| } |
| elsif ($target{dso_scheme} eq "DLFCN_NO_H") |
| { |
| $dso_cflags = "-DDSO_DLFCN"; |
| } |
| else |
| { |
| $dso_cflags = "-DDSO_$target{dso_scheme}"; |
| } |
| $config{cflags} = "$dso_cflags $config{cflags}"; |
| } |
| |
| my $thread_cflags = ""; |
| my @thread_defines; |
| if ($target{thread_cflag} ne "(unknown)" && !$no_threads) |
| { |
| # If we know how to do it, support threads by default. |
| $threads = 1; |
| } |
| if ($target{thread_cflag} eq "(unknown)" && $threads) |
| { |
| # If the user asked for "threads", [s]he is also expected to |
| # provide any system-dependent compiler options that are |
| # necessary. |
| if ($no_user_cflags) |
| { |
| print "You asked for multi-threading support, but didn't\n"; |
| print "provide any system-specific compiler options\n"; |
| exit(1); |
| } |
| $thread_cflags="-DOPENSSL_THREADS" ; |
| push @thread_defines, "OPENSSL_THREADS"; |
| } |
| else |
| { |
| $thread_cflags="-DOPENSSL_THREADS $target{thread_cflag}"; |
| push @thread_defines, "OPENSSL_THREADS"; |
| } |
| |
| $config{ex_libs}="$libs$config{ex_libs}" if ($libs ne ""); |
| |
| if ($no_asm) |
| { |
| $config{cflags}=~s/-D[BL]_ENDIAN// if ($config{fips}); |
| } |
| |
| if ($threads) |
| { |
| $config{cflags} = "$thread_cflags $config{cflags}" if $thread_cflags; |
| push @{$config{openssl_thread_defines}}, @thread_defines; |
| } |
| |
| if ($zlib) |
| { |
| $config{cflags} = "-DZLIB $config{cflags}"; |
| if (defined($disabled{"zlib-dynamic"})) |
| { |
| if (defined($withargs{zlib_lib})) |
| { |
| $config{ex_libs} .= " -L" . $withargs{zlib_lib} . " -lz"; |
| } |
| else |
| { |
| $config{ex_libs} .= " -lz"; |
| } |
| } |
| else |
| { |
| $config{cflags} = "-DZLIB_SHARED $config{cflags}"; |
| } |
| } |
| |
| # With "deprecated" disable all deprecated features. |
| if (defined($disabled{"deprecated"})) { |
| $config{api} = $maxapi; |
| } |
| |
| if ($target{shared_target} eq "") |
| { |
| $no_shared_warn = 1 if !$config{no_shared} && !$config{fips}; |
| $config{no_shared} = 1; |
| } |
| if (!$config{no_shared}) |
| { |
| if ($target{shared_cflag} ne "") |
| { |
| $config{cflags} = "$target{shared_cflag} -DOPENSSL_PIC $config{cflags}"; |
| } |
| } |
| |
| if ($target{build_scheme}->[0] ne "mk1mf") |
| { |
| # add {no-}static-engine to options to allow mkdef.pl to work without extra arguments |
| if ($config{no_shared}) |
| { |
| push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE"; |
| $config{options}.=" static-engine"; |
| } |
| else |
| { |
| push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE"; |
| $config{options}.=" no-static-engine"; |
| } |
| } |
| |
| # |
| # Platform fix-ups |
| # |
| # Unlike other OSes (like Solaris, Linux, Tru64, IRIX) BSD run-time |
| # linkers (tested OpenBSD, NetBSD and FreeBSD) "demand" RPATH set on |
| # .so objects. Apparently application RPATH is not global and does |
| # not apply to .so linked with other .so. Problem manifests itself |
| # when libssl.so fails to load libcrypto.so. One can argue that we |
| # should engrave this into Makefile.shared rules or into BSD-* config |
| # lines above. Meanwhile let's try to be cautious and pass -rpath to |
| # linker only when --prefix is not /usr. |
| if ($target =~ /^BSD-/) |
| { |
| $target{shared_ldflag}.=" -Wl,-rpath,\$\$(LIBRPATH)" if ($config{prefix} !~ m|^/usr[/]*$|); |
| } |
| |
| if ($target{sys_id} ne "") |
| { |
| #$config{cflags}="-DOPENSSL_SYS_$target{sys_id} $config{cflags}"; |
| push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}"; |
| } |
| |
| if ($target{ranlib} eq "") |
| { |
| $target{ranlib} = $default_ranlib; |
| } |
| |
| if (!$no_asm) { |
| $target{cpuid_asm_src}=$table{BASE}->{cpuid_asm_src} if ($config{processor} eq "386"); |
| $target{cpuid_asm_src}.=" uplink.c uplink-x86.s" if ($config{cflags} =~ /-DOPENSSL_USE_APPLINK/); |
| |
| $target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m})); |
| |
| # bn-586 is the only one implementing bn_*_part_words |
| $config{cflags}.=" -DOPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/); |
| $config{cflags}.=" -DOPENSSL_IA32_SSE2" if (!$no_sse2 && $target{bn_asm_src} =~ /86/); |
| |
| $config{cflags}.=" -DOPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/); |
| $config{cflags}.=" -DOPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/); |
| $config{cflags}.=" -DOPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/); |
| |
| if ($config{fips}) { |
| push @{$config{openssl_other_defines}}, "OPENSSL_FIPS"; |
| } |
| |
| if ($target{sha1_asm_src}) { |
| $config{cflags}.=" -DSHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/); |
| $config{cflags}.=" -DSHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/); |
| $config{cflags}.=" -DSHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/); |
| } |
| if ($target{md5_asm_src}) { |
| $config{cflags}.=" -DMD5_ASM"; |
| } |
| $target{cast_asm_src}=$table{BASE}->{cast_asm_src} if (!$config{no_shared}); # CAST assembler is not PIC |
| if ($target{rmd160_asm_src}) { |
| $config{cflags}.=" -DRMD160_ASM"; |
| } |
| if ($target{aes_asm_src}) { |
| $config{cflags}.=" -DAES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);; |
| # aes-ctr.fake is not a real file, only indication that assembler |
| # module implements AES_ctr32_encrypt... |
| $config{cflags}.=" -DAES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//); |
| # aes-xts.fake indicates presence of AES_xts_[en|de]crypt... |
| $config{cflags}.=" -DAES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//); |
| $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($no_sse2); |
| $config{cflags}.=" -DVPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/); |
| $config{cflags}.=" -DBSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/); |
| } |
| if ($target{wp_asm_src} =~ /mmx/) { |
| if ($config{processor} eq "386") { |
| $target{wp_asm_src}=$table{BASE}->{wp_asm_src}; |
| } elsif (!$disabled{"whirlpool"}) { |
| $config{cflags}.=" -DWHIRLPOOL_ASM"; |
| } |
| } |
| if ($target{modes_asm_src} =~ /ghash-/) { |
| $config{cflags}.=" -DGHASH_ASM"; |
| } |
| if ($target{ec_asm_src} =~ /ecp_nistz256/) { |
| $config{cflags}.=" -DECP_NISTZ256_ASM"; |
| } |
| if ($target{poly1305_asm_src} ne "") { |
| $config{cflags}.=" -DPOLY1305_ASM"; |
| } |
| } |
| |
| # Is the compiler gcc or clang? $ecc is used below to see if error-checking |
| # can be turned on. |
| my $ecc = $target{cc}; |
| my $ccpcc = "$config{cross_compile_prefix}$target{cc}"; |
| $config{makedepprog} = 'makedepend'; |
| open(PIPE, "$ccpcc --version 2>&1 | head -2 |"); |
| while ( <PIPE> ) { |
| $config{makedepprog} = $ccpcc if /clang|gcc/; |
| $ecc = "clang" if /clang/; |
| $ecc = "gcc" if /gcc/; |
| } |
| close(PIPE); |
| |
| $config{depflags} =~ s/^\s*//; |
| |
| |
| # Deal with bn_ops ################################################### |
| |
| $config{bn_ll} =0; |
| $config{export_var_as_fn} =0; |
| my $def_int="unsigned int"; |
| $config{rc4_int} =$def_int; |
| ($config{b64l},$config{b64},$config{b32})=(0,0,1); |
| |
| my $count = 0; |
| foreach (sort split(/\s+/,$target{bn_ops})) { |
| $count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/; |
| $config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN'; |
| $config{bn_ll}=1 if $_ eq 'BN_LLONG'; |
| $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR'; |
| ($config{b64l},$config{b64},$config{b32}) |
| =(0,1,0) if $_ eq 'SIXTY_FOUR_BIT'; |
| ($config{b64l},$config{b64},$config{b32}) |
| =(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG'; |
| ($config{b64l},$config{b64},$config{b32}) |
| =(0,0,1) if $_ eq 'THIRTY_TWO_BIT'; |
| } |
| die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n" |
| if $count > 1; |
| |
| |
| # Hack cflags for better warnings (dev option) ####################### |
| |
| # "Stringify" the C flags string. This permits it to be made part of a string |
| # and works as well on command lines. |
| $config{cflags} =~ s/([\\\"])/\\\1/g; |
| |
| if (defined($config{api})) { |
| $config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ]; |
| my $apiflag = sprintf("-DOPENSSL_API_COMPAT=%s", $apitable->{$config{api}}); |
| $default_depflags .= " $apiflag"; |
| $config{cflags} .= " $apiflag"; |
| } |
| |
| if ($strict_warnings) |
| { |
| my $wopt; |
| die "ERROR --strict-warnings requires gcc or clang" |
| unless $ecc eq 'gcc' || $ecc eq 'clang'; |
| foreach $wopt (split /\s+/, $gcc_devteam_warn) |
| { |
| $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(^|\s)$wopt(\s|$)/) |
| } |
| if ($ecc eq "clang") |
| { |
| foreach $wopt (split /\s+/, $clang_devteam_warn) |
| { |
| $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(^|\s)$wopt(\s|$)/) |
| } |
| } |
| if ($target !~ /^mingw/) |
| { |
| foreach $wopt (split /\s+/, $memleak_devteam_backtrace) |
| { |
| $config{cflags} .= " $wopt" unless ($config{cflags} =~ /(^|\s)$wopt(\s|$)/) |
| } |
| if ($target =~ /^BSD-/) |
| { |
| $config{ex_libs} .= " -lexecinfo"; |
| } |
| } |
| } |
| |
| # If we use the unified build, collect information from build.info files |
| my %unified_info = (); |
| |
| if ($target{build_scheme}->[0] eq "unified") { |
| use lib catdir(dirname(__FILE__),"util"); |
| use with_fallback qw(Text::Template); |
| |
| # Helpers to produce clean paths with no /../ in the middle and so on. |
| sub int_absolutedir { |
| my $dir = shift; |
| |
| # Required, because realpath only works properly with existing dirs |
| make_path($dir); |
| |
| my $res = realpath($dir); |
| return $res; |
| } |
| |
| sub cleandir { |
| my $dir = shift; |
| my $base = shift || "."; |
| |
| my $res = abs2rel(int_absolutedir($dir), rel2abs($base)); |
| #print STDERR "DEBUG[cleandir]: $dir , $base => $res\n"; |
| return $res; |
| } |
| |
| sub cleanfile { |
| my $file = shift; |
| my $base = shift || "."; |
| my $d = dirname($file); |
| my $f = basename($file); |
| |
| my $res = abs2rel(catfile(int_absolutedir($d), $f), rel2abs($base)); |
| #print STDERR "DEBUG[cleanfile]: $d , $f => $res\n"; |
| return $res; |
| } |
| |
| my @build_infos = ( [ ".", "build.info" ] ); |
| foreach (@{$config{dirs}}) { |
| push @build_infos, [ $_, "build.info" ] |
| if (-f catfile($srcdir, $_, "build.info")); |
| } |
| foreach (@{$config{sdirs}}) { |
| push @build_infos, [ catdir("crypto", $_), "build.info" ] |
| if (-f catfile($srcdir, "crypto", $_, "build.info")); |
| } |
| foreach (@{$config{engdirs}}) { |
| push @build_infos, [ catdir("engines", $_), "build.info" ] |
| if (-f catfile($srcdir, "engines", $_, "build.info")); |
| } |
| |
| foreach (@build_infos) { |
| my $sourced = catdir($srcdir, $_->[0]); |
| my $buildd = catdir($blddir, $_->[0]); |
| |
| make_path($buildd); |
| |
| my $f = $_->[1]; |
| # The basic things we're trying to build |
| my @programs = (); |
| my @libraries = (); |
| my @engines = (); |
| my @scripts = (); |
| my @extra = (); |
| my @intermediates = (); |
| my @rawlines = (); |
| |
| my %ordinals = (); |
| my %sources = (); |
| my %includes = (); |
| my %depends = (); |
| my %renames = (); |
| my %sharednames = (); |
| |
| my $template = Text::Template->new(TYPE => 'FILE', |
| SOURCE => catfile($sourced, $f)); |
| die "Something went wrong with $sourced/$f: $!\n" unless $template; |
| my @text = |
| split /^/m, |
| $template->fill_in(HASH => { config => \%config, |
| target => \%target, |
| builddir => abs2rel($buildd, $blddir), |
| sourcedir => abs2rel($sourced, $blddir), |
| buildtop => abs2rel($blddir, $blddir), |
| sourcetop => abs2rel($srcdir, $blddir) }, |
| DELIMITERS => [ "{-", "-}" ]); |
| |
| # The top item of this stack has the following values |
| # -2 positive already run and we found ELSE (following ELSIF should fail) |
| # -1 positive already run (skip until ENDIF) |
| # 0 negatives so far (if we're at a condition, check it) |
| # 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF) |
| # 2 positive ELSE (following ELSIF should fail) |
| my @skip = (); |
| collect_information( |
| collect_from_array([ @text ], |
| qr/\\$/ => sub { my $l1 = shift; my $l2 = shift; |
| $l1 =~ s/\\$//; $l1.$l2 }), |
| # Info we're looking for |
| qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/ |
| => sub { push @skip, !! $1; }, |
| qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/ |
| => sub { die "ELSIF out of scope" if ! @skip; |
| die "ELSIF following ELSE" if abs($skip[$#skip]) == 2; |
| $skip[$#skip] = -1 if $skip[$#skip] != 0; |
| $skip[$#skip] = !! $1 |
| if $skip[$#skip] == 0; }, |
| qr/^\s*ELSE\s*$/ |
| => sub { die "ELSE out of scope" if ! @skip; |
| $skip[$#skip] = -2 if $skip[$#skip] != 0; |
| $skip[$#skip] = 2 if $skip[$#skip] == 0; }, |
| qr/^\s*ENDIF\s*$/ |
| => sub { die "ENDIF out of scope" if ! @skip; |
| pop @skip; }, |
| qr/^\s*PROGRAMS\s*=\s*(.*)\s*$/ |
| => sub { push @programs, split(/\s+/, $1) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*LIBS\s*=\s*(.*)\s*$/ |
| => sub { push @libraries, split(/\s+/, $1) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*ENGINES\s*=\s*(.*)\s*$/ |
| => sub { push @engines, split(/\s+/, $1) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*SCRIPTS\s*=\s*(.*)\s*$/ |
| => sub { push @scripts, split(/\s+/, $1) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*EXTRA\s*=\s*(.*)\s*$/ |
| => sub { push @extra, split(/\s+/, $1) |
| if !@skip || $skip[$#skip] > 0 }, |
| |
| qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/, |
| => sub { push @{$ordinals{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ |
| => sub { push @{$sources{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ |
| => sub { push @{$includes{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*DEPEND\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ |
| => sub { push @{$depends{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ |
| => sub { push @{$renames{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/ |
| => sub { push @{$sharednames{$1}}, split(/\s+/, $2) |
| if !@skip || $skip[$#skip] > 0 }, |
| qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/ |
| => sub { |
| my $lineiterator = shift; |
| my $target_kind = $1; |
| while (defined $lineiterator->()) { |
| chomp; |
| if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) { |
| die "ENDRAW doesn't match BEGINRAW" |
| if $1 ne $target_kind; |
| last; |
| } |
| next if @skip && $skip[$#skip] <= 0; |
| push @rawlines, $_ |
| if ($target_kind eq $target{build_file} |
| || $target_kind eq $target{build_file}."(".$target{build_scheme}->[1].")"); |
| } |
| }, |
| qr/^(?:#.*|\s*)$/ => sub { }, |
| "OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" } |
| ); |
| die "runaway IF?" if (@skip); |
| |
| foreach (keys %renames) { |
| die "$_ renamed to more than one thing: " |
| ,join(" ", @{$renames{$_}}),"\n" |
| if scalar @{$renames{$_}} > 1; |
| my $dest = cleanfile(catfile($buildd, $_), $blddir); |
| my $to = cleanfile(catfile($buildd, $renames{$_}->[0]), $blddir); |
| die "$dest renamed to more than one thing: " |
| ,$unified_info{rename}->{$dest}, $to |
| unless !defined($unified_info{rename}->{$dest}) |
| or $unified_info{rename}->{$dest} eq $to; |
| $unified_info{rename}->{$dest} = $to; |
| } |
| |
| foreach (@programs) { |
| my $program = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$program}) { |
| $program = $unified_info{rename}->{$program}; |
| } |
| $unified_info{programs}->{$program} = 1; |
| } |
| |
| foreach (@libraries) { |
| my $library = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$library}) { |
| $library = $unified_info{rename}->{$library}; |
| } |
| $unified_info{libraries}->{$library} = 1; |
| } |
| |
| die <<"EOF" if $config{no_shared} && scalar @engines; |
| ENGINES can only be used if configured with 'shared'. |
| This is usually a fault in a build.info file. |
| EOF |
| foreach (@engines) { |
| my $library = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$library}) { |
| $library = $unified_info{rename}->{$library}; |
| } |
| $unified_info{engines}->{$library} = 1; |
| } |
| |
| foreach (@scripts) { |
| my $script = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$script}) { |
| $script = $unified_info{rename}->{$script}; |
| } |
| $unified_info{scripts}->{$script} = 1; |
| } |
| |
| foreach (@extra) { |
| my $extra = cleanfile(catfile($buildd, $_), $blddir); |
| $unified_info{extra}->{$extra} = 1; |
| } |
| |
| push @{$unified_info{rawlines}}, @rawlines; |
| |
| if (!$config{no_shared}) { |
| # Check sharednames. |
| foreach (keys %sharednames) { |
| my $dest = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$dest}) { |
| $dest = $unified_info{rename}->{$dest}; |
| } |
| die "shared_name for $dest with multiple values: " |
| ,join(" ", @{$sharednames{$_}}),"\n" |
| if scalar @{$sharednames{$_}} > 1; |
| my $to = cleanfile(catfile($buildd, $sharednames{$_}->[0]), |
| $blddir); |
| die "shared_name found for a library $dest that isn't defined\n" |
| unless $unified_info{libraries}->{$dest}; |
| die "shared_name for $dest with multiple values: " |
| ,$unified_info{sharednames}->{$dest}, ", ", $to |
| unless !defined($unified_info{sharednames}->{$dest}) |
| or $unified_info{sharednames}->{$dest} eq $to; |
| $unified_info{sharednames}->{$dest} = $to; |
| } |
| |
| # Additionally, we set up sharednames for libraries that don't |
| # have any, as themselves. |
| foreach (keys %{$unified_info{libraries}}) { |
| if (!defined $unified_info{sharednames}->{$_}) { |
| $unified_info{sharednames}->{$_} = $_ |
| } |
| } |
| } |
| |
| foreach (keys %ordinals) { |
| my $dest = $_; |
| my $ddest = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$ddest}) { |
| $ddest = $unified_info{rename}->{$ddest}; |
| } |
| foreach (@{$ordinals{$dest}}) { |
| my %known_ordinals = |
| ( |
| crypto => |
| cleanfile(catfile($sourced, "util", "libeay.num"), $blddir), |
| ssl => |
| cleanfile(catfile($sourced, "util", "ssleay.num"), $blddir) |
| ); |
| my $o = $known_ordinals{$_}; |
| die "Ordinals for $ddest defined more than once\n" |
| if $unified_info{ordinals}->{$ddest}; |
| $unified_info{ordinals}->{$ddest} = [ $_, $o ]; |
| } |
| } |
| |
| foreach (keys %sources) { |
| my $dest = $_; |
| my $ddest = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$ddest}) { |
| $ddest = $unified_info{rename}->{$ddest}; |
| } |
| foreach (@{$sources{$dest}}) { |
| my $s = cleanfile(catfile($sourced, $_), $blddir); |
| |
| # If it isn't in the source tree, we assume it's generated |
| # in the build tree |
| if (! -f $s) { |
| $s = cleanfile(catfile($buildd, $_), $blddir); |
| } |
| # We recognise C and asm files |
| if ($s =~ /\.[csS]\b$/) { |
| (my $o = $_) =~ s/\.[csS]\b$/.o/; |
| $o = cleanfile(catfile($buildd, $o), $blddir); |
| $unified_info{sources}->{$ddest}->{$o} = 1; |
| $unified_info{sources}->{$o}->{$s} = 1; |
| } else { |
| $unified_info{sources}->{$ddest}->{$s} = 1; |
| } |
| } |
| } |
| |
| foreach (keys %depends) { |
| my $dest = $_; |
| my $ddest = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$ddest}) { |
| $ddest = $unified_info{rename}->{$ddest}; |
| } |
| foreach (@{$depends{$dest}}) { |
| my $d = cleanfile(catfile($sourced, $_), $blddir); |
| |
| # If it isn't found in the source, let's assume it's generated |
| # and that the Makefile template has the lines |
| if (! -f $d) { |
| $d = cleanfile(catfile($buildd, $_), $blddir); |
| } |
| # Take note if the file to depend on is being renamed |
| if ($unified_info{rename}->{$d}) { |
| $d = $unified_info{rename}->{$d}; |
| } |
| $unified_info{depends}->{$ddest}->{$d} = 1; |
| # If we depend on a header file, let's make sure it |
| # can get included |
| if ($d =~ /\.h$/) { |
| my $i = dirname($d); |
| push @{$unified_info{includes}->{$ddest}}, $i |
| unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}}; |
| } |
| } |
| } |
| |
| foreach (keys %includes) { |
| my $dest = $_; |
| my $ddest = cleanfile(catfile($buildd, $_), $blddir); |
| if ($unified_info{rename}->{$ddest}) { |
| $ddest = $unified_info{rename}->{$ddest}; |
| } |
| foreach (@{$includes{$dest}}) { |
| my $i = cleandir(catdir($sourced, $_), $blddir); |
| push @{$unified_info{includes}->{$ddest}}, $i |
| unless grep { $_ eq $i } @{$unified_info{includes}->{$ddest}}; |
| } |
| } |
| } |
| |
| ### Make unified_info a bit more efficient |
| # One level structures |
| foreach (("programs", "libraries", "engines", "scripts", "extra")) { |
| $unified_info{$_} = [ sort keys %{$unified_info{$_}} ]; |
| } |
| # Two level structures |
| foreach my $l1 (("sources", "ldadd", "depends")) { |
| foreach my $l2 (sort keys %{$unified_info{$l1}}) { |
| $unified_info{$l1}->{$l2} = |
| [ sort keys %{$unified_info{$l1}->{$l2}} ]; |
| } |
| } |
| } |
| |
| # For the schemes that need it, we provide the old *_obj configs |
| # from the *_asm_obj ones |
| foreach (grep /_asm_src$/, keys %target) { |
| my $src = $_; |
| (my $obj = $_) =~ s/_asm_src$/_obj/; |
| ($target{$obj} = $target{$src}) =~ s/\.[csS]\b/.o/g; |
| } |
| |
| # Write down our configuration where it fits ######################### |
| |
| open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n"; |
| print OUT <<"EOF"; |
| package configdata; |
| |
| use strict; |
| use warnings; |
| |
| use Exporter; |
| #use vars qw(\@ISA \@EXPORT); |
| our \@ISA = qw(Exporter); |
| our \@EXPORT = qw(\%config \%target %withargs %unified_info); |
| |
| EOF |
| print OUT "our %config = (\n"; |
| foreach (sort keys %config) { |
| if (ref($config{$_}) eq "ARRAY") { |
| print OUT " ", $_, " => [ ", join(", ", |
| map { quotify("perl", $_) } |
| @{$config{$_}}), " ],\n"; |
| } else { |
| print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n" |
| } |
| } |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| print OUT "our %target = (\n"; |
| foreach (sort keys %target) { |
| if (ref($target{$_}) eq "ARRAY") { |
| print OUT " ", $_, " => [ ", join(", ", |
| map { quotify("perl", $_) } |
| @{$target{$_}}), " ],\n"; |
| } else { |
| print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n" |
| } |
| } |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| print OUT "our \%available_protocols = (\n"; |
| print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n"; |
| print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n"; |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| print OUT "our \%disabled = (\n"; |
| foreach (sort keys %disabled) { |
| print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n"; |
| } |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| print OUT "our %withargs = (\n"; |
| foreach (sort keys %withargs) { |
| if (ref($withargs{$_}) eq "ARRAY") { |
| print OUT " ", $_, " => [ ", join(", ", |
| map { quotify("perl", $_) } |
| @{$withargs{$_}}), " ],\n"; |
| } else { |
| print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n" |
| } |
| } |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| if ($target{build_scheme}->[0] eq "unified") { |
| my $recurse; |
| $recurse = sub { |
| my $indent = shift; |
| foreach (@_) { |
| if (ref $_ eq "ARRAY") { |
| print OUT " "x$indent, "[\n"; |
| foreach (@$_) { |
| $recurse->($indent + 4, $_); |
| } |
| print OUT " "x$indent, "],\n"; |
| } elsif (ref $_ eq "HASH") { |
| my %h = %$_; |
| print OUT " "x$indent, "{\n"; |
| foreach (sort keys %h) { |
| if (ref $h{$_} eq "") { |
| print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n"; |
| } else { |
| print OUT " "x($indent + 4), quotify("perl", $_), " =>\n"; |
| $recurse->($indent + 8, $h{$_}); |
| } |
| } |
| print OUT " "x$indent, "},\n"; |
| } else { |
| print OUT " "x$indent, quotify("perl", $_), ",\n"; |
| } |
| } |
| }; |
| print OUT "our %unified_info = (\n"; |
| foreach (sort keys %unified_info) { |
| if (ref $unified_info{$_} eq "") { |
| print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n"; |
| } else { |
| print OUT " "x4, quotify("perl", $_), " =>\n"; |
| $recurse->(8, $unified_info{$_}); |
| } |
| } |
| print OUT <<"EOF"; |
| ); |
| |
| EOF |
| } |
| print OUT "1;\n"; |
| close(OUT); |
| |
| die <<"EOF" if $target{build_scheme}->[0] ne "unified" && $srcdir ne $blddir; |
| |
| ***** Trying building anywhere else than in the source tree will not |
| ***** work for target $config{target}. To make it possible, it needs |
| ***** to use the "unified" build scheme. |
| |
| EOF |
| |
| print "IsMK1MF =", ($target{build_scheme}->[0] eq "mk1mf" ? "yes" : "no"), "\n"; |
| print "CC =$target{cc}\n"; |
| print "CFLAG =$config{cflags}\n"; |
| print "LFLAGS =$config{lflags}\n"; |
| print "EX_LIBS =$config{ex_libs}\n"; |
| print "CPUID_OBJ =$target{cpuid_obj}\n"; |
| print "BN_ASM =$target{bn_obj}\n"; |
| print "EC_ASM =$target{ec_obj}\n"; |
| print "DES_ENC =$target{des_obj}\n"; |
| print "AES_ENC =$target{aes_obj}\n"; |
| print "BF_ENC =$target{bf_obj}\n"; |
| print "CAST_ENC =$target{cast_obj}\n"; |
| print "RC4_ENC =$target{rc4_obj}\n"; |
| print "RC5_ENC =$target{rc5_obj}\n"; |
| print "MD5_OBJ_ASM =$target{md5_obj}\n"; |
| print "SHA1_OBJ_ASM =$target{sha1_obj}\n"; |
| print "RMD160_OBJ_ASM=$target{rmd160_obj}\n"; |
| print "CMLL_ENC =$target{cmll_obj}\n"; |
| print "MODES_OBJ =$target{modes_obj}\n"; |
| print "PADLOCK_OBJ =$target{padlock_obj}\n"; |
| print "CHACHA_ENC =$target{chacha_obj}\n"; |
| print "POLY1305_OBJ =$target{poly1305_obj}\n"; |
| print "PROCESSOR =$config{processor}\n"; |
| print "RANLIB =$target{ranlib}\n"; |
| print "ARFLAGS =$target{arflags}\n"; |
| print "PERL =$config{perl}\n"; |
| print "\n"; |
| print "SIXTY_FOUR_BIT_LONG mode\n" if $config{b64l}; |
| print "SIXTY_FOUR_BIT mode\n" if $config{b64}; |
| print "THIRTY_TWO_BIT mode\n" if $config{b32}; |
| print "BN_LLONG mode\n" if $config{bn_ll}; |
| print "RC4 uses $config{rc4_int}\n" if $config{rc4_int} != $def_int; |
| |
| make_path(catdir($blddir, "include/openssl")); |
| run_dofile(catfile($blddir, "include/openssl/opensslconf.h"), |
| catfile($srcdir, "include/openssl/opensslconf.h.in")); |
| |
| make_path(catdir($blddir, "crypto/include/internal")); |
| foreach my $alg ( 'bn' ) { |
| run_dofile(catfile($blddir, "crypto/include/internal/${alg}_conf.h"), |
| catfile($srcdir, "crypto/include/internal/${alg}_conf.h.in")); |
| } |
| |
| ### |
| ### When the old "unixmake" scheme goes away, so does this function |
| ### |
| sub build_Makefile { |
| run_dofile("Makefile","Makefile.in"); |
| |
| # Copy all Makefile.in to Makefile (except top-level) |
| use File::Find; |
| use IO::File; |
| find( |
| { |
| preprocess => sub { |
| grep(!/^\./, @_); |
| }, |
| wanted => sub { |
| return if ($_ ne "Makefile.in" || $File::Find::dir eq "."); |
| my $in = IO::File->new($_, "r") or |
| die sprintf "Error reading Makefile.in in %s: !$\n", |
| $File::Find::dir; |
| my $out = IO::File->new("Makefile", "w") or |
| die sprintf "Error writing Makefile in %s: !$\n", |
| $File::Find::dir; |
| print $out "# Generated from $_, do not edit\n"; |
| while (my $line = <$in>) { print $out $line } |
| $in->close() or |
| die sprintf "Error reading Makefile.in in %s: !$\n", |
| $File::Find::dir; |
| $out->close() or |
| die sprintf "Error writing Makefile in %s: !$\n", |
| $File::Find::dir; |
| }, |
| }, |
| "."); |
| } |
| |
| my %builders = ( |
| unified => sub { |
| die "unified build currently does nothing"; |
| }, |
| unixmake => sub { |
| build_Makefile(); |
| |
| run_dofile("util/domd", "util/domd.in"); |
| chmod 0755, "util/domd"; |
| |
| my $make_command = "$make PERL=\'$config{perl}\'"; |
| my $make_targets = ""; |
| $make_targets .= " depend" if $config{depflags} ne $default_depflags && $make_depend; |
| (system $make_command.$make_targets) == 0 or die "make $make_targets failed" |
| if $make_targets ne ""; |
| if ($config{depflags} ne $default_depflags && !$make_depend) { |
| $warn_make_depend++; |
| } |
| }, |
| mk1mf => sub { |
| # The only reason we do this is to have something to build MINFO from |
| build_Makefile(); |
| |
| open (OUT,">crypto/buildinf.h") || die "Can't open buildinf.h"; |
| printf OUT <<"EOF"; |
| #ifndef MK1MF_BUILD |
| /* auto-generated by Configure for crypto/cversion.c: |
| * for Unix builds, crypto/Makefile.ssl generates functional definitions; |
| * Windows builds (and other mk1mf builds) compile cversion.c with |
| * -DMK1MF_BUILD and use definitions added to this file by util/mk1mf.pl. */ |
| #error "Windows builds (PLATFORM=$target) use mk1mf.pl-created Makefiles" |
| #endif |
| EOF |
| close(OUT); |
| |
| # create the ms/version32.rc file if needed |
| if (! grep /^netware/, @{$target{build_scheme}}) { |
| my ($v1, $v2, $v3, $v4); |
| if ($config{version_num} =~ /^0x([0-9a-f]{1})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{1})L$/i) { |
| $v1=hex $1; |
| $v2=hex $2; |
| $v3=hex $3; |
| $v4=hex $4; |
| } |
| open (OUT,">ms/version32.rc") || die "Can't open ms/version32.rc"; |
| print OUT <<"EOF"; |
| #include <winver.h> |
| |
| LANGUAGE 0x09,0x01 |
| |
| 1 VERSIONINFO |
| FILEVERSION $v1,$v2,$v3,$v4 |
| PRODUCTVERSION $v1,$v2,$v3,$v4 |
| FILEFLAGSMASK 0x3fL |
| #ifdef _DEBUG |
| FILEFLAGS 0x01L |
| #else |
| FILEFLAGS 0x00L |
| #endif |
| FILEOS VOS__WINDOWS32 |
| FILETYPE VFT_DLL |
| FILESUBTYPE 0x0L |
| BEGIN |
| BLOCK "StringFileInfo" |
| BEGIN |
| BLOCK "040904b0" |
| BEGIN |
| // Required: |
| VALUE "CompanyName", "The OpenSSL Project, http://www.openssl.org/\\0" |
| VALUE "FileDescription", "OpenSSL Shared Library\\0" |
| VALUE "FileVersion", "$config{version}\\0" |
| #if defined(CRYPTO) |
| VALUE "InternalName", "libeay32\\0" |
| VALUE "OriginalFilename", "libeay32.dll\\0" |
| #elif defined(SSL) |
| VALUE "InternalName", "ssleay32\\0" |
| VALUE "OriginalFilename", "ssleay32.dll\\0" |
| #endif |
| VALUE "ProductName", "The OpenSSL Toolkit\\0" |
| VALUE "ProductVersion", "$config{version}\\0" |
| // Optional: |
| //VALUE "Comments", "\\0" |
| VALUE "LegalCopyright", "Copyright © 1998-2015 The OpenSSL Project. Copyright © 1995-1998 Eric A. Young, Tim J. Hudson. All rights reserved.\\0" |
| //VALUE "LegalTrademarks", "\\0" |
| //VALUE "PrivateBuild", "\\0" |
| //VALUE "SpecialBuild", "\\0" |
| END |
| END |
| BLOCK "VarFileInfo" |
| BEGIN |
| VALUE "Translation", 0x409, 0x4b0 |
| END |
| END |
| EOF |
| close(OUT); |
| } |
| }, |
| ); |
| |
| my ($builder, @builder_opts) = @{$target{build_scheme}}; |
| $builders{$builder}->(@builder_opts); |
| |
| print <<"EOF"; |
| |
| Configured for $target. |
| EOF |
| |
| print <<"EOF" if (!$no_threads && !$threads); |
| |
| The library could not be configured for supporting multi-threaded |
| applications as the compiler options required on this system are not known. |
| See file INSTALL for details if you need multi-threading. |
| EOF |
| |
| print <<"EOF" if ($no_shared_warn); |
| |
| You gave the option 'shared', which is not supported on this platform, so |
| we will pretend you gave the option 'no-shared'. If you know how to implement |
| shared libraries, please let us know (but please first make sure you have |
| tried with a current version of OpenSSL). |
| EOF |
| |
| print <<"EOF" if ($warn_make_depend); |
| |
| *** Because of configuration changes, you MUST do the following before |
| *** building: |
| |
| make depend |
| EOF |
| |
| exit(0); |
| |
| ###################################################################### |
| # |
| # Helpers and utility functions |
| # |
| |
| # Configuration file reading ######################################### |
| |
| # Helper function to implement conditional inheritance depending on the |
| # value of $no_asm. Used in inherit_from values as follows: |
| # |
| # inherit_from => [ "template", asm("asm_tmpl") ] |
| # |
| sub asm { |
| my @x = @_; |
| sub { |
| $no_asm ? () : @x; |
| } |
| } |
| |
| # Helper function to implement adding values to already existing configuration |
| # values. It handles elements that are ARRAYs, CODEs and scalars |
| sub _add { |
| my $separator = shift; |
| |
| # If there's any ARRAY in the collection of values, we will return |
| # an ARRAY of combined values, otherwise a string of joined values |
| # with $separator as the separator. |
| my $found_array = 0; |
| |
| my @values = |
| map { |
| if (ref($_) eq "ARRAY") { |
| $found_array = 1; |
| @$_; |
| } else { |
| $_; |
| } |
| } (@_); |
| |
| if ($found_array) { |
| [ @values ]; |
| } else { |
| join($separator, @values); |
| } |
| } |
| sub add_before { |
| my $separator = shift; |
| my @x = @_; |
| sub { _add($separator, @x, @_) }; |
| } |
| sub add { |
| my $separator = shift; |
| my @x = @_; |
| sub { _add($separator, @_, @x) }; |
| } |
| |
| # configuration reader, evaluates the input file as a perl script and expects |
| # it to fill %targets with target configurations. Those are then added to |
| # %table. |
| sub read_config { |
| my $fname = shift; |
| open(CONFFILE, "< $fname") |
| or die "Can't open configuration file '$fname'!\n"; |
| my $x = $/; |
| undef $/; |
| my $content = <CONFFILE>; |
| $/ = $x; |
| close(CONFFILE); |
| my %targets = (); |
| { |
| local %table = %::table; # Protect %table from tampering |
| |
| eval $content; |
| warn $@ if $@; |
| } |
| |
| # For each target, check that it's configured with a hash table. |
| foreach (keys %targets) { |
| if (ref($targets{$_}) ne "HASH") { |
| if (ref($targets{$_}) eq "") { |
| warn "Deprecated target configuration for $_, ignoring...\n"; |
| } else { |
| warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n"; |
| } |
| delete $targets{$_}; |
| } |
| } |
| |
| %table = (%table, %targets); |
| |
| } |
| |
| # configuration resolver. Will only resolve all the lazy evalutation |
| # codeblocks for the chozen target and all those it inherits from, |
| # recursively |
| sub resolve_config { |
| my $target = shift; |
| my @breadcrumbs = @_; |
| |
| if (grep { $_ eq $target } @breadcrumbs) { |
| die "inherit_from loop! target backtrace:\n " |
| ,$target,"\n ",join("\n ", @breadcrumbs),"\n"; |
| } |
| |
| if (!defined($table{$target})) { |
| warn "Warning! target $target doesn't exist!\n"; |
| return (); |
| } |
| # Recurse through all inheritances. They will be resolved on the |
| # fly, so when this operation is done, they will all just be a |
| # bunch of attributes with string values. |
| # What we get here, though, are keys with references to lists of |
| # the combined values of them all. We will deal with lists after |
| # this stage is done. |
| my %combined_inheritance = (); |
| if ($table{$target}->{inherit_from}) { |
| my @inherit_from = |
| map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}}; |
| foreach (@inherit_from) { |
| my %inherited_config = resolve_config($_, $target, @breadcrumbs); |
| |
| # 'template' is a marker that's considered private to |
| # the config that had it. |
| delete $inherited_config{template}; |
| |
| map { |
| if (!$combined_inheritance{$_}) { |
| $combined_inheritance{$_} = []; |
| } |
| push @{$combined_inheritance{$_}}, $inherited_config{$_}; |
| } keys %inherited_config; |
| } |
| } |
| |
| # We won't need inherit_from in this target any more, since we've |
| # resolved all the inheritances that lead to this |
| delete $table{$target}->{inherit_from}; |
| |
| # Now is the time to deal with those lists. Here's the place to |
| # decide what shall be done with those lists, all based on the |
| # values of the target we're currently dealing with. |
| # - If a value is a coderef, it will be executed with the list of |
| # inherited values as arguments. |
| # - If the corresponding key doesn't have a value at all or is the |
| # emoty string, the inherited value list will be run through the |
| # default combiner (below), and the result becomes this target's |
| # value. |
| # - Otherwise, this target's value is assumed to be a string that |
| # will simply override the inherited list of values. |
| my $default_combiner = add(" "); |
| |
| my %all_keys = |
| map { $_ => 1 } (keys %combined_inheritance, |
| keys %{$table{$target}}); |
| foreach (sort keys %all_keys) { |
| |
| # Current target doesn't have a value for the current key? |
| # Assign it the default combiner, the rest of this loop body |
| # will handle it just like any other coderef. |
| if (!exists $table{$target}->{$_}) { |
| $table{$target}->{$_} = $default_combiner; |
| } |
| |
| my $valuetype = ref($table{$target}->{$_}); |
| if ($valuetype eq "CODE") { |
| # CODE reference, execute it with the inherited values as |
| # arguments. |
| $table{$target}->{$_} = |
| $table{$target}->{$_}->(@{$combined_inheritance{$_}}); |
| } elsif ($valuetype eq "ARRAY" || $valuetype eq "") { |
| # ARRAY or Scalar, just leave it as is. |
| } else { |
| # Some other type of reference that we don't handle. |
| # Better to abort at this point. |
| die "cannot handle reference type $valuetype," |
| ," found in target $target -> $_\n"; |
| } |
| } |
| |
| # Finally done, return the result. |
| return %{$table{$target}}; |
| } |
| |
| sub usage |
| { |
| print STDERR $usage; |
| print STDERR "\npick os/compiler from:\n"; |
| my $j=0; |
| my $i; |
| my $k=0; |
| foreach $i (sort keys %table) |
| { |
| next if $table{$i}->{template}; |
| next if $i =~ /^debug/; |
| $k += length($i) + 1; |
| if ($k > 78) |
| { |
| print STDERR "\n"; |
| $k=length($i); |
| } |
| print STDERR $i . " "; |
| } |
| foreach $i (sort keys %table) |
| { |
| next if $table{$i}->{template}; |
| next if $i !~ /^debug/; |
| $k += length($i) + 1; |
| if ($k > 78) |
| { |
| print STDERR "\n"; |
| $k=length($i); |
| } |
| print STDERR $i . " "; |
| } |
| print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n"; |
| exit(1); |
| } |
| |
| sub run_dofile() |
| { |
| my $out = shift; |
| my @templates = @_; |
| |
| unlink $out || warn "Can't remove $out, $!" |
| if -f $out; |
| foreach (@templates) { |
| die "Can't open $_, $!" unless -f $_; |
| } |
| my $cmd = "$config{perl} \"-I.\" \"-Mconfigdata\" $dofile -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\""; |
| #print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n"; |
| system($cmd); |
| exit 1 if $? != 0; |
| rename("$out.new", $out) || die "Can't rename $out.new, $!"; |
| } |
| |
| # Configuration printer ############################################## |
| |
| sub print_table_entry |
| { |
| my $target = shift; |
| my %target = resolve_config($target); |
| my $type = shift; |
| |
| # Don't print the templates |
| return if $target{template}; |
| |
| my @sequence = ( |
| "sys_id", |
| "cc", |
| "cflags", |
| "debug_cflags", |
| "release_cflags", |
| "thread_cflag", |
| "unistd", |
| "ld", |
| "lflags", |
| "ex_libs", |
| "debug_lflags", |
| "debug_ex_libs", |
| "release_lflags", |
| "release_ex_libs", |
| "bn_ops", |
| "cpuid_obj", |
| "bn_obj", |
| "ec_obj", |
| "des_obj", |
| "aes_obj", |
| "bf_obj", |
| "md5_obj", |
| "sha1_obj", |
| "cast_obj", |
| "rc4_obj", |
| "rmd160_obj", |
| "rc5_obj", |
| "wp_obj", |
| "cmll_obj", |
| "modes_obj", |
| "padlock_obj", |
| "perlasm_scheme", |
| "dso_scheme", |
| "shared_target", |
| "shared_cflag", |
| "shared_ldflag", |
| "shared_extension", |
| "obj_extension", |
| "exe_extension", |
| "ranlib", |
| "ar", |
| "arflags", |
| "multilib", |
| "build_scheme", |
| ); |
| |
| if ($type eq "TABLE") { |
| print "\n"; |
| print "*** $target\n"; |
| printf "\$%-12s = %s\n", $_, $target{$_} foreach (@sequence); |
| } elsif ($type eq "HASH") { |
| my $largest = |
| length((sort { length($a) <=> length($b) } @sequence)[-1]); |
| print " '$target' => {\n"; |
| foreach (@sequence) { |
| if ($target{$_}) { |
| print " '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n"; |
| } |
| } |
| print " },\n"; |
| } |
| } |
| |
| # Utility routines ################################################### |
| |
| sub which |
| { |
| my($name)=@_; |
| my $path; |
| foreach $path (split /:/, $ENV{PATH}) |
| { |
| if (-f "$path/$name$target{exe_extension}" and -x _) |
| { |
| return "$path/$name$target{exe_extension}" unless ($name eq "perl" and |
| system("$path/$name$target{exe_extension} -e " . '\'exit($]<5.0);\'')); |
| } |
| } |
| } |
| |
| sub quotify { |
| my %processors = ( |
| perl => sub { my $x = shift; |
| $x =~ s/([\\\$\@"])/\\$1/g; |
| return '"'.$x.'"'; }, |
| ); |
| my $for = shift; |
| my $processor = |
| defined($processors{$for}) ? $processors{$for} : sub { shift; }; |
| |
| map { $processor->($_); } @_; |
| } |
| |
| # collect_from_file($filename, $line_concat_cond_re, $line_concat) |
| # $filename is a file name to read from |
| # $line_concat_cond_re is a regexp detecting a line continuation ending |
| # $line_concat is a CODEref that takes care of concatenating two lines |
| sub collect_from_file { |
| my $filename = shift; |
| my $line_concat_cond_re = shift; |
| my $line_concat = shift; |
| |
| open my $fh, $filename || die "unable to read $filename: $!\n"; |
| return sub { |
| my $saved_line = ""; |
| $_ = ""; |
| while (<$fh>) { |
| chomp; |
| if (defined $line_concat) { |
| $_ = $line_concat->($saved_line, $_); |
| $saved_line = ""; |
| } |
| if (defined $line_concat_cond_re && /$line_concat_cond_re/) { |
| $saved_line = $_; |
| next; |
| } |
| return $_; |
| } |
| die "$filename ending with continuation line\n" if $_; |
| close $fh; |
| return undef; |
| } |
| } |
| |
| # collect_from_array($array, $line_concat_cond_re, $line_concat) |
| # $array is an ARRAYref of lines |
| # $line_concat_cond_re is a regexp detecting a line continuation ending |
| # $line_concat is a CODEref that takes care of concatenating two lines |
| sub collect_from_array { |
| my $array = shift; |
| my $line_concat_cond_re = shift; |
| my $line_concat = shift; |
| my @array = (@$array); |
| |
| return sub { |
| my $saved_line = ""; |
| $_ = ""; |
| while (defined($_ = shift @array)) { |
| chomp; |
| if (defined $line_concat) { |
| $_ = $line_concat->($saved_line, $_); |
| $saved_line = ""; |
| } |
| if (defined $line_concat_cond_re && /$line_concat_cond_re/) { |
| $saved_line = $_; |
| next; |
| } |
| return $_; |
| } |
| die "input text ending with continuation line\n" if $_; |
| return undef; |
| } |
| } |
| |
| # collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...) |
| # $lineiterator is a CODEref that delivers one line at a time. |
| # All following arguments are regex/CODEref pairs, where the regexp detects a |
| # line and the CODEref does something with the result of the regexp. |
| sub collect_information { |
| my $lineiterator = shift; |
| my %collectors = @_; |
| |
| while(defined($_ = $lineiterator->())) { |
| chomp; |
| my $found = 0; |
| foreach my $re (keys %collectors) { |
| if ($re ne "OTHERWISE" && /$re/) { |
| $collectors{$re}->($lineiterator); |
| $found = 1; |
| }; |
| } |
| if ($collectors{"OTHERWISE"}) { |
| $collectors{"OTHERWISE"}->($lineiterator, $_) |
| unless $found || !defined $collectors{"OTHERWISE"}; |
| } |
| } |
| } |