blob: 7dc53655a90f5de5823fee22e6caae760af2d343 [file] [log] [blame]
Zachary Ware10c2dba2014-05-09 09:07:50 -05001# Script for preparing OpenSSL for building on Windows.
2# Uses Perl to create nmake makefiles and otherwise prepare the way
3# for building on 32 or 64 bit platforms.
4
5# Script originally authored by Mark Hammond.
6# Major revisions by:
7# Martin v. Löwis
8# Christian Heimes
9# Zachary Ware
10
11# THEORETICALLY, you can:
12# * Unpack the latest OpenSSL release where $(opensslDir) in
13# PCbuild\pyproject.props expects it to be.
14# * Install ActivePerl and ensure it is somewhere on your path.
15# * Run this script with the OpenSSL source dir as the only argument.
16#
17# it should configure OpenSSL such that it is ready to be built by
18# ssl.vcxproj on 32 or 64 bit platforms.
19
20import os
21import re
22import sys
23import shutil
24
25# Find all "foo.exe" files on the PATH.
26def find_all_on_path(filename, extras = None):
27 entries = os.environ["PATH"].split(os.pathsep)
28 ret = []
29 for p in entries:
30 fname = os.path.abspath(os.path.join(p, filename))
31 if os.path.isfile(fname) and fname not in ret:
32 ret.append(fname)
33 if extras:
34 for p in extras:
35 fname = os.path.abspath(os.path.join(p, filename))
36 if os.path.isfile(fname) and fname not in ret:
37 ret.append(fname)
38 return ret
39
40# Find a suitable Perl installation for OpenSSL.
41# cygwin perl does *not* work. ActivePerl does.
42# Being a Perl dummy, the simplest way I can check is if the "Win32" package
43# is available.
44def find_working_perl(perls):
45 for perl in perls:
46 fh = os.popen('"%s" -e "use Win32;"' % perl)
47 fh.read()
48 rc = fh.close()
49 if rc:
50 continue
51 return perl
52 print("Can not find a suitable PERL:")
53 if perls:
54 print(" the following perl interpreters were found:")
55 for p in perls:
56 print(" ", p)
57 print(" None of these versions appear suitable for building OpenSSL")
58 else:
59 print(" NO perl interpreters were found on this machine at all!")
60 print(" Please install ActivePerl and ensure it appears on your path")
61 return None
62
63def create_makefile64(makefile, m32):
64 """Create and fix makefile for 64bit
65
66 Replace 32 with 64bit directories
67 """
68 if not os.path.isfile(m32):
69 return
70 with open(m32) as fin:
71 with open(makefile, 'w') as fout:
72 for line in fin:
73 line = line.replace("=tmp32", "=tmp64")
74 line = line.replace("=out32", "=out64")
75 line = line.replace("=inc32", "=inc64")
76 # force 64 bit machine
77 line = line.replace("MKLIB=lib", "MKLIB=lib /MACHINE:X64")
78 line = line.replace("LFLAGS=", "LFLAGS=/MACHINE:X64 ")
79 # don't link against the lib on 64bit systems
80 line = line.replace("bufferoverflowu.lib", "")
81 fout.write(line)
82 os.unlink(m32)
83
84def fix_makefile(makefile):
85 """Fix some stuff in all makefiles
86 """
87 if not os.path.isfile(makefile):
88 return
89 with open(makefile) as fin:
90 lines = fin.readlines()
91 with open(makefile, 'w') as fout:
92 for line in lines:
93 if line.startswith("PERL="):
94 continue
95 if line.startswith("CP="):
96 line = "CP=copy\n"
97 if line.startswith("MKDIR="):
98 line = "MKDIR=mkdir\n"
99 if line.startswith("CFLAG="):
100 line = line.strip()
101 for algo in ("RC5", "MDC2", "IDEA"):
102 noalgo = " -DOPENSSL_NO_%s" % algo
103 if noalgo not in line:
104 line = line + noalgo
105 line = line + '\n'
106 fout.write(line)
107
108def run_configure(configure, do_script):
109 print("perl Configure "+configure+" no-idea no-mdc2")
110 os.system("perl Configure "+configure+" no-idea no-mdc2")
111 print(do_script)
112 os.system(do_script)
113
114def cmp(f1, f2):
115 bufsize = 1024 * 8
116 with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
117 while True:
118 b1 = fp1.read(bufsize)
119 b2 = fp2.read(bufsize)
120 if b1 != b2:
121 return False
122 if not b1:
123 return True
124
125def copy(src, dst):
126 if os.path.isfile(dst) and cmp(src, dst):
127 return
128 shutil.copy(src, dst)
129
130def prep(arch):
131 if arch == "x86":
132 configure = "VC-WIN32"
133 do_script = "ms\\do_nasm"
134 makefile="ms\\nt.mak"
135 m32 = makefile
136 dirsuffix = "32"
137 elif arch == "amd64":
138 configure = "VC-WIN64A"
139 do_script = "ms\\do_win64a"
140 makefile = "ms\\nt64.mak"
141 m32 = makefile.replace('64', '')
142 dirsuffix = "64"
143 #os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON"
144 else:
145 raise ValueError('Unrecognized platform: %s' % arch)
146
147 # rebuild makefile when we do the role over from 32 to 64 build
148 if arch == "amd64" and os.path.isfile(m32) and not os.path.isfile(makefile):
149 os.unlink(m32)
150
151 # If the ssl makefiles do not exist, we invoke Perl to generate them.
152 # Due to a bug in this script, the makefile sometimes ended up empty
153 # Force a regeneration if it is.
154 if not os.path.isfile(makefile) or os.path.getsize(makefile)==0:
155 print("Creating the makefiles...")
156 sys.stdout.flush()
157 run_configure(configure, do_script)
158
159 if arch == "amd64":
160 create_makefile64(makefile, m32)
161 fix_makefile(makefile)
162 copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch)
163 copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch)
164 else:
165 print(makefile, 'already exists!')
166
167 # If the assembler files don't exist in tmpXX, copy them there
168 if os.path.exists("asm"+dirsuffix):
169 if not os.path.exists("tmp"+dirsuffix):
170 os.mkdir("tmp"+dirsuffix)
171 for f in os.listdir("asm"+dirsuffix):
172 if not f.endswith(".asm"): continue
173 if os.path.isfile(r"tmp%s\%s" % (dirsuffix, f)): continue
174 shutil.copy(r"asm%s\%s" % (dirsuffix, f), "tmp"+dirsuffix)
175
176def main():
177 if len(sys.argv) == 1:
178 print("Not enough arguments: directory containing OpenSSL",
179 "sources must be supplied")
180 sys.exit(1)
181
182 if len(sys.argv) > 2:
183 print("Too many arguments supplied, all we need is the directory",
184 "containing OpenSSL sources")
185 sys.exit(1)
186
187 ssl_dir = sys.argv[1]
188
189 if not os.path.exists(ssl_dir) and os.path.isdir(ssl_dir):
190 print(ssl_dir, "is not an existing directory!")
191 sys.exit(1)
192
193 # perl should be on the path, but we also look in "\perl" and "c:\\perl"
194 # as "well known" locations
195 perls = find_all_on_path("perl.exe", ["\\perl\\bin", "C:\\perl\\bin"])
196 perl = find_working_perl(perls)
197 if perl:
198 print("Found a working perl at '%s'" % (perl,))
199 else:
200 sys.exit(1)
201 sys.stdout.flush()
202
203 # Put our working Perl at the front of our path
204 os.environ["PATH"] = os.path.dirname(perl) + \
205 os.pathsep + \
206 os.environ["PATH"]
207
208 old_cwd = os.getcwd()
209 try:
210 os.chdir(ssl_dir)
211 for arch in ['amd64', 'x86']:
212 prep(arch)
213 finally:
214 os.chdir(old_cwd)
215
216if __name__=='__main__':
217 main()