/PC/VC6/build_ssl.py

http://unladen-swallow.googlecode.com/ · Python · 202 lines · 148 code · 14 blank · 40 comment · 47 complexity · e8232f62dfc6c99f055ff68fc6501805 MD5 · raw file

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