Fix indentation
[openssl.git] / util / mk1mf.pl
index 0bcda863c2c83b1a85cb5b38eb1b2cabffa82577..99652aff918c891b8af83aa140643a50a3da086f 100755 (executable)
@@ -2,8 +2,12 @@
 # A bit of an evil hack but it post processes the file ../MINFO which
 # is generated by `make files` in the top directory.
 # This script outputs one mega makefile that has no shell stuff or any
-# funny stuff
-#
+# funny stuff (if the target is not "copy").
+# If the target is "copy", then it tries to create a makefile that can be
+# safely used with the -j flag and that is compatible with the top-level
+# Makefile, in the sense that it uses the same options and assembler files etc.
+
+use Cwd;
 
 $INSTALLTOP="/usr/local/ssl";
 $OPENSSLDIR="/usr/local/ssl";
@@ -13,10 +17,13 @@ $banner="\t\@echo Building OpenSSL";
 
 my $no_static_engine = 1;
 my $engines = "";
+my $otherlibs = "";
 local $zlib_opt = 0;   # 0 = no zlib, 1 = static, 2 = dynamic
 local $zlib_lib = "";
 local $perl_asm = 0;   # 1 to autobuild asm files from perl scripts
 
+my $ex_l_libs = "";
+
 # Options to import from top level Makefile
 
 my %mf_import = (
@@ -25,6 +32,7 @@ my %mf_import = (
        INSTALLTOP     => \$INSTALLTOP,
        OPENSSLDIR     => \$OPENSSLDIR,
        PLATFORM       => \$mf_platform,
+       CC             => \$mf_cc,
        CFLAG          => \$mf_cflag,
        DEPFLAG        => \$mf_depflag,
        CPUID_OBJ      => \$mf_cpuid_asm,
@@ -39,21 +47,27 @@ my %mf_import = (
        SHA1_ASM_OBJ   => \$mf_sha_asm,
        RMD160_ASM_OBJ => \$mf_rmd_asm,
        WP_ASM_OBJ     => \$mf_wp_asm,
-       CMLL_ENC       => \$mf_cm_asm
+       CMLL_ENC       => \$mf_cm_asm,
+       MODES_ASM_OBJ  => \$mf_modes_asm,
+        ENGINES_ASM_OBJ=> \$mf_engines_asm,
+       BASEADDR       => \$baseaddr,
+       FIPSDIR        => \$fipsdir,
+       EC_ASM         => \$mf_ec_asm,
 );
 
-
 open(IN,"<Makefile") || die "unable to open Makefile!\n";
 while(<IN>) {
     my ($mf_opt, $mf_ref);
     while (($mf_opt, $mf_ref) = each %mf_import) {
-       if (/^$mf_opt\s*=\s*(.*)$/) {
+       if (/^$mf_opt\s*=\s*(.*)$/ && !defined($$mfref)) {
           $$mf_ref = $1;
        }
     }
 }
 close(IN);
 
+$debug = 1 if $mf_platform =~ /^debug-/;
+
 die "Makefile is not the toplevel Makefile!\n" if $ssl_version eq "";
 
 $infile="MINFO";
@@ -76,7 +90,8 @@ $infile="MINFO";
        "netware-libc", "CodeWarrior for NetWare - LibC - with WinSock Sockets",
        "netware-libc-bsdsock", "CodeWarrior for NetWare - LibC - with BSD Sockets",
        "default","cc under unix",
-       "auto", "auto detect from top level Makefile"
+       "auto", "auto detect from top level Makefile",
+        "copy", "copy from top level Makefile"
        );
 
 $platform="";
@@ -101,6 +116,7 @@ and [options] can be one of
        just-ssl                                - remove all non-ssl keys/digest
        no-asm                                  - No x86 asm
        no-krb5                                 - No KRB5
+       no-srp                                  - No SRP
        no-ec                                   - No EC
        no-ecdsa                                - No ECDSA
        no-ecdh                                 - No ECDH
@@ -154,7 +170,7 @@ $mkdir="-mkdir" unless defined $mkdir;
 $ranlib="echo ranlib";
 
 $cc=(defined($VARS{'CC'}))?$VARS{'CC'}:'cc';
-$src_dir=(defined($VARS{'SRC'}))?$VARS{'SRC'}:'.';
+$src_dir=(defined($VARS{'SRC'}))?$VARS{'SRC'}: $platform eq 'copy' ? getcwd() : '.';
 $bin_dir=(defined($VARS{'BIN'}))?$VARS{'BIN'}:'';
 
 # $bin_dir.=$o causes a core dump on my sparc :-(
@@ -164,7 +180,8 @@ $NT=0;
 
 push(@INC,"util/pl","pl");
 
-if ($platform eq "auto") {
+if ($platform eq "auto" || $platform eq 'copy') {
+       $orig_platform = $platform;
        $platform = $mf_platform;
        print STDERR "Imported platform $mf_platform\n";
 }
@@ -225,6 +242,8 @@ else
        $cflags.=' -DTERMIO';
        }
 
+$fipsdir =~ s/\//${o}/g;
+
 $out_dir=(defined($VARS{'OUT'}))?$VARS{'OUT'}:$out_def.($debug?".dbg":"");
 $tmp_dir=(defined($VARS{'TMP'}))?$VARS{'TMP'}:$tmp_def.($debug?".dbg":"");
 $inc_dir=(defined($VARS{'INC'}))?$VARS{'INC'}:$inc_def;
@@ -258,14 +277,19 @@ $cflags.=" -DOPENSSL_NO_SOCK" if $no_sock;
 $cflags.=" -DOPENSSL_NO_SSL2" if $no_ssl2;
 $cflags.=" -DOPENSSL_NO_SSL3" if $no_ssl3;
 $cflags.=" -DOPENSSL_NO_TLSEXT" if $no_tlsext;
+$cflags.=" -DOPENSSL_NO_SRP" if $no_srp;
+$cflags.=" -DOPENSSL_NO_CMS" if $no_cms;
 $cflags.=" -DOPENSSL_NO_ERR"  if $no_err;
 $cflags.=" -DOPENSSL_NO_KRB5" if $no_krb5;
 $cflags.=" -DOPENSSL_NO_EC"   if $no_ec;
 $cflags.=" -DOPENSSL_NO_ECDSA" if $no_ecdsa;
 $cflags.=" -DOPENSSL_NO_ECDH" if $no_ecdh;
+$cflags.=" -DOPENSSL_NO_GOST" if $no_gost;
 $cflags.=" -DOPENSSL_NO_ENGINE"   if $no_engine;
 $cflags.=" -DOPENSSL_NO_HW"   if $no_hw;
-
+$cflags.=" -DOPENSSL_FIPS"    if $fips;
+$cflags.=" -DOPENSSL_NO_JPAKE"    if $no_jpake;
+$cflags.=" -DOPENSSL_NO_EC2M"    if $no_ec2m;
 $cflags.= " -DZLIB" if $zlib_opt;
 $cflags.= " -DZLIB_SHARED" if $zlib_opt == 2;
 
@@ -285,6 +309,11 @@ else
 ##else
        { $cflags="$c_flags$cflags" if ($c_flags ne ""); }
 
+if ($orig_platform eq 'copy') {
+    $cflags = $mf_cflag;
+    $cc = $mf_cc;
+}
+
 $ex_libs="$l_flags$ex_libs" if ($l_flags ne "");
 
 
@@ -311,7 +340,7 @@ open(IN,"<$infile") || die "unable to open $infile:$!\n";
 $_=<IN>;
 for (;;)
        {
-       chop;
+       s/\s*$//; # was chop, didn't work in mixture of perls for Windows...
 
        ($key,$val)=/^([^=]+)=(.*)/;
        if ($key eq "RELATIVE_DIRECTORY")
@@ -353,6 +382,12 @@ for (;;)
                $lib=$val;
                $lib =~ s/^.*\/([^\/]+)$/$1/;
                }
+       if ($key eq "LIBNAME" && $no_static_engine)
+               {
+               $lib=$val;
+               $lib =~ s/^.*\/([^\/]+)$/$1/;
+               $otherlibs .= " $lib";
+               }
 
        if ($key eq "EXHEADER")
                { $exheader.=&var_add($dir,$val, 1); }
@@ -370,6 +405,14 @@ for (;;)
        }
 close(IN);
 
+if ($orig_platform eq 'copy')
+       {
+       # Remove opensslconf.h so it doesn't get updated if we configure a
+       # different branch.
+       $exheader =~ s/[^ ]+\/opensslconf.h//;
+       $header =~ s/[^ ]+\/opensslconf.h//;
+       }
+
 if ($shlib)
        {
        $extra_install= <<"EOF";
@@ -393,12 +436,18 @@ else
        \$(CP) \"\$(O_CRYPTO)\" \"\$(INSTALLTOP)${o}lib\"
 EOF
        $ex_libs .= " $zlib_lib" if $zlib_opt == 1;
+       if ($fips)
+               {
+               $build_targets .= " \$(LIB_D)$o$crypto_compat \$(PREMAIN_DSO_EXE)";
+               $ex_l_libs .= " \$(O_FIPSCANISTER)";
+               }
        }
 
 $defs= <<"EOF";
+# N.B. You MUST use -j on FreeBSD.
 # This makefile has been automatically generated from the OpenSSL distribution.
 # This single makefile will build the complete OpenSSL distribution and
-# by default leave the 'intertesting' output files in .${o}out and the stuff
+# by default leave the 'interesting' output files in .${o}out and the stuff
 # that needs deleting in .${o}tmp.
 # The file was generated by running 'make makefile.one', which
 # does a 'make files', which writes all the environment variables from all
@@ -437,34 +486,7 @@ LINK=$link
 LFLAGS=$lflags
 RSC=$rsc
 
-AES_ASM_OBJ=$aes_asm_obj
-AES_ASM_SRC=$aes_asm_src
-BN_ASM_OBJ=$bn_asm_obj
-BN_ASM_SRC=$bn_asm_src
-BNCO_ASM_OBJ=$bnco_asm_obj
-BNCO_ASM_SRC=$bnco_asm_src
-DES_ENC_OBJ=$des_enc_obj
-DES_ENC_SRC=$des_enc_src
-BF_ENC_OBJ=$bf_enc_obj
-BF_ENC_SRC=$bf_enc_src
-CAST_ENC_OBJ=$cast_enc_obj
-CAST_ENC_SRC=$cast_enc_src
-RC4_ENC_OBJ=$rc4_enc_obj
-RC4_ENC_SRC=$rc4_enc_src
-RC5_ENC_OBJ=$rc5_enc_obj
-RC5_ENC_SRC=$rc5_enc_src
-MD5_ASM_OBJ=$md5_asm_obj
-MD5_ASM_SRC=$md5_asm_src
-SHA1_ASM_OBJ=$sha1_asm_obj
-SHA1_ASM_SRC=$sha1_asm_src
-RMD160_ASM_OBJ=$rmd160_asm_obj
-RMD160_ASM_SRC=$rmd160_asm_src
-WHIRLPOOL_ASM_OBJ=$whirlpool_asm_obj
-WHIRLPOOL_ASM_SRC=$whirlpool_asm_src
-CPUID_ASM_OBJ=$cpuid_asm_obj
-CPUID_ASM_SRC=$cpuid_asm_src
-
-# The output directory for everything intersting
+# The output directory for everything interesting
 OUT_D=$out_dir
 # The output directory for all the temporary muck
 TMP_D=$tmp_dir
@@ -481,6 +503,19 @@ MKLIB=$bin_dir$mklib
 MLFLAGS=$mlflags
 ASM=$bin_dir$asm
 
+# FIPS validated module and support file locations
+
+E_PREMAIN_DSO=fips_premain_dso
+
+FIPSDIR=$fipsdir
+BASEADDR=$baseaddr
+FIPSLIB_D=\$(FIPSDIR)${o}lib
+FIPS_PREMAIN_SRC=\$(FIPSLIB_D)${o}fips_premain.c
+O_FIPSCANISTER=\$(FIPSLIB_D)${o}fipscanister.lib
+FIPS_SHA1_EXE=\$(FIPSDIR)${o}bin${o}fips_standalone_sha1${exep}
+PREMAIN_DSO_EXE=\$(BIN_D)${o}fips_premain_dso$exep
+FIPSLINK=\$(PERL) \$(FIPSDIR)${o}bin${o}fipslink.pl
+
 ######################################################
 # You should not need to touch anything below this point
 ######################################################
@@ -513,7 +548,7 @@ SO_CRYPTO= $plib\$(CRYPTO)$so_shlibp
 L_SSL=     \$(LIB_D)$o$plib\$(SSL)$libp
 L_CRYPTO=  \$(LIB_D)$o$plib\$(CRYPTO)$libp
 
-L_LIBS= \$(L_SSL) \$(L_CRYPTO)
+L_LIBS= \$(L_SSL) \$(L_CRYPTO) $ex_l_libs
 
 ######################################################
 # Don't touch anything below this point
@@ -529,7 +564,7 @@ LIBS_DEP=\$(O_CRYPTO) \$(O_SSL)
 EOF
 
 $rules=<<"EOF";
-all: banner \$(TMP_D) \$(BIN_D) \$(TEST_D) \$(LIB_D) \$(INCO_D) headers lib exe
+all: banner \$(TMP_D) \$(BIN_D) \$(TEST_D) \$(LIB_D) \$(INCO_D) headers lib exe $build_targets
 
 banner:
 $banner
@@ -552,8 +587,12 @@ $banner
 \$(INC_D):
        \$(MKDIR) \"\$(INC_D)\"
 
+# This needs to be invoked once, when the makefile is first constructed, or
+# after cleaning.
+init: \$(TMP_D) \$(LIB_D) \$(INC_D) \$(INCO_D) \$(BIN_D) \$(TEST_D) headers
+       \$(PERL) \$(SRC_D)/util/copy-if-different.pl "\$(SRC_D)/crypto/opensslconf.h" "\$(INCO_D)/opensslconf.h"
+
 headers: \$(HEADER) \$(EXHEADER)
-       @
 
 lib: \$(LIBS_DEP) \$(E_SHLIB)
 
@@ -571,11 +610,6 @@ install: all
        \$(CP) apps${o}openssl.cnf \"\$(OPENSSLDIR)\"
 $extra_install
 
-
-test: \$(T_EXE)
-       cd \$(BIN_D)
-       ..${o}ms${o}test
-
 clean:
        \$(RM) \$(TMP_D)$o*.*
 
@@ -583,8 +617,25 @@ vclean:
        \$(RM) \$(TMP_D)$o*.*
        \$(RM) \$(OUT_D)$o*.*
 
+reallyclean:
+       \$(RM) -rf \$(TMP_D)
+       \$(RM) -rf \$(BIN_D)
+       \$(RM) -rf \$(TEST_D)
+       \$(RM) -rf \$(LIB_D)
+       \$(RM) -rf \$(INC_D)
+
 EOF
-    
+
+if ($orig_platform ne 'copy')
+       {
+        $rules .= <<"EOF";
+test: \$(T_EXE)
+       cd \$(BIN_D)
+       ..${o}ms${o}test
+
+EOF
+       }
+
 my $platform_cpp_symbol = "MK1MF_PLATFORM_$platform";
 $platform_cpp_symbol =~ s/-/_/g;
 if (open(IN,"crypto/buildinf.h"))
@@ -614,14 +665,14 @@ open (OUT,">>crypto/buildinf.h") || die "Can't open buildinf.h";
 printf OUT <<EOF;
 #ifdef $platform_cpp_symbol
   /* auto-generated/updated by util/mk1mf.pl for crypto/cversion.c */
-  #define CFLAGS "$cc $cflags"
+  #define CFLAGS "compiler: $cc $cflags"
   #define PLATFORM "$platform"
 EOF
 printf OUT "  #define DATE \"%s\"\n", scalar gmtime();
 printf OUT "#endif\n";
 close(OUT);
 
-# Strip of trailing ' '
+# Strip off trailing ' '
 foreach (keys %lib_obj) { $lib_obj{$_}=&clean_up_ws($lib_obj{$_}); }
 $test=&clean_up_ws($test);
 $e_exe=&clean_up_ws($e_exe);
@@ -645,92 +696,57 @@ $rules.=&do_compile_rule("\$(OBJ_D)",$test,"\$(APP_CFLAGS)");
 $defs.=&do_defs("E_OBJ",$e_exe,"\$(OBJ_D)",$obj);
 $rules.=&do_compile_rule("\$(OBJ_D)",$e_exe,'-DMONOLITH $(APP_CFLAGS)');
 
+# Special case rule for fips_premain_dso
+
+if ($fips)
+       {
+       $rules.=&cc_compile_target("\$(OBJ_D)${o}\$(E_PREMAIN_DSO)$obj",
+               "\$(FIPS_PREMAIN_SRC)",
+               "-DFINGERPRINT_PREMAIN_DSO_LOAD \$(APP_CFLAGS)", "");
+       $rules.=&do_link_rule("\$(PREMAIN_DSO_EXE)","\$(OBJ_D)${o}\$(E_PREMAIN_DSO)$obj \$(CRYPTOOBJ) \$(O_FIPSCANISTER)","","\$(EX_LIBS)", 1);
+       }
+
+sub fix_asm
+       {
+       my($asm, $dir) = @_;
+
+       return '' if $asm eq '';
+
+       $asm = " $asm";
+       $asm =~ s/\s+/ $dir\//g;
+       $asm =~ s/\.o//g;
+       $asm =~ s/^ //;
+
+       return $asm . ' ';
+       }
+
+if ($orig_platform eq 'copy') {
+       $lib_obj{CRYPTO} .= fix_asm($mf_md5_asm, 'crypto/md5');
+       $lib_obj{CRYPTO} .= fix_asm($mf_bn_asm, 'crypto/bn');
+       # cpuid is included by the crypto dir
+       #$lib_obj{CRYPTO} .= fix_asm($mf_cpuid_asm, 'crypto');
+       # AES asm files DON'T end up included by the aes dir itself
+       $lib_obj{CRYPTO} .= fix_asm($mf_aes_asm, 'crypto/aes');
+       $lib_obj{CRYPTO} .= fix_asm($mf_sha_asm, 'crypto/sha');
+       $lib_obj{CRYPTO} .= fix_asm($mf_engines_asm, 'engines');
+       $lib_obj{CRYPTO} .= fix_asm($mf_rc4_asm, 'crypto/rc4');
+       $lib_obj{CRYPTO} .= fix_asm($mf_modes_asm, 'crypto/modes');
+       $lib_obj{CRYPTO} .= fix_asm($mf_ec_asm, 'crypto/ec');
+}
+
 foreach (values %lib_nam)
        {
        $lib_obj=$lib_obj{$_};
        local($slib)=$shlib;
 
-       if (($_ eq "SSL") && $no_ssl2 && $no_ssl3)
-               {
-               $rules.="\$(O_SSL):\n\n"; 
-               next;
-               }
-
-       if (($aes_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s(\S*\/aes_core\S*)/ \$(AES_ASM_OBJ)/;
-               $lib_obj =~ s/\s\S*\/aes_cbc\S*//;
-               $rules.=&do_asm_rule($aes_asm_obj,$aes_asm_src);
-               }
-       if (($bn_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*\/bn_asm\S*/ \$(BN_ASM_OBJ)/;
-               $rules.=&do_asm_rule($bn_asm_obj,$bn_asm_src);
-               }
-       if (($bnco_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj .= "\$(BNCO_ASM_OBJ)";
-               $rules.=&do_asm_rule($bnco_asm_obj,$bnco_asm_src);
-               }
-       if (($des_enc_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*des_enc\S*/ \$(DES_ENC_OBJ)/;
-               $lib_obj =~ s/\s\S*\/fcrypt_b\S*\s*/ /;
-               $rules.=&do_asm_rule($des_enc_obj,$des_enc_src);
-               }
-       if (($bf_enc_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*\/bf_enc\S*/ \$(BF_ENC_OBJ)/;
-               $rules.=&do_asm_rule($bf_enc_obj,$bf_enc_src);
-               }
-       if (($cast_enc_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/(\s\S*\/c_enc\S*)/ \$(CAST_ENC_OBJ)/;
-               $rules.=&do_asm_rule($cast_enc_obj,$cast_enc_src);
-               }
-       if (($rc4_enc_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*\/rc4_enc\S*/ \$(RC4_ENC_OBJ)/;
-               $lib_obj =~ s/\s\S*\/rc4_skey\S*//;
-               $rules.=&do_asm_rule($rc4_enc_obj,$rc4_enc_src);
-               }
-       if (($rc5_enc_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*\/rc5_enc\S*/ \$(RC5_ENC_OBJ)/;
-               $rules.=&do_asm_rule($rc5_enc_obj,$rc5_enc_src);
-               }
-       if (($md5_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s(\S*\/md5_dgst\S*)/ $1 \$(MD5_ASM_OBJ)/;
-               $rules.=&do_asm_rule($md5_asm_obj,$md5_asm_src);
-               }
-       if (($sha1_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s(\S*\/sha1dgst\S*)/ $1 \$(SHA1_ASM_OBJ)/;
-               $rules.=&do_asm_rule($sha1_asm_obj,$sha1_asm_src);
-               }
-       if (($rmd160_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s(\S*\/rmd_dgst\S*)/ $1 \$(RMD160_ASM_OBJ)/;
-               $rules.=&do_asm_rule($rmd160_asm_obj,$rmd160_asm_src);
-               }
-       if (($whirlpool_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s(\S*\/wp_dgst\S*)/ $1 \$(WHIRLPOOL_ASM_OBJ)/;
-               $rules.=&do_asm_rule($whirlpool_asm_obj,$whirlpool_asm_src);
-               }
-       if (($cpuid_asm_obj ne "") && ($_ eq "CRYPTO"))
-               {
-               $lib_obj =~ s/\s\S*\/mem_clr\S*/ \$(CPUID_ASM_OBJ)/;
-               $rules.=&do_asm_rule($cpuid_asm_obj,$cpuid_asm_src);
-               }
        $defs.=&do_defs(${_}."OBJ",$lib_obj,"\$(OBJ_D)",$obj);
        $lib=($slib)?" \$(SHLIB_CFLAGS)".$shlib_ex_cflags{$_}:" \$(LIB_CFLAGS)";
        $rules.=&do_compile_rule("\$(OBJ_D)",$lib_obj{$_},$lib);
        }
 
 # hack to add version info on MSVC
-if (($platform eq "VC-WIN32") || ($platform eq "VC-NT")) {
+if (($platform eq "VC-WIN32") || ($platform eq "VC-WIN64A")
+       || ($platform eq "VC-WIN64I") || ($platform eq "VC-NT")) {
     $rules.= <<"EOF";
 \$(OBJ_D)\\\$(CRYPTO).res: ms\\version32.rc
        \$(RSC) /fo"\$(OBJ_D)\\\$(CRYPTO).res" /d CRYPTO ms\\version32.rc
@@ -749,7 +765,7 @@ foreach (split(/\s+/,$test))
        $rules.=&do_link_rule("\$(TEST_D)$o$t$exep",$tt,"\$(LIBS_DEP)","\$(L_LIBS) \$(EX_LIBS)");
        }
 
-$defs.=&do_defs("E_SHLIB",$engines,"\$(ENG_D)",$shlibp);
+$defs.=&do_defs("E_SHLIB",$engines . $otherlibs,"\$(ENG_D)",$shlibp);
 
 foreach (split(/\s+/,$engines))
        {
@@ -760,9 +776,40 @@ foreach (split(/\s+/,$engines))
 
 
 $rules.= &do_lib_rule("\$(SSLOBJ)","\$(O_SSL)",$ssl,$shlib,"\$(SO_SSL)");
-$rules.= &do_lib_rule("\$(CRYPTOOBJ)","\$(O_CRYPTO)",$crypto,$shlib,"\$(SO_CRYPTO)");
 
-$rules.=&do_link_rule("\$(BIN_D)$o\$(E_EXE)$exep","\$(E_OBJ)","\$(LIBS_DEP)","\$(L_LIBS) \$(EX_LIBS)");
+if ($fips)
+       {
+       if ($shlib)
+               {
+               $rules.= &do_lib_rule("\$(CRYPTOOBJ) \$(O_FIPSCANISTER)",
+                               "\$(O_CRYPTO)", "$crypto",
+                               $shlib, "\$(SO_CRYPTO)", "\$(BASEADDR)");
+               }
+       else
+               {
+               $rules.= &do_lib_rule("\$(CRYPTOOBJ)",
+                       "\$(O_CRYPTO)",$crypto,$shlib,"\$(SO_CRYPTO)", "");
+               $rules.= &do_lib_rule("\$(CRYPTOOBJ) \$(O_FIPSCANISTER)",
+                       "\$(LIB_D)$o$crypto_compat",$crypto,$shlib,"\$(SO_CRYPTO)", "");
+               }
+       }
+       else
+       {
+       $rules.= &do_lib_rule("\$(CRYPTOOBJ)","\$(O_CRYPTO)",$crypto,$shlib,
+                                                       "\$(SO_CRYPTO)");
+       }
+
+foreach (split(" ",$otherlibs))
+       {
+       my $uc = $_;
+       $uc =~ tr /a-z/A-Z/;    
+       $rules.= &do_lib_rule("\$(${uc}OBJ)","\$(ENG_D)$o$_$shlibp", "", $shlib, "");
+
+       }
+
+$rules.=&do_link_rule("\$(BIN_D)$o\$(E_EXE)$exep","\$(E_OBJ)","\$(LIBS_DEP)","\$(L_LIBS) \$(EX_LIBS)", ($fips && !$shlib) ? 2 : 0);
+
+$rules .= get_tests('test/Makefile') if $orig_platform eq 'copy';
 
 print $defs;
 
@@ -799,6 +846,9 @@ sub var_add
        return("") if $no_dsa  && $dir =~ /\/dsa/;
        return("") if $no_dh   && $dir =~ /\/dh/;
        return("") if $no_ec   && $dir =~ /\/ec/;
+       return("") if $no_gost   && $dir =~ /\/ccgost/;
+       return("") if $no_cms  && $dir =~ /\/cms/;
+       return("") if $no_jpake  && $dir =~ /\/jpake/;
        if ($no_des && $dir =~ /\/des/)
                {
                if ($val =~ /read_pwd/)
@@ -828,8 +878,8 @@ sub var_add
        @a=grep(!/^e_camellia$/,@a) if $no_camellia;
        @a=grep(!/^e_seed$/,@a) if $no_seed;
 
-       @a=grep(!/(^s2_)|(^s23_)/,@a) if $no_ssl2;
-       @a=grep(!/(^s3_)|(^s23_)/,@a) if $no_ssl3;
+       #@a=grep(!/(^s2_)|(^s23_)/,@a) if $no_ssl2;
+       #@a=grep(!/(^s3_)|(^s23_)/,@a) if $no_ssl3;
 
        @a=grep(!/(_sock$)|(_acpt$)|(_conn$)|(^pxy_)/,@a) if $no_sock;
 
@@ -853,6 +903,8 @@ sub var_add
        @a=grep(!/(^sha1)|(_sha1$)|(m_dss1$)/,@a) if $no_sha1;
        @a=grep(!/_mdc2$/,@a) if $no_mdc2;
 
+       @a=grep(!/(srp)/,@a) if $no_srp;
+
        @a=grep(!/^engine$/,@a) if $no_engine;
        @a=grep(!/^hw$/,@a) if $no_hw;
        @a=grep(!/(^rsa$)|(^genrsa$)/,@a) if $no_rsa;
@@ -920,7 +972,7 @@ sub do_defs
                $ret.=$t;
                }
        # hack to add version info on MSVC
-       if ($shlib && (($platform eq "VC-WIN32") || ($platform eq "VC-NT")))
+       if ($shlib && (($platform eq "VC-WIN32") || ($platfrom eq "VC-WIN64I") || ($platform eq "VC-WIN64A") || ($platform eq "VC-NT")))
                {
                if ($var eq "CRYPTOOBJ")
                        { $ret.="\$(OBJ_D)\\\$(CRYPTO).res "; }
@@ -940,6 +992,13 @@ sub bname
        return($ret);
        }
 
+# return the leading path
+sub dname
+       {
+       my $ret=shift;
+       $ret =~ s/(^.*)[\\\/][^\\\/]+$/$1/;
+       return($ret);
+       }
 
 ##############################################################
 # do a rule for each file that says 'compile' to new direcory
@@ -947,29 +1006,85 @@ sub bname
 sub do_compile_rule
        {
        local($to,$files,$ex)=@_;
-       local($ret,$_,$n);
-       
+       local($ret,$_,$n,$d,$s);
+
        $files =~ s/\//$o/g if $o ne '/';
        foreach (split(/\s+/,$files))
                {
                $n=&bname($_);
-               $ret.=&cc_compile_target("$to${o}$n$obj","${_}.c",$ex)
+               $d=&dname($_);
+               if (-f "${_}.c")
+                       {
+                       $ret.=&cc_compile_target("$to${o}$n$obj","${_}.c",$ex)
+                       }
+               elsif (-f ($s="${d}${o}asm${o}${n}.pl") or
+                      ($s=~s/sha256/sha512/ and -f $s) or
+                      -f ($s="${d}${o}${n}.pl"))
+                       {
+                       $ret.=&perlasm_compile_target("$to${o}$n$obj",$s,$n);
+                       }
+               elsif (-f ($s="${d}${o}asm${o}${n}.S") or
+                      -f ($s="${d}${o}${n}.S"))
+                       {
+                       $ret.=&Sasm_compile_target("$to${o}$n$obj",$s,$n);
+                       }
+               elsif (defined &special_compile_target and
+                      ($s=special_compile_target($_)))
+                       {
+                       $ret.=$s;
+                       }
+               else    { die "no rule for $_"; }
                }
        return($ret);
        }
 
 ##############################################################
 # do a rule for each file that says 'compile' to new direcory
+sub perlasm_compile_target
+       {
+       my($target,$source,$bname)=@_;
+
+       return platform_perlasm_compile_target($target, $source, $bname)
+           if defined &platform_perlasm_compile_target;
+
+       my($ret);
+
+       $bname =~ s/(.*)\.[^\.]$/$1/;
+       $ret ="\$(TMP_D)$o$bname.asm: $source\n";
+       $ret.="\t\$(PERL) $source $asmtype \$(CFLAG) >\$\@\n\n";
+       $ret.="$target: \$(TMP_D)$o$bname.asm\n";
+       $ret.="\t\$(ASM) $afile\$\@ \$(TMP_D)$o$bname.asm\n\n";
+       return($ret);
+       }
+
+sub Sasm_compile_target
+       {
+       my($target,$source,$bname)=@_;
+       my($ret);
+
+       $bname =~ s/(.*)\.[^\.]$/$1/;
+       $ret ="\$(TMP_D)$o$bname.asm: $source\n";
+       $ret.="\t\$(CC) -E \$(CFLAG) $source >\$\@\n\n";
+       $ret.="$target: \$(TMP_D)$o$bname.asm\n";
+       $ret.="\t\$(ASM) $afile\$\@ \$(TMP_D)$o$bname.asm\n\n";
+       return($ret);
+       }
+
 sub cc_compile_target
        {
-       local($target,$source,$ex_flags)=@_;
+       local($target,$source,$ex_flags, $srcd)=@_;
        local($ret);
        
        $ex_flags.=" -DMK1MF_BUILD -D$platform_cpp_symbol" if ($source =~ /cversion/);
        $target =~ s/\//$o/g if $o ne "/";
        $source =~ s/\//$o/g if $o ne "/";
-       $ret ="$target: \$(SRC_D)$o$source\n\t";
-       $ret.="\$(CC) ${ofile}$target $ex_flags -c \$(SRC_D)$o$source\n\n";
+       $srcd = "\$(SRC_D)$o" unless defined $srcd && $platform ne 'copy';
+       $ret ="$target: $srcd$source\n\t";
+       $ret.="\$(CC)";
+       $ret.= " -MMD" if $orig_platform eq "copy";
+       $ret.= " ${ofile}$target $ex_flags -c $srcd$source\n\n";
+       $target =~ s/\.o$/.d/;
+       $ret.=".sinclude \"$target\"\n\n" if $orig_platform eq "copy";
        return($ret);
        }
 
@@ -1034,17 +1149,22 @@ sub do_copy_rule
                if ($n =~ /bss_file/)
                        { $pp=".c"; }
                else    { $pp=$p; }
-               $ret.="$to${o}$n$pp: \$(SRC_D)$o$_$pp\n\t\$(CP) \"\$(SRC_D)$o$_$pp\" \"$to${o}$n$pp\"\n\n";
+               $ret.="$to${o}$n$pp: \$(SRC_D)$o$_$pp\n\t\$(PERL) \$(SRC_D)${o}util${o}copy-if-different.pl \"\$(SRC_D)$o$_$pp\" \"$to${o}$n$pp\"\n\n";
                }
        return($ret);
        }
 
+# Options picked up from the OPTIONS line in the top level Makefile
+# generated by Configure.
+
 sub read_options
        {
        # Many options are handled in a similar way. In particular
        # no-xxx sets zero or more scalars to 1.
-       # Process these using a hash containing the option name and
-       # reference to the scalars to set.
+       # Process these using the %valid_options hash containing the option
+       # name and reference to the scalars to set. In some cases the option
+       # needs no special handling and can be ignored: this is done by
+       # setting the value to 0.
 
        my %valid_options = (
                "no-rc2" => \$no_rc2,
@@ -1078,20 +1198,28 @@ sub read_options
                "gaswin" => \$gaswin,
                "no-ssl2" => \$no_ssl2,
                "no-ssl3" => \$no_ssl3,
+               "no-ssl3-method" => 0,
                "no-tlsext" => \$no_tlsext,
+               "no-srp" => \$no_srp,
+               "no-cms" => \$no_cms,
+               "no-jpake" => \$no_jpake,
+               "no-ec2m" => \$no_ec2m,
+               "no-ec_nistp_64_gcc_128" => 0,
                "no-err" => \$no_err,
                "no-sock" => \$no_sock,
                "no-krb5" => \$no_krb5,
                "no-ec" => \$no_ec,
                "no-ecdsa" => \$no_ecdsa,
                "no-ecdh" => \$no_ecdh,
+               "no-gost" => \$no_gost,
                "no-engine" => \$no_engine,
                "no-hw" => \$no_hw,
+               "no-rsax" => 0,
                "just-ssl" =>
                        [\$no_rc2, \$no_idea, \$no_des, \$no_bf, \$no_cast,
                          \$no_md2, \$no_sha, \$no_mdc2, \$no_dsa, \$no_dh,
                          \$no_ssl2, \$no_err, \$no_ripemd, \$no_rc5,
-                         \$no_aes, \$no_camellia, \$no_seed],
+                         \$no_aes, \$no_camellia, \$no_seed, \$no_srp],
                "rsaref" => 0,
                "gcc" => \$gcc,
                "debug" => \$debug,
@@ -1099,11 +1227,20 @@ sub read_options
                "shlib" => \$shlib,
                "dll" => \$shlib,
                "shared" => 0,
+               "no-sctp" => 0,
+               "no-srtp" => 0,
                "no-gmp" => 0,
                "no-rfc3779" => 0,
+               "no-montasm" => 0,
                "no-shared" => 0,
+               "no-store" => 0,
                "no-zlib" => 0,
                "no-zlib-dynamic" => 0,
+               "no-ssl-trace" => 0,
+               "no-unit-test" => 0,
+               "no-libunbound" => 0,
+               "no-multiblock" => 0,
+               "fips" => \$fips
                );
 
        if (exists $valid_options{$_})
@@ -1144,6 +1281,18 @@ sub read_options
                if (exists $valid_options{$t})
                        {return 1;}
                return 0;
+               }
+       # experimental-xxx is mostly like enable-xxx, but opensslconf.v
+       # will still set OPENSSL_NO_xxx unless we set OPENSSL_EXPERIMENTAL_xxx.
+       # (No need to fail if we don't know the algorithm -- this is for adventurous users only.)
+       elsif (/^experimental-/)
+               {
+               my $algo, $ALGO;
+               ($algo = $_) =~ s/^experimental-//;
+               ($ALGO = $algo) =~ tr/[a-z]/[A-Z]/;
+
+               $xcflags="-DOPENSSL_EXPERIMENTAL_$ALGO $xcflags";
+               
                }
        elsif (/^--with-krb5-flavor=(.*)$/)
                {