1 from __future__
import with_statement
2 # Script for building the _ssl and _hashlib modules for Windows.
3 # Uses Perl to setup the OpenSSL environment correctly
4 # and build OpenSSL, then invokes a simple nmake session
5 # for the actual _ssl.pyd and _hashlib.pyd DLLs.
7 # THEORETICALLY, you can:
8 # * Unpack the latest SSL release one level above your main Python source
9 # directory. It is likely you will already find the zlib library and
10 # any other external packages there.
11 # * Install ActivePerl and ensure it is somewhere on your path.
12 # * Run this script from the PCBuild directory.
14 # it should configure and build SSL, then build the _ssl and _hashlib
15 # Python extensions without intervention.
17 # Modified by Christian Heimes
18 # Now this script supports pre-generated makefiles and assembly files.
19 # Developers don't need an installation of Perl anymore to build Python. A svn
20 # checkout from our svn repository is enough.
22 # In Order to create the files in the case of an update you still need Perl.
23 # Run build_ssl in this order:
24 # python.exe build_ssl.py Release x64
25 # python.exe build_ssl.py Release Win32
27 import os
, sys
, re
, shutil
29 # Find all "foo.exe" files on the PATH.
30 def find_all_on_path(filename
, extras
= None):
31 entries
= os
.environ
["PATH"].split(os
.pathsep
)
34 fname
= os
.path
.abspath(os
.path
.join(p
, filename
))
35 if os
.path
.isfile(fname
) and fname
not in ret
:
39 fname
= os
.path
.abspath(os
.path
.join(p
, filename
))
40 if os
.path
.isfile(fname
) and fname
not in ret
:
44 # Find a suitable Perl installation for OpenSSL.
45 # cygwin perl does *not* work. ActivePerl does.
46 # Being a Perl dummy, the simplest way I can check is if the "Win32" package
48 def find_working_perl(perls
):
50 fh
= os
.popen(perl
+ ' -e "use Win32;"')
56 print("Can not find a suitable PERL:")
58 print(" the following perl interpreters were found:")
61 print(" None of these versions appear suitable for building OpenSSL")
63 print(" NO perl interpreters were found on this machine at all!")
64 print(" Please install ActivePerl and ensure it appears on your path")
67 # Locate the best SSL directory given a few roots to look into.
68 def find_best_ssl_dir(sources
):
72 # note: do not abspath s; the build will fail if any
73 # higher up directory name has spaces in it.
74 fnames
= os
.listdir(s
)
78 fqn
= os
.path
.join(s
, fname
)
79 if os
.path
.isdir(fqn
) and fname
.startswith("openssl-"):
80 candidates
.append(fqn
)
81 # Now we have all the candidates, locate the best.
85 parts
= re
.split("[.-]", os
.path
.basename(c
))[1:]
86 # eg - openssl-0.9.7-beta1 - ignore all "beta" or any other qualifiers
89 if parts
> best_parts
:
92 if best_name
is not None:
93 print("Found an SSL directory at '%s'" % (best_name
,))
95 print("Could not find an SSL directory in '%s'" % (sources
,))
99 def create_makefile64(makefile
, m32
):
100 """Create and fix makefile for 64bit
102 Replace 32 with 64bit directories
104 if not os
.path
.isfile(m32
):
106 with
open(m32
) as fin
:
107 with
open(makefile
, 'w') as fout
:
109 line
= line
.replace("=tmp32", "=tmp64")
110 line
= line
.replace("=out32", "=out64")
111 line
= line
.replace("=inc32", "=inc64")
112 # force 64 bit machine
113 line
= line
.replace("MKLIB=lib", "MKLIB=lib /MACHINE:X64")
114 line
= line
.replace("LFLAGS=", "LFLAGS=/MACHINE:X64 ")
115 # don't link against the lib on 64bit systems
116 line
= line
.replace("bufferoverflowu.lib", "")
120 def fix_makefile(makefile
):
121 """Fix some stuff in all makefiles
123 if not os
.path
.isfile(makefile
):
127 if 1: # with open(makefile) as fin:
128 lines
= fin
.readlines()
130 fout
= open(makefile
, 'w')
131 if 1: # with open(makefile, 'w') as fout:
133 if line
.startswith("PERL="):
135 if line
.startswith("CP="):
137 if line
.startswith("MKDIR="):
138 line
= "MKDIR=mkdir\n"
139 if line
.startswith("CFLAG="):
141 for algo
in ("RC5", "MDC2", "IDEA"):
142 noalgo
= " -DOPENSSL_NO_%s" % algo
143 if noalgo
not in line
:
149 def run_configure(configure
, do_script
):
150 print("perl Configure "+configure
)
151 os
.system("perl Configure "+configure
)
156 build_all
= "-a" in sys
.argv
157 if sys
.argv
[1] == "Release":
159 elif sys
.argv
[1] == "Debug":
162 raise ValueError(str(sys
.argv
))
164 if sys
.argv
[2] == "Win32":
166 configure
= "VC-WIN32"
167 do_script
= "ms\\do_nasm"
168 makefile
="ms\\nt.mak"
170 elif sys
.argv
[2] == "x64":
172 configure
= "VC-WIN64A"
173 do_script
= "ms\\do_win64a"
174 makefile
= "ms\\nt64.mak"
175 m32
= makefile
.replace('64', '')
176 #os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON"
178 raise ValueError(str(sys
.argv
))
183 # perl should be on the path, but we also look in "\perl" and "c:\\perl"
184 # as "well known" locations
185 perls
= find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"])
186 perl
= find_working_perl(perls
)
188 print("No Perl installation was found. Existing Makefiles are used.")
190 print("Found a working perl at '%s'" % (perl
,))
192 # Look for SSL 2 levels up from pcbuild - ie, same place zlib etc all live.
193 ssl_dir
= find_best_ssl_dir(("..\\..",))
200 # rebuild makefile when we do the role over from 32 to 64 build
201 if arch
== "amd64" and os
.path
.isfile(m32
) and not os
.path
.isfile(makefile
):
204 # If the ssl makefiles do not exist, we invoke Perl to generate them.
205 # Due to a bug in this script, the makefile sometimes ended up empty
206 # Force a regeneration if it is.
207 if not os
.path
.isfile(makefile
) or os
.path
.getsize(makefile
)==0:
209 print("Perl is required to build the makefiles!")
212 print("Creating the makefiles...")
214 # Put our working Perl at the front of our path
215 os
.environ
["PATH"] = os
.path
.dirname(perl
) + \
218 run_configure(configure
, do_script
)
220 print("OpenSSL debug builds aren't supported.")
221 #if arch=="x86" and debug:
222 # # the do_masm script in openssl doesn't generate a debug
223 # # build makefile so we generate it here:
224 # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile)
227 create_makefile64(makefile
, m32
)
228 fix_makefile(makefile
)
229 shutil
.copy(r
"crypto\buildinf.h", r
"crypto\buildinf_%s.h" % arch
)
230 shutil
.copy(r
"crypto\opensslconf.h", r
"crypto\opensslconf_%s.h" % arch
)
234 rc
= os
.system(r
"ml64 -c -Foms\uptable.obj ms\uptable.asm")
236 print("ml64 assembler has failed.")
239 shutil
.copy(r
"crypto\buildinf_%s.h" % arch
, r
"crypto\buildinf.h")
240 shutil
.copy(r
"crypto\opensslconf_%s.h" % arch
, r
"crypto\opensslconf.h")
242 #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile)
243 makeCommand
= "nmake /nologo -f \"%s\"" % makefile
244 print("Executing ssl makefiles:", makeCommand
)
246 rc
= os
.system(makeCommand
)
248 print("Executing "+makefile
+" failed")
255 if __name__
=='__main__':