source: issm/trunk-jpl/externalpackages/petsc-dev/src/config/BuildSystem/script.py@ 11896

Last change on this file since 11896 was 11896, checked in by habbalf, 13 years ago

petsc-dev : Petsc development code in external packages. Mercurial updates

File size: 17.3 KB
Line 
1import sys
2if not hasattr(sys, 'version_info'):
3 print '*** Python version 1 is not supported. Please get the latest version from www.python.org ***'
4 sys.exit(4)
5
6import cPickle
7
8try:
9 import subprocess
10 USE_SUBPROCESS = 1
11except ImportError:
12 USE_SUBPROCESS = 0
13
14# Some features related to detecting login failures cannot be easily
15# implemented with the 'subprocess' module. Disable it for now ...
16USE_SUBPROCESS = 0
17# In Python 2.6 and above, the 'popen2' module is deprecated
18if sys.version_info[:2] >= (2, 6) and not USE_SUBPROCESS:
19 import warnings
20 warnings.filterwarnings('ignore', category=DeprecationWarning, module=__name__)
21
22import nargs
23useThreads = nargs.Arg.findArgument('useThreads', sys.argv[1:])
24if useThreads is None:
25 useThreads = 1
26else:
27 useThreads = int(useThreads)
28
29useSelect = nargs.Arg.findArgument('useSelect', sys.argv[1:])
30if useSelect is None:
31 useSelect = 1
32else:
33 useSelect = int(useSelect)
34
35import logger
36
37class Script(logger.Logger):
38 def __init__(self, clArgs = None, argDB = None, log = None):
39 self.checkPython()
40 logger.Logger.__init__(self, clArgs, argDB, log)
41 self.shell = '/bin/sh'
42 self.showHelp = 1
43 return
44
45 def hasHelpFlag(self):
46 '''Decide whether to display the help message and exit'''
47 import nargs
48
49 if not self.showHelp:
50 return 0
51 if nargs.Arg.findArgument('help', self.clArgs) is None and nargs.Arg.findArgument('h', self.clArgs) is None:
52 return 0
53 return 1
54
55 def setupArguments(self, argDB):
56 '''This method now also creates the help and action logs'''
57 import help
58
59 argDB = logger.Logger.setupArguments(self, argDB)
60
61 self.help = help.Help(argDB)
62 self.help.title = 'Script Help'
63
64 self.actions = help.Info(argDB)
65 self.actions.title = 'Script Actions'
66
67 self.setupHelp(self.help)
68 return argDB
69
70 def setupHelp(self, help):
71 '''This method should be overidden to provide help for arguments'''
72 import nargs
73
74 help.addArgument('Script', '-help', nargs.ArgBool(None, 0, 'Print this help message', isTemporary = 1), ignoreDuplicates = 1)
75 help.addArgument('Script', '-h', nargs.ArgBool(None, 0, 'Print this help message', isTemporary = 1), ignoreDuplicates = 1)
76 return help
77
78 def setup(self):
79 ''' This method checks to see whether help was requested'''
80 if hasattr(self, '_setup'):
81 return
82 logger.Logger.setup(self)
83 self._setup = 1
84 if self.hasHelpFlag():
85 if self.argDB.target == ['default']:
86 sections = None
87 else:
88 sections = self.argDB.target
89 self.help.output(sections = sections)
90 sys.exit()
91 return
92
93 def cleanup(self):
94 '''This method outputs the action log'''
95 self.actions.output(self.log)
96 return
97
98 def checkPython(self):
99 if not hasattr(sys, 'version_info') or float(sys.version_info[0]) != 2 or float(sys.version_info[1]) < 4:
100 raise RuntimeError('BuildSystem requires Python2 version 2.4 or higher. Get Python at http://www.python.org')
101 return
102
103 def getModule(root, name):
104 '''Retrieve a specific module from the directory root, bypassing the usual paths'''
105 import imp
106
107 (fp, pathname, description) = imp.find_module(name, [root])
108 try:
109 return imp.load_module(name, fp, pathname, description)
110 finally:
111 if fp: fp.close()
112 return
113 getModule = staticmethod(getModule)
114
115 def importModule(moduleName):
116 '''Import the named module, and return the module object
117 - Works properly for fully qualified names'''
118 module = __import__(moduleName)
119 components = moduleName.split('.')
120 for comp in components[1:]:
121 module = getattr(module, comp)
122 return module
123 importModule = staticmethod(importModule)
124
125 if USE_SUBPROCESS:
126
127 def runShellCommand(command, log=None, cwd=None):
128 Popen = subprocess.Popen
129 PIPE = subprocess.PIPE
130 if log: log.write('Executing: %s\n' % (command,))
131 pipe = Popen(command, cwd=cwd, stdin=None, stdout=PIPE, stderr=PIPE,
132 bufsize=-1, shell=True, universal_newlines=True)
133 (out, err) = pipe.communicate()
134 ret = pipe.returncode
135 return (out, err, ret)
136
137 else:
138
139 def openPipe(command):
140 '''We need to use the asynchronous version here since we want to avoid blocking reads'''
141 import popen2
142
143 pipe = None
144 if hasattr(popen2, 'Popen3'):
145 pipe = popen2.Popen3(command, 1)
146 input = pipe.tochild
147 output = pipe.fromchild
148 err = pipe.childerr
149 else:
150 import os
151 (input, output, err) = os.popen3(command)
152 return (input, output, err, pipe)
153 openPipe = staticmethod(openPipe)
154
155 def runShellCommand(command, log = None, cwd = None):
156 import select, os
157
158 ret = None
159 out = ''
160 err = ''
161 loginError = 0
162 if cwd is not None:
163 oldpath = os.getcwd()
164 os.chdir(cwd)
165 if log: log.write('Executing: %s\n' % (command,))
166 (input, output, error, pipe) = Script.openPipe(command)
167 if cwd is not None:
168 os.chdir(oldpath)
169 input.close()
170 if useSelect:
171 outputClosed = 0
172 errorClosed = 0
173 lst = [output, error]
174 while 1:
175 ready = select.select(lst, [], [])
176 if len(ready[0]):
177 if error in ready[0]:
178 msg = error.readline()
179 if msg:
180 err += msg
181 else:
182 errorClosed = 1
183 lst.remove(error)
184 if output in ready[0]:
185 msg = output.readline()
186 if msg:
187 out += msg
188 else:
189 outputClosed = 1
190 lst.remove(output)
191 if out.find('password:') >= 0 or err.find('password:') >= 0:
192 loginError = 1
193 break
194 if outputClosed and errorClosed:
195 break
196 else:
197 out = output.read()
198 err = error.read()
199 output.close()
200 error.close()
201 if pipe:
202 # We would like the NOHANG argument here
203 ret = pipe.wait()
204 if loginError:
205 raise RuntimeError('Could not login to site')
206 return (out, err, ret)
207
208 runShellCommand = staticmethod(runShellCommand)
209
210 def defaultCheckCommand(command, status, output, error):
211 '''Raise an error if the exit status is nonzero'''
212 if status: raise RuntimeError('Could not execute "%s":\n%s' % (command,output+error))
213 defaultCheckCommand = staticmethod(defaultCheckCommand)
214
215 def executeShellCommand(command, checkCommand = None, timeout = 600.0, log = None, lineLimit = 0, cwd=None):
216 '''Execute a shell command returning the output, and optionally provide a custom error checker
217 - This returns a tuple of the (output, error, statuscode)'''
218 if not checkCommand:
219 checkCommand = Script.defaultCheckCommand
220 if log is None:
221 log = logger.Logger.defaultLog
222 def logOutput(log, output):
223 import re
224 # get rid of multiple blank lines
225 output = re.sub('\n[\n]*','\n', output)
226 if lineLimit:
227 output = '\n'.join(output.split('\n')[:lineLimit])
228 log.write('sh: '+output+'\n')
229 return output
230 def runInShell(command, log, cwd):
231 if useThreads:
232 import threading
233 class InShell(threading.Thread):
234 def __init__(self):
235 threading.Thread.__init__(self)
236 self.name = 'Shell Command'
237 self.setDaemon(1)
238 def run(self):
239 (self.output, self.error, self.status) = ('', '', -1) # So these fields exist even if command fails with no output
240 (self.output, self.error, self.status) = Script.runShellCommand(command, log, cwd)
241 thread = InShell()
242 thread.start()
243 thread.join(timeout)
244 if thread.isAlive():
245 error = 'Runaway process exceeded time limit of '+str(timeout)+'s\n'
246 log.write(error)
247 return ('', error, -1)
248 else:
249 return (thread.output, thread.error, thread.status)
250 else:
251 return Script.runShellCommand(command, log, cwd)
252
253 log.write('sh: %s\n' % (command,))
254 (output, error, status) = runInShell(command, log, cwd)
255 output = logOutput(log, output)
256 checkCommand(command, status, output, error)
257 return (output, error, status)
258 executeShellCommand = staticmethod(executeShellCommand)
259
260 def loadConfigure(self, argDB = None):
261 if argDB is None:
262 argDB = self.argDB
263 if not 'configureCache' in argDB:
264 self.logPrint('No cached configure in RDict at '+str(argDB.saveFilename))
265 return None
266 try:
267 cache = argDB['configureCache']
268 framework = cPickle.loads(cache)
269 framework.framework = framework
270 framework.argDB = argDB
271 self.logPrint('Loaded configure to cache: size '+str(len(cache)))
272 except cPickle.UnpicklingError, e:
273 framework = None
274 self.logPrint('Invalid cached configure: '+str(e))
275 return framework
276
277import args
278
279class LanguageProcessor(args.ArgumentProcessor):
280 def __init__(self, clArgs = None, argDB = None, framework = None, versionControl = None):
281 self.languageModule = {}
282 self.preprocessorObject = {}
283 self.compilerObject = {}
284 self.linkerObject = {}
285 self.sharedLinkerObject = {}
286 self.dynamicLinkerObject = {}
287 self.framework = framework
288 self.versionControl = versionControl
289 args.ArgumentProcessor.__init__(self, clArgs, argDB)
290 self.outputFiles = {}
291 self.modulePath = 'config.compile'
292 return
293
294 def getCompilers(self):
295 if self.framework is None:
296 return
297 return self.framework.require('config.compilers', None)
298 compilers = property(getCompilers, doc = 'The config.compilers configure object')
299 def getLibraries(self):
300 if self.framework is None:
301 return
302 return self.framework.require('config.libraries', None)
303 libraries = property(getLibraries, doc = 'The config.libraries configure object')
304
305 def __getstate__(self, d = None):
306 '''We only want to pickle the language module names and output files. The other objects are set by configure.'''
307 if d is None:
308 d = args.ArgumentProcessor.__getstate__(self)
309 if 'languageModule' in d:
310 d['languageModule'] = dict([(lang,mod._loadName) for lang,mod in d['languageModule'].items()])
311 for member in ['preprocessorObject', 'compilerObject', 'linkerObject', 'sharedLinkerObject', 'dynamicLinkerObject', 'framework']:
312 if member in d:
313 del d[member]
314 return d
315
316 def __setstate__(self, d):
317 '''We must create the language modules'''
318 args.ArgumentProcessor.__setstate__(self, d)
319 self.__dict__.update(d)
320 [self.getLanguageModule(language, moduleName) for language,moduleName in self.languageModule.items()]
321 self.preprocessorObject = {}
322 self.compilerObject = {}
323 self.linkerObject = {}
324 self.sharedLinkerObject = {}
325 self.dynamicLinkerObject = {}
326 return
327
328 def setArgDB(self, argDB):
329 args.ArgumentProcessor.setArgDB(self, argDB)
330 for obj in self.preprocessorObject.values():
331 if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
332 obj.argDB = argDB
333 for obj in self.compilerObject.values():
334 if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
335 obj.argDB = argDB
336 for obj in self.linkerObject.values():
337 if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
338 obj.argDB = argDB
339 for obj in self.sharedLinkerObject.values():
340 if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
341 obj.argDB = argDB
342 for obj in self.dynamicLinkerObject.values():
343 if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
344 obj.argDB = argDB
345 if not self.compilers is None:
346 self.compilers.argDB = argDB
347 for obj in self.preprocessorObject.values():
348 if hasattr(obj, 'configCompilers'):
349 obj.configCompilers.argDB = argDB
350 for obj in self.compilerObject.values():
351 if hasattr(obj, 'configCompilers'):
352 obj.configCompilers.argDB = argDB
353 for obj in self.linkerObject.values():
354 if hasattr(obj, 'configCompilers'):
355 obj.configCompilers.argDB = argDB
356 for obj in self.sharedLinkerObject.values():
357 if hasattr(obj, 'configCompilers'):
358 obj.configCompilers.argDB = argDB
359 for obj in self.dynamicLinkerObject.values():
360 if hasattr(obj, 'configCompilers'):
361 obj.configCompilers.argDB = argDB
362 if not self.libraries is None:
363 self.libraries.argDB = argDB
364 for obj in self.linkerObject.values():
365 if hasattr(obj, 'configLibraries'):
366 obj.configLibraries.argDB = argDB
367 for obj in self.sharedLinkerObject.values():
368 if hasattr(obj, 'configLibraries'):
369 obj.configLibraries.argDB = argDB
370 for obj in self.dynamicLinkerObject.values():
371 if hasattr(obj, 'configLibraries'):
372 obj.configLibraries.argDB = argDB
373 return
374 argDB = property(args.ArgumentProcessor.getArgDB, setArgDB, doc = 'The RDict argument database')
375
376 def getLanguageModule(self, language, moduleName = None):
377 '''Return the module associated with operations for a given language
378 - Giving a moduleName explicitly forces a reimport'''
379 if not language in self.languageModule or not moduleName is None:
380 try:
381 if moduleName is None:
382 moduleName = self.modulePath+'.'+language
383 module = __import__(moduleName)
384 except ImportError, e:
385 if not moduleName is None:
386 self.logPrint('Failure to find language module: '+str(e))
387 try:
388 moduleName = self.modulePath+'.'+language
389 module = __import__(moduleName)
390 except ImportError, e:
391 self.logPrint('Failure to find language module: '+str(e))
392 moduleName = 'config.compile.'+language
393 module = __import__(moduleName)
394 components = moduleName.split('.')
395 for component in components[1:]:
396 module = getattr(module, component)
397 module._loadName = moduleName
398 self.languageModule[language] = module
399 return self.languageModule[language]
400
401 def getPreprocessorObject(self, language):
402 if not language in self.preprocessorObject:
403 self.preprocessorObject[language] = self.getLanguageModule(language).Preprocessor(self.argDB)
404 self.preprocessorObject[language].setup()
405 if not self.compilers is None:
406 self.preprocessorObject[language].configCompilers = self.compilers
407 if not self.versionControl is None:
408 self.preprocessorObject[language].versionControl = self.versionControl
409 return self.preprocessorObject[language]
410
411 def setPreprocessorObject(self, language, preprocessor):
412 self.preprocessorObject[language] = preprocessor
413 return self.getPreprocessorObject(language)
414
415 def getCompilerObject(self, language):
416 if not language in self.compilerObject:
417 self.compilerObject[language] = self.getLanguageModule(language).Compiler(self.argDB)
418 self.compilerObject[language].setup()
419 if not self.compilers is None:
420 self.compilerObject[language].configCompilers = self.compilers
421 if not self.versionControl is None:
422 self.compilerObject[language].versionControl = self.versionControl
423 return self.compilerObject[language]
424
425 def setCompilerObject(self, language, compiler):
426 self.compilerObject[language] = compiler
427 return self.getCompilerObject(language)
428
429 def getLinkerObject(self, language):
430 if not language in self.linkerObject:
431 self.linkerObject[language] = self.getLanguageModule(language).Linker(self.argDB)
432 self.linkerObject[language].setup()
433 if not self.compilers is None:
434 self.linkerObject[language].configCompilers = self.compilers
435 if not self.libraries is None:
436 self.linkerObject[language].configLibraries = self.libraries
437 if not self.versionControl is None:
438 self.linkerObject[language].versionControl = self.versionControl
439 return self.linkerObject[language]
440
441 def setLinkerObject(self, language, linker):
442 self.linkerObject[language] = linker
443 return self.getLinkerObject(language)
444
445 def getSharedLinkerObject(self, language):
446 if not language in self.sharedLinkerObject:
447 self.sharedLinkerObject[language] = self.getLanguageModule(language).SharedLinker(self.argDB)
448 self.sharedLinkerObject[language].setup()
449 if not self.compilers is None:
450 self.sharedLinkerObject[language].configCompilers = self.compilers
451 if not self.libraries is None:
452 self.sharedLinkerObject[language].configLibraries = self.libraries
453 if not self.versionControl is None:
454 self.sharedLinkerObject[language].versionControl = self.versionControl
455 return self.sharedLinkerObject[language]
456
457 def setSharedLinkerObject(self, language, linker):
458 self.sharedLinkerObject[language] = linker
459 return self.getSharedLinkerObject(language)
460
461 def getDynamicLinkerObject(self, language):
462 if not language in self.dynamicLinkerObject:
463 self.dynamicLinkerObject[language] = self.getLanguageModule(language).DynamicLinker(self.argDB)
464 self.dynamicLinkerObject[language].setup()
465 if not self.compilers is None:
466 self.dynamicLinkerObject[language].configCompilers = self.compilers
467 if not self.libraries is None:
468 self.dynamicLinkerObject[language].configLibraries = self.libraries
469 if not self.versionControl is None:
470 self.dynamicLinkerObject[language].versionControl = self.versionControl
471 return self.dynamicLinkerObject[language]
472
473 def setDynamicLinkerObject(self, language, linker):
474 self.dynamicLinkerObject[language] = linker
475 return self.getDynamicLinkerObject(language)
Note: See TracBrowser for help on using the repository browser.