Filthy newline drama?
[craw.git] / setup / setup.py
blob442c8603c5fd593ba89834e15245d13ff7afb5ab
1 import subprocess, os, sys, urllib2, platform, shutil, time, winsound, _winreg
3 #All the external sources are defined here:
5 git_url = 'http://msysgit.googlecode.com/files/Git-1.6.3.2-preview20090608.exe'
6 scons_url = 'http://surfnet.dl.sourceforge.net/sourceforge/scons/scons-1.2.0.d20090223.win32.exe'
7 python_url = 'http://www.python.org/ftp/python/2.6.2/python-2.6.2.msi'
9 if len(sys.argv) == 2:
10 mode = sys.argv[1]
11 if mode == 'http':
12 boost_git = 'http://git.gitorious.org/boost/svn.git'
14 nil_git = 'http://repo.or.cz/r/nil.git'
15 ail_git = 'http://repo.or.cz/r/ail.git'
16 syringe_git = 'http://repo.or.cz/r/syringe.git'
17 craw_git = 'http://repo.or.cz/r/craw.git'
19 print 'Using http git URLs instead of the git ones'
20 else:
21 print 'Unknown mode "%s" specified' % mode
22 else:
23 boost_git = 'git://gitorious.org/boost/svn.git'
25 nil_git = 'git://repo.or.cz/nil.git'
26 ail_git = 'git://repo.or.cz/ail.git'
27 syringe_git = 'git://repo.or.cz/syringe.git'
28 craw_git = 'git://repo.or.cz/craw.git'
30 #Functions used by the setup:
32 def is_64_bit():
33 return platform.architecture()[0] == '64bit'
35 def download(url):
36 try:
37 print 'Downloading %s' % url
38 request = urllib2.Request(url)
39 response = urllib2.urlopen(request)
40 data = response.read()
41 return data
42 except:
43 return None
45 def download_file(url, download_path):
46 data = download(url)
47 if data == None:
48 print 'Failed to download %s' % url
49 sys.exit(1)
50 file = open(download_path, 'w+b')
51 file.write(data)
52 file.close()
54 def has_command(command):
55 return len(os.popen(command).read()) > 0
57 def has_git():
58 return has_command('%s --help' % git_path)
60 def has_scons():
61 return has_command('%s --help' % scons_path)
63 def has_bjam():
64 return has_command('boost\\bjam.exe --help')
66 def string_filter(filter_string, lines):
67 return filter(lambda line: line.find(filter_string) != -1, lines)
69 def make_directory(directory):
70 try:
71 os.mkdir(directory)
72 except:
73 pass
75 def copy_binary(source):
76 try:
77 target_directory = 'binaries'
78 make_directory(target_directory)
79 destination = os.path.join(target_directory, os.path.basename(source))
80 shutil.copy(source, destination)
81 except:
82 pass
84 def get_site_packages():
85 target = 'site-packages'
86 for path in sys.path:
87 if len(path) > len(target) and path[- len(target) : ] == target:
88 return path
89 return None
91 def get_wow_node():
92 wow = ''
93 if is_64_bit():
94 wow = 'Wow6432Node\\'
95 return wow
97 def get_git_path():
98 try:
99 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\%sMicrosoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1' % get_wow_node())
100 value, type = _winreg.QueryValueEx(key, 'InstallLocation')
101 return '"%s"' % os.path.join(value, 'bin', 'git.exe')
102 except:
103 return None
105 def get_scons_path():
106 target = 'lib'
107 for path in sys.path:
108 if os.path.basename(path).lower() == target:
109 return os.path.join(path[0 : - len(target)], 'Scripts', 'scons.bat')
110 return None
112 def get_python_path():
113 sources = [_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE]
114 for source in sources:
115 try:
116 key = _winreg.OpenKey(source, 'Software\\%sPython\\PythonCore\\2.6\\InstallPath' % get_wow_node())
117 value, type = _winreg.QueryValueEx(key, '')
118 return value
119 except:
120 continue
121 return None
123 def execute(command):
124 print 'Executing [%s] in directory %s' % (command, os.getcwd())
125 return os.system(command)
127 def clone(url, diretory):
128 command = '%s clone %s %s' % (git_path, url, diretory)
129 execute(command)
131 def pull(directory):
132 os.chdir(directory)
133 command = '%s pull' % git_path
134 execute(command)
135 os.chdir('..')
137 def git(url, directory):
138 clone(url, directory)
139 pull(directory)
141 def vcvars():
142 try:
143 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\%sMicrosoft\\VisualStudio\\9.0\\Setup' % get_wow_node())
144 value, type = _winreg.QueryValueEx(key, 'Dbghelp_path')
145 path = value + '..\\..\\VC\\bin\\vcvars32.bat'
146 #execute('"%s"' % path)
147 return path
148 except:
149 return None
151 def vcvars_check():
152 print 'Checking if the Microsoft Visual C++ environment is set up'
153 path = vcvars()
154 if path == None:
155 print 'Unable to locate the Visual C++ 9.0 installation to get the path to vcvars32.bat!'
156 sys.exit(1)
157 if not has_command('cl'):
158 print 'The Microsoft Visual C++ environment has not been set up!'
159 print 'You need to manually execute the following batch file in this prompt:'
160 print '"%s"' % path
161 sys.exit(1)
163 def setup_git():
164 global git_path
165 git_path = 'git'
166 if has_git():
167 return
169 git_path = get_git_path()
170 if git_path != None:
171 return
173 print 'Setting up msysgit'
174 target_directory = 'git'
175 url = git_url
176 path = os.path.join(target_directory, os.path.basename(url))
177 make_directory(target_directory)
178 download_file(url, path)
179 print 'Successfully downloaded the msysgit setup to %s, running it' % path
180 execute(path)
181 print 'Setup has finished'
183 git_path = get_git_path()
184 if git_path == None:
185 print 'Fatal error: I was unable to detect msysgit in the registry'
186 sys.exit(1)
188 def brutal_removal(target):
189 execute('rmdir /q /s %s' % target)
191 def setup_nil():
192 print 'Setting up the nil general purpose library for Python'
193 target = 'nil'
194 git(nil_git, target)
195 path = os.path.join(get_site_packages(), target)
196 print 'Creating a symbolic link to the library at %s' % path
197 source = '%s\\%s' % (target, target)
198 if execute('mklink /D %s %s' % (path, source)) != 0:
199 print 'Failed to create symbolic link, this is probably not Vista/Windows 7'
200 print 'Deleting the old library and moving the new one there'
201 try:
202 print 'Removing old entry %s' % path
203 brutal_removal(target)
204 brutal_removal(path)
205 git(nil_git, target)
206 except:
207 pass
208 print 'Moving %s to %s' % (source, path)
209 try:
210 shutil.move(source, path)
211 except:
212 print 'Failed to install nil library!'
213 sys.exit(1)
215 def setup_scons():
216 global scons_path
217 scons_path = get_scons_path()
218 if scons_path == None:
219 print 'Unable to get the Python library directory to determine the SCons path'
220 sys.exit(1)
222 if has_scons():
223 return
225 print 'Setting up the SCons building system (written in Python)'
226 target_directory = 'scons'
227 url = scons_url
228 path = os.path.join(target_directory, os.path.basename(url))
229 make_directory(target_directory)
230 download_file(url, path)
231 print 'Successfully downloaded the SCons setup to %s, running it' % path
232 execute(path)
233 print 'Setup has finished'
235 def setup_boost():
236 print 'Setting up the mighty boost C++ library'
237 target_directory = 'boost'
239 git(boost_git, target_directory)
241 os.chdir(target_directory)
243 bjam_binary = 'bjam.exe'
245 execute(vcvars())
247 if not os.path.exists(bjam_binary):
248 print 'Compiling bjam'
249 execute('bootstrap.bat')
250 if not os.path.exists(bjam_binary):
251 sys.exit('Failed to build bjam.')
252 #download_file(prebuilt_bjam_url, bjam_binary)
254 print 'Compiling boost'
255 cpus = int(os.environ.get('NUMBER_OF_PROCESSORS', 2))
256 print 'Number of CPUs detected: %d' % cpus
257 execute('%s toolset=%s variant=release threading=multi runtime-link=static link=static stage -j %d --without-graph --without-graph_parallel --without-iostreams --without-math --without-mpi --without-python --without-program_options --without-python --without-serialization --without-signals --without-test --without-wave' % (bjam_binary, toolset, cpus))
258 os.chdir('..')
260 def setup_ail():
261 print 'Setting up the ail C++ general purpose library'
262 target_directory = 'ail'
263 git(ail_git, target_directory)
264 os.chdir(target_directory)
265 execute('%s boost=..\\..\\boost' % scons_path)
266 os.chdir('..')
268 def setup_syringe():
269 print 'Setting up the syringe injection tool'
271 target = 'syringe'
272 git(syringe_git, target)
273 os.chdir(target)
274 execute('%s boost=..\\..\\boost ail=..\\..\\ail ail_lib=..\\..\\ail\\build\\ail.lib' % scons_path)
275 os.chdir('..')
276 copy_binary('%s\\build\\%s.exe' % (target, target))
278 def setup_python():
279 print 'Setting up the 32-bit version of Python (the 64-bit library/DLL is of no use to us because Diablo II is 32-bit)'
281 target_directory = 'python'
282 url = python_url
283 base = os.path.basename(url)
284 path = os.path.join(target_directory, base)
285 make_directory(target_directory)
286 download_file(url, path)
287 print 'Successfully downloaded the Python 32-bit setup to %s, attempting to perform an unattended MSI installation' % path
288 execute('msiexec /package %s\\%s /passive' % (target_directory, base))
289 print 'Setup has finished'
291 def setup_craw():
292 print 'Setting up the Charles Romley Alder Wright (short C.R.A.W.) Diablo II module'
294 target = 'craw'
295 git(craw_git, target)
297 python_path = get_python_path()
298 if python_path == None:
299 setup_python()
300 python_path = get_python_path()
301 if python_path == None:
302 print 'Unable to detect the 32-bit installation of Python 2.6'
303 sys.exit(1)
305 os.chdir(target)
306 execute('%s boost=..\\..\\boost boost_lib=..\\..\\boost\\stage\\lib ail=..\\..\\ail ail_lib=..\\ail\\build\\ail.lib python=%s' % (scons_path, python_path))
307 os.chdir('..')
308 copy_binary('%s\\build\\%s.dll' % (target, target))
310 toolset = 'msvc-9.0'
312 start = time.time()
314 vcvars_check()
315 setup_git()
316 setup_nil()
317 setup_scons()
318 setup_boost()
319 setup_ail()
320 setup_syringe()
321 setup_craw()
323 seconds_per_minute = 60
324 seconds_passed = int(time.time() - start)
325 print 'Setup finished after %d:%02d minute(s)' % (seconds_passed / seconds_per_minute, seconds_passed % seconds_per_minute)
326 winsound.MessageBeep()