ยปCore Development>Code coverage>PC/VS8.0/build_ssl.py

Python code coverage for PC/VS8.0/build_ssl.py

#countcontent
1n/a# Script for building the _ssl and _hashlib modules for Windows.
2n/a# Uses Perl to setup the OpenSSL environment correctly
3n/a# and build OpenSSL, then invokes a simple nmake session
4n/a# for the actual _ssl.pyd and _hashlib.pyd DLLs.
5n/a
6n/a# THEORETICALLY, you can:
7n/a# * Unpack the latest SSL release one level above your main Python source
8n/a# directory. It is likely you will already find the zlib library and
9n/a# any other external packages there.
10n/a# * Install ActivePerl and ensure it is somewhere on your path.
11n/a# * Run this script from the PC/VS8.0 directory.
12n/a#
13n/a# it should configure and build SSL, then build the _ssl and _hashlib
14n/a# Python extensions without intervention.
15n/a
16n/a# Modified by Christian Heimes
17n/a# Now this script supports pre-generated makefiles and assembly files.
18n/a# Developers don't need an installation of Perl anymore to build Python. A svn
19n/a# checkout from our svn repository is enough.
20n/a#
21n/a# In Order to create the files in the case of an update you still need Perl.
22n/a# Run build_ssl in this order:
23n/a# python.exe build_ssl.py Release x64
24n/a# python.exe build_ssl.py Release Win32
25n/a
26n/aimport os, sys, re, shutil
27n/a
28n/a# Find all "foo.exe" files on the PATH.
29n/adef find_all_on_path(filename, extras = None):
30n/a entries = os.environ["PATH"].split(os.pathsep)
31n/a ret = []
32n/a for p in entries:
33n/a fname = os.path.abspath(os.path.join(p, filename))
34n/a if os.path.isfile(fname) and fname not in ret:
35n/a ret.append(fname)
36n/a if extras:
37n/a for p in extras:
38n/a fname = os.path.abspath(os.path.join(p, filename))
39n/a if os.path.isfile(fname) and fname not in ret:
40n/a ret.append(fname)
41n/a return ret
42n/a
43n/a# Find a suitable Perl installation for OpenSSL.
44n/a# cygwin perl does *not* work. ActivePerl does.
45n/a# Being a Perl dummy, the simplest way I can check is if the "Win32" package
46n/a# is available.
47n/adef find_working_perl(perls):
48n/a for perl in perls:
49n/a fh = os.popen('"%s" -e "use Win32;"' % perl)
50n/a fh.read()
51n/a rc = fh.close()
52n/a if rc:
53n/a continue
54n/a return perl
55n/a print("Can not find a suitable PERL:")
56n/a if perls:
57n/a print(" the following perl interpreters were found:")
58n/a for p in perls:
59n/a print(" ", p)
60n/a print(" None of these versions appear suitable for building OpenSSL")
61n/a else:
62n/a print(" NO perl interpreters were found on this machine at all!")
63n/a print(" Please install ActivePerl and ensure it appears on your path")
64n/a return None
65n/a
66n/a# Locate the best SSL directory given a few roots to look into.
67n/adef find_best_ssl_dir(sources):
68n/a candidates = []
69n/a for s in sources:
70n/a try:
71n/a # note: do not abspath s; the build will fail if any
72n/a # higher up directory name has spaces in it.
73n/a fnames = os.listdir(s)
74n/a except OSError:
75n/a fnames = []
76n/a for fname in fnames:
77n/a fqn = os.path.join(s, fname)
78n/a if os.path.isdir(fqn) and fname.startswith("openssl-"):
79n/a candidates.append(fqn)
80n/a # Now we have all the candidates, locate the best.
81n/a best_parts = []
82n/a best_name = None
83n/a for c in candidates:
84n/a parts = re.split("[.-]", os.path.basename(c))[1:]
85n/a # eg - openssl-0.9.7-beta1 - ignore all "beta" or any other qualifiers
86n/a if len(parts) >= 4:
87n/a continue
88n/a if parts > best_parts:
89n/a best_parts = parts
90n/a best_name = c
91n/a if best_name is not None:
92n/a print("Found an SSL directory at '%s'" % (best_name,))
93n/a else:
94n/a print("Could not find an SSL directory in '%s'" % (sources,))
95n/a sys.stdout.flush()
96n/a return best_name
97n/a
98n/adef create_makefile64(makefile, m32):
99n/a """Create and fix makefile for 64bit
100n/a
101n/a Replace 32 with 64bit directories
102n/a """
103n/a if not os.path.isfile(m32):
104n/a return
105n/a with open(m32) as fin:
106n/a with open(makefile, 'w') as fout:
107n/a for line in fin:
108n/a line = line.replace("=tmp32", "=tmp64")
109n/a line = line.replace("=out32", "=out64")
110n/a line = line.replace("=inc32", "=inc64")
111n/a # force 64 bit machine
112n/a line = line.replace("MKLIB=lib", "MKLIB=lib /MACHINE:X64")
113n/a line = line.replace("LFLAGS=", "LFLAGS=/MACHINE:X64 ")
114n/a # don't link against the lib on 64bit systems
115n/a line = line.replace("bufferoverflowu.lib", "")
116n/a fout.write(line)
117n/a os.unlink(m32)
118n/a
119n/adef fix_makefile(makefile):
120n/a """Fix some stuff in all makefiles
121n/a """
122n/a if not os.path.isfile(makefile):
123n/a return
124n/a with open(makefile) as fin:
125n/a lines = fin.readlines()
126n/a with open(makefile, 'w') as fout:
127n/a for line in lines:
128n/a if line.startswith("PERL="):
129n/a continue
130n/a if line.startswith("CP="):
131n/a line = "CP=copy\n"
132n/a if line.startswith("MKDIR="):
133n/a line = "MKDIR=mkdir\n"
134n/a if line.startswith("CFLAG="):
135n/a line = line.strip()
136n/a for algo in ("RC5", "MDC2", "IDEA"):
137n/a noalgo = " -DOPENSSL_NO_%s" % algo
138n/a if noalgo not in line:
139n/a line = line + noalgo
140n/a line = line + '\n'
141n/a fout.write(line)
142n/a
143n/adef run_configure(configure, do_script):
144n/a print("perl Configure "+configure+" no-idea no-mdc2")
145n/a os.system("perl Configure "+configure+" no-idea no-mdc2")
146n/a print(do_script)
147n/a os.system(do_script)
148n/a
149n/adef cmp(f1, f2):
150n/a bufsize = 1024 * 8
151n/a with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
152n/a while True:
153n/a b1 = fp1.read(bufsize)
154n/a b2 = fp2.read(bufsize)
155n/a if b1 != b2:
156n/a return False
157n/a if not b1:
158n/a return True
159n/a
160n/adef copy(src, dst):
161n/a if os.path.isfile(dst) and cmp(src, dst):
162n/a return
163n/a shutil.copy(src, dst)
164n/a
165n/adef main():
166n/a build_all = "-a" in sys.argv
167n/a if sys.argv[1] == "Release":
168n/a debug = False
169n/a elif sys.argv[1] == "Debug":
170n/a debug = True
171n/a else:
172n/a raise ValueError(str(sys.argv))
173n/a
174n/a if sys.argv[2] == "Win32":
175n/a arch = "x86"
176n/a configure = "VC-WIN32"
177n/a do_script = "ms\\do_nasm"
178n/a makefile="ms\\nt.mak"
179n/a m32 = makefile
180n/a dirsuffix = "32"
181n/a elif sys.argv[2] == "x64":
182n/a arch="amd64"
183n/a configure = "VC-WIN64A"
184n/a do_script = "ms\\do_win64a"
185n/a makefile = "ms\\nt64.mak"
186n/a m32 = makefile.replace('64', '')
187n/a dirsuffix = "64"
188n/a #os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON"
189n/a else:
190n/a raise ValueError(str(sys.argv))
191n/a
192n/a make_flags = ""
193n/a if build_all:
194n/a make_flags = "-a"
195n/a # perl should be on the path, but we also look in "\perl" and "c:\\perl"
196n/a # as "well known" locations
197n/a perls = find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"])
198n/a perl = find_working_perl(perls)
199n/a if perl:
200n/a print("Found a working perl at '%s'" % (perl,))
201n/a else:
202n/a print("No Perl installation was found. Existing Makefiles are used.")
203n/a sys.stdout.flush()
204n/a # Look for SSL 3 levels up from PC/VS8.0 - ie, same place zlib etc all live.
205n/a ssl_dir = find_best_ssl_dir(("..\\..\\..",))
206n/a if ssl_dir is None:
207n/a sys.exit(1)
208n/a
209n/a old_cd = os.getcwd()
210n/a try:
211n/a os.chdir(ssl_dir)
212n/a # rebuild makefile when we do the role over from 32 to 64 build
213n/a if arch == "amd64" and os.path.isfile(m32) and not os.path.isfile(makefile):
214n/a os.unlink(m32)
215n/a
216n/a # If the ssl makefiles do not exist, we invoke Perl to generate them.
217n/a # Due to a bug in this script, the makefile sometimes ended up empty
218n/a # Force a regeneration if it is.
219n/a if not os.path.isfile(makefile) or os.path.getsize(makefile)==0:
220n/a if perl is None:
221n/a print("Perl is required to build the makefiles!")
222n/a sys.exit(1)
223n/a
224n/a print("Creating the makefiles...")
225n/a sys.stdout.flush()
226n/a # Put our working Perl at the front of our path
227n/a os.environ["PATH"] = os.path.dirname(perl) + \
228n/a os.pathsep + \
229n/a os.environ["PATH"]
230n/a run_configure(configure, do_script)
231n/a if debug:
232n/a print("OpenSSL debug builds aren't supported.")
233n/a #if arch=="x86" and debug:
234n/a # # the do_masm script in openssl doesn't generate a debug
235n/a # # build makefile so we generate it here:
236n/a # os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile)
237n/a
238n/a if arch == "amd64":
239n/a create_makefile64(makefile, m32)
240n/a fix_makefile(makefile)
241n/a copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch)
242n/a copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch)
243n/a
244n/a # If the assembler files don't exist in tmpXX, copy them there
245n/a if perl is None and os.path.exists("asm"+dirsuffix):
246n/a if not os.path.exists("tmp"+dirsuffix):
247n/a os.mkdir("tmp"+dirsuffix)
248n/a for f in os.listdir("asm"+dirsuffix):
249n/a if not f.endswith(".asm"): continue
250n/a if os.path.isfile(r"tmp%s\%s" % (dirsuffix, f)): continue
251n/a shutil.copy(r"asm%s\%s" % (dirsuffix, f), "tmp"+dirsuffix)
252n/a
253n/a # Now run make.
254n/a if arch == "amd64":
255n/a rc = os.system("ml64 -c -Foms\\uptable.obj ms\\uptable.asm")
256n/a if rc:
257n/a print("ml64 assembler has failed.")
258n/a sys.exit(rc)
259n/a
260n/a copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h")
261n/a copy(r"crypto\opensslconf_%s.h" % arch, r"crypto\opensslconf.h")
262n/a
263n/a #makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile)
264n/a makeCommand = "nmake /nologo -f \"%s\"" % makefile
265n/a print("Executing ssl makefiles:", makeCommand)
266n/a sys.stdout.flush()
267n/a rc = os.system(makeCommand)
268n/a if rc:
269n/a print("Executing "+makefile+" failed")
270n/a print(rc)
271n/a sys.exit(rc)
272n/a finally:
273n/a os.chdir(old_cd)
274n/a sys.exit(rc)
275n/a
276n/aif __name__=='__main__':
277n/a main()