Home | History | Annotate | Download | only in VS7.1
      1 # Script for building the _ssl and _hashlib modules for Windows.
      2 # Uses Perl to setup the OpenSSL environment correctly
      3 # and build OpenSSL, then invokes a simple nmake session
      4 # for the actual _ssl.pyd and _hashlib.pyd DLLs.
      5 
      6 # THEORETICALLY, you can:
      7 # * Unpack the latest SSL release one level above your main Python source
      8 #   directory.  It is likely you will already find the zlib library and
      9 #   any other external packages there.
     10 # * Install ActivePerl and ensure it is somewhere on your path.
     11 # * Run this script from the PCBuild directory.
     12 #
     13 # it should configure and build SSL, then build the _ssl and _hashlib
     14 # Python extensions without intervention.
     15 
     16 import os, sys, re
     17 
     18 # Find all "foo.exe" files on the PATH.
     19 def find_all_on_path(filename, extras = None):
     20     entries = os.environ["PATH"].split(os.pathsep)
     21     ret = []
     22     for p in entries:
     23         fname = os.path.abspath(os.path.join(p, filename))
     24         if os.path.isfile(fname) and fname not in ret:
     25             ret.append(fname)
     26     if extras:
     27         for p in extras:
     28             fname = os.path.abspath(os.path.join(p, filename))
     29             if os.path.isfile(fname) and fname not in ret:
     30                 ret.append(fname)
     31     return ret
     32 
     33 # Find a suitable Perl installation for OpenSSL.
     34 # cygwin perl does *not* work.  ActivePerl does.
     35 # Being a Perl dummy, the simplest way I can check is if the "Win32" package
     36 # is available.
     37 def find_working_perl(perls):
     38     for perl in perls:
     39         fh = os.popen(perl + ' -e "use Win32;"')
     40         fh.read()
     41         rc = fh.close()
     42         if rc:
     43             continue
     44         return perl
     45     print "Can not find a suitable PERL:"
     46     if perls:
     47         print " the following perl interpreters were found:"
     48         for p in perls:
     49             print " ", p
     50         print " None of these versions appear suitable for building OpenSSL"
     51     else:
     52         print " NO perl interpreters were found on this machine at all!"
     53     print " Please install ActivePerl and ensure it appears on your path"
     54     print "The Python SSL module was not built"
     55     return None
     56 
     57 # Locate the best SSL directory given a few roots to look into.
     58 def find_best_ssl_dir(sources):
     59     candidates = []
     60     for s in sources:
     61         try:
     62             # note: do not abspath s; the build will fail if any
     63             # higher up directory name has spaces in it.
     64             fnames = os.listdir(s)
     65         except os.error:
     66             fnames = []
     67         for fname in fnames:
     68             fqn = os.path.join(s, fname)
     69             if os.path.isdir(fqn) and fname.startswith("openssl-"):
     70                 candidates.append(fqn)
     71     # Now we have all the candidates, locate the best.
     72     best_parts = []
     73     best_name = None
     74     for c in candidates:
     75         parts = re.split("[.-]", os.path.basename(c))[1:]
     76         # eg - openssl-0.9.7-beta1 - ignore all "beta" or any other qualifiers
     77         if len(parts) >= 4:
     78             continue
     79         if parts > best_parts:
     80             best_parts = parts
     81             best_name = c
     82     if best_name is not None:
     83         print "Found an SSL directory at '%s'" % (best_name,)
     84     else:
     85         print "Could not find an SSL directory in '%s'" % (sources,)
     86     sys.stdout.flush()
     87     return best_name
     88 
     89 def run_configure(configure, do_script):
     90     os.system("perl Configure "+configure)
     91     os.system(do_script)
     92 
     93 def main():
     94     build_all = "-a" in sys.argv
     95     if sys.argv[1] == "Release":
     96         arch = "x86"
     97         debug = False
     98         configure = "VC-WIN32"
     99         do_script = "ms\\do_masm"
    100         makefile = "ms\\nt.mak"
    101     elif sys.argv[1] == "Debug":
    102         arch = "x86"
    103         debug = True
    104         configure = "VC-WIN32"
    105         do_script = "ms\\do_masm"
    106         makefile="ms\\d32.mak"
    107     elif sys.argv[1] == "ReleaseItanium":
    108         arch = "ia64"
    109         debug = False
    110         configure = "VC-WIN64I"
    111         do_script = "ms\\do_win64i"
    112         makefile = "ms\\nt.mak"
    113         os.environ["VSEXTCOMP_USECL"] = "MS_ITANIUM"
    114     elif sys.argv[1] == "ReleaseAMD64":
    115         arch="amd64"
    116         debug=False
    117         configure = "VC-WIN64A"
    118         do_script = "ms\\do_win64a"
    119         makefile = "ms\\nt.mak"
    120         os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON"
    121     make_flags = ""
    122     if build_all:
    123         make_flags = "-a"
    124     # perl should be on the path, but we also look in "\perl" and "c:\\perl"
    125     # as "well known" locations
    126     perls = find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"])
    127     perl = find_working_perl(perls)
    128     if perl is None:
    129         sys.exit(1)
    130 
    131     print "Found a working perl at '%s'" % (perl,)
    132     sys.stdout.flush()
    133     # Look for SSL 2 levels up from pcbuild - ie, same place zlib etc all live.
    134     ssl_dir = find_best_ssl_dir(("..\\..\\..",))
    135     if ssl_dir is None:
    136         sys.exit(1)
    137 
    138     old_cd = os.getcwd()
    139     try:
    140         os.chdir(ssl_dir)
    141         # If the ssl makefiles do not exist, we invoke Perl to generate them.
    142         # Due to a bug in this script, the makefile sometimes ended up empty
    143         # Force a regeneration if it is.
    144         if not os.path.isfile(makefile) or os.path.getsize(makefile)==0:
    145             print "Creating the makefiles..."
    146             sys.stdout.flush()
    147             # Put our working Perl at the front of our path
    148             os.environ["PATH"] = os.path.dirname(perl) + \
    149                                           os.pathsep + \
    150                                           os.environ["PATH"]
    151             run_configure(configure, do_script)
    152             if arch=="x86" and debug:
    153                 # the do_masm script in openssl doesn't generate a debug
    154                 # build makefile so we generate it here:
    155                 os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile)
    156 
    157         # Now run make.
    158         makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile)
    159         print "Executing ssl makefiles:", makeCommand
    160         sys.stdout.flush()
    161         rc = os.system(makeCommand)
    162         if rc:
    163             print "Executing "+makefile+" failed"
    164             print rc
    165             sys.exit(rc)
    166     finally:
    167         os.chdir(old_cd)
    168     # And finally, we can build the _ssl module itself for Python.
    169     defs = "SSL_DIR=\"%s\"" % (ssl_dir,)
    170     if debug:
    171         defs = defs + " " + "DEBUG=1"
    172     if arch in ('amd64', 'ia64'):
    173         defs = defs + " EXTRA_CFLAGS=/GS- EXTRA_LIBS=bufferoverflowU.lib"
    174     makeCommand = 'nmake /nologo -f _ssl.mak ' + defs + " " + make_flags
    175     print "Executing:", makeCommand
    176     sys.stdout.flush()
    177     rc = os.system(makeCommand)
    178     sys.exit(rc)
    179 
    180 if __name__=='__main__':
    181     main()
    182