blob: 7658da155f54aa9a68f9948ba3d60b0f24eecb31 [file] [log] [blame]
Christian Heimes4d0ebcc2007-11-15 19:57:43 +00001# 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
16import os, sys, re
17
18# Find all "foo.exe" files on the PATH.
19def 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.
37def 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.
58def 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
89def run_configure(configure, do_script):
90 os.system("perl Configure "+configure)
91 os.system(do_script)
92
93def 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 print(os.path.abspath(os.getcwd()))
137 sys.exit(1)
138
139 old_cd = os.getcwd()
140 try:
141 os.chdir(ssl_dir)
142 # If the ssl makefiles do not exist, we invoke Perl to generate them.
143 # Due to a bug in this script, the makefile sometimes ended up empty
144 # Force a regeneration if it is.
145 if not os.path.isfile(makefile) or os.path.getsize(makefile)==0:
146 print("Creating the makefiles...")
147 sys.stdout.flush()
148 # Put our working Perl at the front of our path
149 os.environ["PATH"] = os.path.dirname(perl) + \
150 os.pathsep + \
151 os.environ["PATH"]
152 run_configure(configure, do_script)
153 if arch=="x86" and debug:
154 # the do_masm script in openssl doesn't generate a debug
155 # build makefile so we generate it here:
156 os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile)
157
158 # Now run make.
159 makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile)
160 print("Executing ssl makefiles:", makeCommand)
161 sys.stdout.flush()
162 rc = os.system(makeCommand)
163 if rc:
164 print("Executing "+makefile+" failed")
165 print(rc)
166 sys.exit(rc)
167 finally:
168 os.chdir(old_cd)
169 sys.exit(rc)
170
171if __name__=='__main__':
172 main()