| # Script for building the _ssl and _hashlib modules for Windows. | 
 | # Uses Perl to setup the OpenSSL environment correctly | 
 | # and build OpenSSL, then invokes a simple nmake session | 
 | # for the actual _ssl.pyd and _hashlib.pyd DLLs. | 
 |  | 
 | # THEORETICALLY, you can: | 
 | # * Unpack the latest SSL release one level above your main Python source | 
 | #   directory.  It is likely you will already find the zlib library and | 
 | #   any other external packages there. | 
 | # * Install ActivePerl and ensure it is somewhere on your path. | 
 | # * Run this script from the PCBuild directory. | 
 | # | 
 | # it should configure and build SSL, then build the _ssl and _hashlib | 
 | # Python extensions without intervention. | 
 |  | 
 | import os, sys, re | 
 |  | 
 | # Find all "foo.exe" files on the PATH. | 
 | def find_all_on_path(filename, extras = None): | 
 |     entries = os.environ["PATH"].split(os.pathsep) | 
 |     ret = [] | 
 |     for p in entries: | 
 |         fname = os.path.abspath(os.path.join(p, filename)) | 
 |         if os.path.isfile(fname) and fname not in ret: | 
 |             ret.append(fname) | 
 |     if extras: | 
 |         for p in extras: | 
 |             fname = os.path.abspath(os.path.join(p, filename)) | 
 |             if os.path.isfile(fname) and fname not in ret: | 
 |                 ret.append(fname) | 
 |     return ret | 
 |  | 
 | # Find a suitable Perl installation for OpenSSL. | 
 | # cygwin perl does *not* work.  ActivePerl does. | 
 | # Being a Perl dummy, the simplest way I can check is if the "Win32" package | 
 | # is available. | 
 | def find_working_perl(perls): | 
 |     for perl in perls: | 
 |         fh = os.popen(perl + ' -e "use Win32;"') | 
 |         fh.read() | 
 |         rc = fh.close() | 
 |         if rc: | 
 |             continue | 
 |         return perl | 
 |     print("Can not find a suitable PERL:") | 
 |     if perls: | 
 |         print(" the following perl interpreters were found:") | 
 |         for p in perls: | 
 |             print(" ", p) | 
 |         print(" None of these versions appear suitable for building OpenSSL") | 
 |     else: | 
 |         print(" NO perl interpreters were found on this machine at all!") | 
 |     print(" Please install ActivePerl and ensure it appears on your path") | 
 |     print("The Python SSL module was not built") | 
 |     return None | 
 |  | 
 | # Locate the best SSL directory given a few roots to look into. | 
 | def find_best_ssl_dir(sources): | 
 |     candidates = [] | 
 |     for s in sources: | 
 |         try: | 
 |             # note: do not abspath s; the build will fail if any | 
 |             # higher up directory name has spaces in it. | 
 |             fnames = os.listdir(s) | 
 |         except os.error: | 
 |             fnames = [] | 
 |         for fname in fnames: | 
 |             fqn = os.path.join(s, fname) | 
 |             if os.path.isdir(fqn) and fname.startswith("openssl-"): | 
 |                 candidates.append(fqn) | 
 |     # Now we have all the candidates, locate the best. | 
 |     best_parts = [] | 
 |     best_name = None | 
 |     for c in candidates: | 
 |         parts = re.split("[.-]", os.path.basename(c))[1:] | 
 |         # eg - openssl-0.9.7-beta1 - ignore all "beta" or any other qualifiers | 
 |         if len(parts) >= 4: | 
 |             continue | 
 |         if parts > best_parts: | 
 |             best_parts = parts | 
 |             best_name = c | 
 |     if best_name is not None: | 
 |         print("Found an SSL directory at '%s'" % (best_name,)) | 
 |     else: | 
 |         print("Could not find an SSL directory in '%s'" % (sources,)) | 
 |     sys.stdout.flush() | 
 |     return best_name | 
 |  | 
 | def run_configure(configure, do_script): | 
 |     os.system("perl Configure "+configure) | 
 |     os.system(do_script) | 
 |  | 
 | def main(): | 
 |     build_all = "-a" in sys.argv | 
 |     if sys.argv[1] == "Release": | 
 |         arch = "x86" | 
 |         debug = False | 
 |         configure = "VC-WIN32" | 
 |         do_script = "ms\\do_masm" | 
 |         makefile = "ms\\nt.mak" | 
 |     elif sys.argv[1] == "Debug": | 
 |         arch = "x86" | 
 |         debug = True | 
 |         configure = "VC-WIN32" | 
 |         do_script = "ms\\do_masm" | 
 |         makefile="ms\\d32.mak" | 
 |     elif sys.argv[1] == "ReleaseItanium": | 
 |         arch = "ia64" | 
 |         debug = False | 
 |         configure = "VC-WIN64I" | 
 |         do_script = "ms\\do_win64i" | 
 |         makefile = "ms\\nt.mak" | 
 |         os.environ["VSEXTCOMP_USECL"] = "MS_ITANIUM" | 
 |     elif sys.argv[1] == "ReleaseAMD64": | 
 |         arch="amd64" | 
 |         debug=False | 
 |         configure = "VC-WIN64A" | 
 |         do_script = "ms\\do_win64a" | 
 |         makefile = "ms\\nt.mak" | 
 |         os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON" | 
 |     make_flags = "" | 
 |     if build_all: | 
 |         make_flags = "-a" | 
 |     # perl should be on the path, but we also look in "\perl" and "c:\\perl" | 
 |     # as "well known" locations | 
 |     perls = find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"]) | 
 |     perl = find_working_perl(perls) | 
 |     if perl is None: | 
 |         sys.exit(1) | 
 |  | 
 |     print("Found a working perl at '%s'" % (perl,)) | 
 |     sys.stdout.flush() | 
 |     # Look for SSL 2 levels up from pcbuild - ie, same place zlib etc all live. | 
 |     ssl_dir = find_best_ssl_dir(("..\\..",)) | 
 |     if ssl_dir is None: | 
 |         sys.exit(1) | 
 |  | 
 |     old_cd = os.getcwd() | 
 |     try: | 
 |         os.chdir(ssl_dir) | 
 |         # If the ssl makefiles do not exist, we invoke Perl to generate them. | 
 |         # Due to a bug in this script, the makefile sometimes ended up empty | 
 |         # Force a regeneration if it is. | 
 |         if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: | 
 |             print("Creating the makefiles...") | 
 |             sys.stdout.flush() | 
 |             # Put our working Perl at the front of our path | 
 |             os.environ["PATH"] = os.path.dirname(perl) + \ | 
 |                                           os.pathsep + \ | 
 |                                           os.environ["PATH"] | 
 |             run_configure(configure, do_script) | 
 |             if arch=="x86" and debug: | 
 |                 # the do_masm script in openssl doesn't generate a debug | 
 |                 # build makefile so we generate it here: | 
 |                 os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) | 
 |  | 
 |         # Now run make. | 
 |         makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) | 
 |         print("Executing ssl makefiles:", makeCommand) | 
 |         sys.stdout.flush() | 
 |         rc = os.system(makeCommand) | 
 |         if rc: | 
 |             print("Executing "+makefile+" failed") | 
 |             print(rc) | 
 |             sys.exit(rc) | 
 |     finally: | 
 |         os.chdir(old_cd) | 
 |     # And finally, we can build the _ssl module itself for Python. | 
 |     defs = "SSL_DIR=\"%s\"" % (ssl_dir,) | 
 |     if debug: | 
 |         defs = defs + " " + "DEBUG=1" | 
 |     if arch in ('amd64', 'ia64'): | 
 |         defs = defs + " EXTRA_CFLAGS=/GS- EXTRA_LIBS=bufferoverflowU.lib" | 
 |     makeCommand = 'nmake /nologo -f _ssl.mak ' + defs + " " + make_flags | 
 |     print("Executing:", makeCommand) | 
 |     sys.stdout.flush() | 
 |     rc = os.system(makeCommand) | 
 |     sys.exit(rc) | 
 |  | 
 | if __name__=='__main__': | 
 |     main() |