blob: d9477deb7d8604c148d57985aa7c57fe8a9bc132 [file] [log] [blame]
Christian Heimesad14d112007-11-17 08:15:27 +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_nasm"
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_nasm"
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 sys.exit(rc)
169
170if __name__=='__main__':
171 main()