xref: /petsc/config/BuildSystem/script.py (revision 6612abce4187524de682322781a214a62fe5980b)
15b6bfdb9SJed Brownfrom __future__ import print_function
25b6bfdb9SJed Brownfrom __future__ import absolute_import
3179860b2SJed Brownimport sys
4179860b2SJed Brownif not hasattr(sys, 'version_info'):
55b6bfdb9SJed Brown  print('*** Python version 1 is not supported. Please get the latest version from www.python.org ***')
6179860b2SJed Brown  sys.exit(4)
7179860b2SJed Brown
8492432c8SJed Brownimport pickle
9179860b2SJed Brown
10179860b2SJed Brownimport subprocess
11179860b2SJed Brown
12179860b2SJed Brownimport nargs
130542e31aSBarry Smith
140542e31aSBarry Smith# Uses threads to monitor running programs and time them out if they take too long
15179860b2SJed BrownuseThreads = nargs.Arg.findArgument('useThreads', sys.argv[1:])
160542e31aSBarry Smithif useThreads == 'no' or useThreads == '0':
1792626d4aSBarry Smith  useThreads = 0
180542e31aSBarry Smithelif useThreads == None or useThreads == 'yes' or useThreads == '1':
1992626d4aSBarry Smith  useThreads = 1
20179860b2SJed Brownelse:
2192626d4aSBarry Smith  raise RuntimeError('Unknown option value for --useThreads ',useThreads)
22179860b2SJed Brown
23179860b2SJed BrownuseSelect = nargs.Arg.findArgument('useSelect', sys.argv[1:])
240542e31aSBarry Smithif useSelect == 'no' or useSelect == '0':
2592626d4aSBarry Smith  useSelect = 0
260542e31aSBarry Smithelif  useSelect is None or useSelect == 'yes' or useSelect == '1':
27179860b2SJed Brown  useSelect = 1
28179860b2SJed Brownelse:
2992626d4aSBarry Smith  raise RuntimeError('Unknown option value for --useSelect ',useSelect)
30179860b2SJed Brown
310542e31aSBarry Smith#  Run parts of configure in parallel, does not currently work;
320542e31aSBarry Smith#  see config/BuildSystem/config/framework.parallelQueueEvaluation()
330542e31aSBarry SmithuseParallel = nargs.Arg.findArgument('useParallel', sys.argv[1:])
340542e31aSBarry Smithif useParallel == 'no' or useParallel == '0':
350542e31aSBarry Smith  useParallel = 0
360542e31aSBarry Smithelif  useParallel is None or useParallel == 'yes':
370542e31aSBarry Smith  useParallel = 5
380542e31aSBarry Smithelse:
390542e31aSBarry Smith  if useParallel == '1':
400542e31aSBarry Smith    # handle case with --useParallel was used
410542e31aSBarry Smith    found = 0
420542e31aSBarry Smith    for i in sys.argv[1:]:
430542e31aSBarry Smith      if i.startswith('--useParallel='):
440542e31aSBarry Smith        found = 1
450542e31aSBarry Smith        break
460542e31aSBarry Smith    if found: useParallel = int(useParallel)
470542e31aSBarry Smith    else: useParallel = 5
480542e31aSBarry SmithuseParallel = 0
490542e31aSBarry Smith
50179860b2SJed Brownimport logger
51179860b2SJed Brown
52179860b2SJed Brownclass Script(logger.Logger):
53179860b2SJed Brown  def __init__(self, clArgs = None, argDB = None, log = None):
54179860b2SJed Brown    self.checkPython()
55179860b2SJed Brown    logger.Logger.__init__(self, clArgs, argDB, log)
56179860b2SJed Brown    self.shell = '/bin/sh'
57179860b2SJed Brown    self.showHelp = 1
58179860b2SJed Brown    return
59179860b2SJed Brown
60179860b2SJed Brown  def hasHelpFlag(self):
61179860b2SJed Brown    '''Decide whether to display the help message and exit'''
62179860b2SJed Brown    import nargs
63179860b2SJed Brown
64179860b2SJed Brown    if not self.showHelp:
65179860b2SJed Brown      return 0
66179860b2SJed Brown    if nargs.Arg.findArgument('help', self.clArgs) is None and nargs.Arg.findArgument('h', self.clArgs) is None:
67179860b2SJed Brown      return 0
68179860b2SJed Brown    return 1
69179860b2SJed Brown
7075f179b0SBarry Smith  def hasListFlag(self):
7175f179b0SBarry Smith    '''Decide whether to display the list of download files and exit'''
7275f179b0SBarry Smith    import nargs
7375f179b0SBarry Smith
7475f179b0SBarry Smith    if not self.showHelp:
7575f179b0SBarry Smith      return 0
760aa1f76dSSatish Balay    if nargs.Arg.findArgument('with-packages-download-dir', self.clArgs) is None:
7775f179b0SBarry Smith      return 0
7875f179b0SBarry Smith    return 1
7975f179b0SBarry Smith
80179860b2SJed Brown  def setupArguments(self, argDB):
81179860b2SJed Brown    '''This method now also creates the help and action logs'''
82179860b2SJed Brown    import help
83179860b2SJed Brown
84179860b2SJed Brown    argDB = logger.Logger.setupArguments(self, argDB)
85179860b2SJed Brown
86179860b2SJed Brown    self.help = help.Help(argDB)
87179860b2SJed Brown    self.help.title = 'Script Help'
88179860b2SJed Brown
89179860b2SJed Brown    self.actions = help.Info(argDB)
90179860b2SJed Brown    self.actions.title = 'Script Actions'
91179860b2SJed Brown
92179860b2SJed Brown    self.setupHelp(self.help)
93179860b2SJed Brown    return argDB
94179860b2SJed Brown
95179860b2SJed Brown  def setupHelp(self, help):
966aad120cSJose E. Roman    '''This method should be overridden to provide help for arguments'''
97179860b2SJed Brown    import nargs
98179860b2SJed Brown
99179860b2SJed Brown    help.addArgument('Script', '-h',    nargs.ArgBool(None, 0, 'Print this help message', isTemporary = 1), ignoreDuplicates = 1)
1000aa1f76dSSatish Balay    help.addArgument('Script', '-help', nargs.ArgBool(None, 0, 'Print this help message', isTemporary = 1), ignoreDuplicates = 1)
1010aa1f76dSSatish Balay    help.addArgument('Script', '-with-packages-download-dir=<dir>', nargs.ArgDir(None,None, 'Skip network download of package tarballs and locate them in specified dir. If not found in dir, print package URL - so it can be obtained manually.', isTemporary = 1), ignoreDuplicates = 1)
102179860b2SJed Brown    return help
103179860b2SJed Brown
104179860b2SJed Brown  def setup(self):
105179860b2SJed Brown    ''' This method checks to see whether help was requested'''
106179860b2SJed Brown    if hasattr(self, '_setup'):
107179860b2SJed Brown      return
108179860b2SJed Brown    logger.Logger.setup(self)
109179860b2SJed Brown    self._setup = 1
110179860b2SJed Brown    if self.hasHelpFlag():
111e1362b5bSMatthew G. Knepley      self.argDB.readonly = True
112179860b2SJed Brown      if self.argDB.target == ['default']:
113179860b2SJed Brown        sections = None
114179860b2SJed Brown      else:
115179860b2SJed Brown        sections = self.argDB.target
116179860b2SJed Brown      self.help.output(sections = sections)
117179860b2SJed Brown      sys.exit()
11875f179b0SBarry Smith    if self.hasListFlag():
11975f179b0SBarry Smith      self.help.outputDownload()
120179860b2SJed Brown    return
121179860b2SJed Brown
122179860b2SJed Brown  def cleanup(self):
123179860b2SJed Brown    '''This method outputs the action log'''
124179860b2SJed Brown    self.actions.output(self.log)
125179860b2SJed Brown    return
126179860b2SJed Brown
127179860b2SJed Brown  def checkPython(self):
128df3bd252SSatish Balay    if not hasattr(sys, 'version_info') or sys.version_info < (3,4):
129df3bd252SSatish Balay      raise RuntimeError('BuildSystem requires Python version 3.4 or higher. Get Python at https://www.python.org/')
130179860b2SJed Brown    return
131179860b2SJed Brown
1320d623e36SVaclav Hapla  @staticmethod
133179860b2SJed Brown  def getModule(root, name):
134179860b2SJed Brown    '''Retrieve a specific module from the directory root, bypassing the usual paths'''
135*983a7392SJose E. Roman    if sys.version_info < (3,12):
136179860b2SJed Brown      import imp
137179860b2SJed Brown      (fp, pathname, description) = imp.find_module(name, [root])
138179860b2SJed Brown      try:
139179860b2SJed Brown        return imp.load_module(name, fp, pathname, description)
140179860b2SJed Brown      finally:
141179860b2SJed Brown        if fp: fp.close()
142*983a7392SJose E. Roman    else:
143*983a7392SJose E. Roman      import importlib.util
144*983a7392SJose E. Roman      spec = importlib.util.spec_from_file_location(name, root)
145*983a7392SJose E. Roman      module = importlib.util.module_from_spec(spec) # novermin
146*983a7392SJose E. Roman      sys.modules[name] = module
147*983a7392SJose E. Roman      spec.loader.exec_module(module)
148179860b2SJed Brown
1490d623e36SVaclav Hapla  @staticmethod
150179860b2SJed Brown  def importModule(moduleName):
151179860b2SJed Brown    '''Import the named module, and return the module object
152179860b2SJed Brown       - Works properly for fully qualified names'''
153179860b2SJed Brown    module     = __import__(moduleName)
154179860b2SJed Brown    components = moduleName.split('.')
155179860b2SJed Brown    for comp in components[1:]:
156179860b2SJed Brown      module = getattr(module, comp)
157179860b2SJed Brown    return module
158179860b2SJed Brown
15950f8d48fSJed Brown  @staticmethod
16097565ffdSJunchao Zhang  def runShellCommand(command, log=None, cwd=None, env=None):
16197565ffdSJunchao Zhang    return Script.runShellCommandSeq([command], log=log, cwd=cwd, env=env)
16250f8d48fSJed Brown
16350f8d48fSJed Brown  @staticmethod
16497565ffdSJunchao Zhang  def runShellCommandSeq(commandseq, log=None, cwd=None, env=None):
165179860b2SJed Brown    Popen = subprocess.Popen
166179860b2SJed Brown    PIPE  = subprocess.PIPE
16750f8d48fSJed Brown    output = ''
16850f8d48fSJed Brown    error = ''
1690d623e36SVaclav Hapla    ret = 0
17050f8d48fSJed Brown    for command in commandseq:
17150f8d48fSJed Brown      useShell = isinstance(command, str) or isinstance(command, bytes)
172179860b2SJed Brown      if log: log.write('Executing: %s\n' % (command,))
17350f8d48fSJed Brown      try:
17497565ffdSJunchao Zhang        pipe = Popen(command, cwd=cwd, env=env, stdin=None, stdout=PIPE, stderr=PIPE,
1759467260aSSatish Balay                     shell=useShell)
176179860b2SJed Brown        (out, err) = pipe.communicate()
1779467260aSSatish Balay        out = out.decode(encoding='UTF-8',errors='replace')
1789467260aSSatish Balay        err = err.decode(encoding='UTF-8',errors='replace')
179179860b2SJed Brown        ret = pipe.returncode
180a952ef13SBarry Smith      except Exception as e:
1811a7b8b2eSBarry Smith        if hasattr(e,'message') and hasattr(e,'errno'):
18250f8d48fSJed Brown          return ('', e.message, e.errno)
1831a7b8b2eSBarry Smith        else:
1841a7b8b2eSBarry Smith          return ('', str(e),1)
18550f8d48fSJed Brown      output += out
18650f8d48fSJed Brown      error += err
18750f8d48fSJed Brown      if ret:
18850f8d48fSJed Brown        break
18950f8d48fSJed Brown    return (output, error, ret)
190179860b2SJed Brown
1910d623e36SVaclav Hapla  @staticmethod
192179860b2SJed Brown  def defaultCheckCommand(command, status, output, error):
19373f05c50SBarry Smith    '''Raise an error if the exit status is nonzero
19473f05c50SBarry Smith       Since output and error may be huge and the exception error message may be printed to the
19573f05c50SBarry Smith       screen we cannot print the entire output'''
19673f05c50SBarry Smith    if status:
19773f05c50SBarry Smith      mlen = 512//2
19873f05c50SBarry Smith      if len(output) > 2*mlen:
19973f05c50SBarry Smith        output = output[0:mlen]+'\n .... more output .....\n'+output[len(output)- mlen:]
20073f05c50SBarry Smith      if len(error) > 2*mlen:
20173f05c50SBarry Smith        error = error[0:mlen]+'\n .... more error .....\n'+error[len(error)- mlen:]
20273f05c50SBarry Smith      raise RuntimeError('Could not execute "%s":\n%s' % (command,output+error))
203179860b2SJed Brown
2040d623e36SVaclav Hapla  @staticmethod
20505f86fb1SBarry Smith  def passCheckCommand(command, status, output, error):
20605f86fb1SBarry Smith    '''Does not check the command results'''
20705f86fb1SBarry Smith
20850f8d48fSJed Brown  @staticmethod
20997565ffdSJunchao Zhang  def executeShellCommand(command, checkCommand = None, timeout = 600.0, log = None, lineLimit = 0, cwd=None, env=None, logOutputflg = True, threads = 0):
210179860b2SJed Brown    '''Execute a shell command returning the output, and optionally provide a custom error checker
211179860b2SJed Brown       - This returns a tuple of the (output, error, statuscode)'''
2121a87e097SBarry Smith    '''The timeout is ignored unless the threads values is nonzero'''
21397565ffdSJunchao Zhang    return Script.executeShellCommandSeq([command], checkCommand=checkCommand, timeout=timeout, log=log, lineLimit=lineLimit, cwd=cwd, env=env, logOutputflg = logOutputflg, threads = threads)
21450f8d48fSJed Brown
21550f8d48fSJed Brown  @staticmethod
21697565ffdSJunchao Zhang  def executeShellCommandSeq(commandseq, checkCommand = None, timeout = 600.0, log = None, lineLimit = 0, cwd=None, env=None, logOutputflg = True, threads = 0):
21750f8d48fSJed Brown    '''Execute a sequence of shell commands (an && chain) returning the output, and optionally provide a custom error checker
21850f8d48fSJed Brown       - This returns a tuple of the (output, error, statuscode)'''
219179860b2SJed Brown    if not checkCommand:
220179860b2SJed Brown      checkCommand = Script.defaultCheckCommand
221179860b2SJed Brown    if log is None:
222179860b2SJed Brown      log = logger.Logger.defaultLog
223c3ec109aSBarry Smith    def logOutput(log, output, logOutputflg):
224179860b2SJed Brown      import re
225c3ec109aSBarry Smith      if not logOutputflg: return output
226179860b2SJed Brown      # get rid of multiple blank lines
2279f0d583aSJed Brown      output = re.sub('\n+','\n', output).strip()
2284854f487SJed Brown      if output:
229179860b2SJed Brown        if lineLimit:
230179860b2SJed Brown          output = '\n'.join(output.split('\n')[:lineLimit])
2314854f487SJed Brown        if '\n' in output:      # multi-line output
2324854f487SJed Brown          log.write('stdout:\n'+output+'\n')
2334854f487SJed Brown        else:
2344854f487SJed Brown          log.write('stdout: '+output+'\n')
235179860b2SJed Brown      return output
23697565ffdSJunchao Zhang    def runInShell(commandseq, log, cwd, env):
2370542e31aSBarry Smith      if useThreads and threads:
238179860b2SJed Brown        import threading
2391a87e097SBarry Smith        log.write('Running Executable with threads to time it out at '+str(timeout)+'\n')
240179860b2SJed Brown        class InShell(threading.Thread):
241179860b2SJed Brown          def __init__(self):
242179860b2SJed Brown            threading.Thread.__init__(self)
243179860b2SJed Brown            self.name = 'Shell Command'
244179860b2SJed Brown            self.setDaemon(1)
245179860b2SJed Brown          def run(self):
246179860b2SJed Brown            (self.output, self.error, self.status) = ('', '', -1) # So these fields exist even if command fails with no output
24797565ffdSJunchao Zhang            (self.output, self.error, self.status) = Script.runShellCommandSeq(commandseq, log, cwd, env)
248179860b2SJed Brown        thread = InShell()
249179860b2SJed Brown        thread.start()
250179860b2SJed Brown        thread.join(timeout)
251ca038c9dSSatish Balay        if thread.is_alive():
2521a87e097SBarry Smith          error = 'Runaway process exceeded time limit of '+str(timeout)+'\n'
253179860b2SJed Brown          log.write(error)
254179860b2SJed Brown          return ('', error, -1)
255179860b2SJed Brown        else:
256179860b2SJed Brown          return (thread.output, thread.error, thread.status)
257179860b2SJed Brown      else:
25897565ffdSJunchao Zhang        return Script.runShellCommandSeq(commandseq, log, cwd, env)
259179860b2SJed Brown
26097565ffdSJunchao Zhang    (output, error, status) = runInShell(commandseq, log, cwd, env)
261c3ec109aSBarry Smith    output = logOutput(log, output,logOutputflg)
262b7d94e18SBarry Smith    logOutput(log, error,logOutputflg)
26350f8d48fSJed Brown    checkCommand(commandseq, status, output, error)
264179860b2SJed Brown    return (output, error, status)
265179860b2SJed Brown
266179860b2SJed Brown  def loadConfigure(self, argDB = None):
267179860b2SJed Brown    if argDB is None:
268179860b2SJed Brown      argDB = self.argDB
269179860b2SJed Brown    if not 'configureCache' in argDB:
270179860b2SJed Brown      self.logPrint('No cached configure in RDict at '+str(argDB.saveFilename))
271179860b2SJed Brown      return None
272179860b2SJed Brown    try:
273179860b2SJed Brown      cache = argDB['configureCache']
274492432c8SJed Brown      framework = pickle.loads(cache)
275179860b2SJed Brown      framework.framework = framework
276179860b2SJed Brown      framework.argDB = argDB
277179860b2SJed Brown      self.logPrint('Loaded configure to cache: size '+str(len(cache)))
278492432c8SJed Brown    except pickle.UnpicklingError as e:
279179860b2SJed Brown      framework = None
280179860b2SJed Brown      self.logPrint('Invalid cached configure: '+str(e))
281179860b2SJed Brown    return framework
282179860b2SJed Brown
283179860b2SJed Brownimport args
284179860b2SJed Brown
285179860b2SJed Brownclass LanguageProcessor(args.ArgumentProcessor):
286179860b2SJed Brown  def __init__(self, clArgs = None, argDB = None, framework = None, versionControl = None):
287179860b2SJed Brown    self.languageModule      = {}
288179860b2SJed Brown    self.preprocessorObject  = {}
289179860b2SJed Brown    self.compilerObject      = {}
290179860b2SJed Brown    self.linkerObject        = {}
291179860b2SJed Brown    self.sharedLinkerObject  = {}
292179860b2SJed Brown    self.dynamicLinkerObject = {}
293179860b2SJed Brown    self.framework           = framework
294179860b2SJed Brown    self.versionControl      = versionControl
295179860b2SJed Brown    args.ArgumentProcessor.__init__(self, clArgs, argDB)
296179860b2SJed Brown    self.outputFiles         = {}
297179860b2SJed Brown    self.modulePath          = 'config.compile'
298179860b2SJed Brown    return
299179860b2SJed Brown
300179860b2SJed Brown  def getCompilers(self):
301179860b2SJed Brown    if self.framework is None:
302179860b2SJed Brown      return
303179860b2SJed Brown    return self.framework.require('config.compilers', None)
304179860b2SJed Brown  compilers = property(getCompilers, doc = 'The config.compilers configure object')
305179860b2SJed Brown  def getLibraries(self):
306179860b2SJed Brown    if self.framework is None:
307179860b2SJed Brown      return
308179860b2SJed Brown    return self.framework.require('config.libraries', None)
309179860b2SJed Brown  libraries = property(getLibraries, doc = 'The config.libraries configure object')
310179860b2SJed Brown
311179860b2SJed Brown  def __getstate__(self, d = None):
312179860b2SJed Brown    '''We only want to pickle the language module names and output files. The other objects are set by configure.'''
313179860b2SJed Brown    if d is None:
314179860b2SJed Brown      d = args.ArgumentProcessor.__getstate__(self)
315179860b2SJed Brown    if 'languageModule' in d:
316179860b2SJed Brown      d['languageModule'] = dict([(lang,mod._loadName) for lang,mod in d['languageModule'].items()])
317179860b2SJed Brown    for member in ['preprocessorObject', 'compilerObject', 'linkerObject', 'sharedLinkerObject', 'dynamicLinkerObject', 'framework']:
318179860b2SJed Brown      if member in d:
319179860b2SJed Brown        del d[member]
320179860b2SJed Brown    return d
321179860b2SJed Brown
322179860b2SJed Brown  def __setstate__(self, d):
323179860b2SJed Brown    '''We must create the language modules'''
324179860b2SJed Brown    args.ArgumentProcessor.__setstate__(self, d)
325179860b2SJed Brown    self.__dict__.update(d)
326179860b2SJed Brown    [self.getLanguageModule(language, moduleName) for language,moduleName in self.languageModule.items()]
327179860b2SJed Brown    self.preprocessorObject  = {}
328179860b2SJed Brown    self.compilerObject      = {}
329179860b2SJed Brown    self.linkerObject        = {}
330179860b2SJed Brown    self.sharedLinkerObject  = {}
331179860b2SJed Brown    self.dynamicLinkerObject = {}
332179860b2SJed Brown    return
333179860b2SJed Brown
334179860b2SJed Brown  def setArgDB(self, argDB):
335179860b2SJed Brown    args.ArgumentProcessor.setArgDB(self, argDB)
336179860b2SJed Brown    for obj in self.preprocessorObject.values():
337179860b2SJed Brown      if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
338179860b2SJed Brown        obj.argDB = argDB
339179860b2SJed Brown    for obj in self.compilerObject.values():
340179860b2SJed Brown      if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
341179860b2SJed Brown        obj.argDB = argDB
342179860b2SJed Brown    for obj in self.linkerObject.values():
343179860b2SJed Brown      if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
344179860b2SJed Brown        obj.argDB = argDB
345179860b2SJed Brown    for obj in self.sharedLinkerObject.values():
346179860b2SJed Brown      if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
347179860b2SJed Brown        obj.argDB = argDB
348179860b2SJed Brown    for obj in self.dynamicLinkerObject.values():
349179860b2SJed Brown      if not hasattr(obj, 'argDB') or not obj.argDB == argDB:
350179860b2SJed Brown        obj.argDB = argDB
351179860b2SJed Brown    if not self.compilers is None:
352179860b2SJed Brown      self.compilers.argDB = argDB
353179860b2SJed Brown      for obj in self.preprocessorObject.values():
354179860b2SJed Brown        if hasattr(obj, 'configCompilers'):
355179860b2SJed Brown          obj.configCompilers.argDB = argDB
356179860b2SJed Brown      for obj in self.compilerObject.values():
357179860b2SJed Brown        if hasattr(obj, 'configCompilers'):
358179860b2SJed Brown          obj.configCompilers.argDB = argDB
359179860b2SJed Brown      for obj in self.linkerObject.values():
360179860b2SJed Brown        if hasattr(obj, 'configCompilers'):
361179860b2SJed Brown          obj.configCompilers.argDB = argDB
362179860b2SJed Brown      for obj in self.sharedLinkerObject.values():
363179860b2SJed Brown        if hasattr(obj, 'configCompilers'):
364179860b2SJed Brown          obj.configCompilers.argDB = argDB
365179860b2SJed Brown      for obj in self.dynamicLinkerObject.values():
366179860b2SJed Brown        if hasattr(obj, 'configCompilers'):
367179860b2SJed Brown          obj.configCompilers.argDB = argDB
368179860b2SJed Brown    if not self.libraries is None:
369179860b2SJed Brown      self.libraries.argDB = argDB
370179860b2SJed Brown      for obj in self.linkerObject.values():
371179860b2SJed Brown        if hasattr(obj, 'configLibraries'):
372179860b2SJed Brown          obj.configLibraries.argDB = argDB
373179860b2SJed Brown      for obj in self.sharedLinkerObject.values():
374179860b2SJed Brown        if hasattr(obj, 'configLibraries'):
375179860b2SJed Brown          obj.configLibraries.argDB = argDB
376179860b2SJed Brown      for obj in self.dynamicLinkerObject.values():
377179860b2SJed Brown        if hasattr(obj, 'configLibraries'):
378179860b2SJed Brown          obj.configLibraries.argDB = argDB
379179860b2SJed Brown    return
380179860b2SJed Brown  argDB = property(args.ArgumentProcessor.getArgDB, setArgDB, doc = 'The RDict argument database')
381179860b2SJed Brown
382179860b2SJed Brown  def getLanguageModule(self, language, moduleName = None):
383179860b2SJed Brown    '''Return the module associated with operations for a given language
384179860b2SJed Brown       - Giving a moduleName explicitly forces a reimport'''
385179860b2SJed Brown    if not language in self.languageModule or not moduleName is None:
386179860b2SJed Brown      try:
387179860b2SJed Brown        if moduleName is None:
388179860b2SJed Brown          moduleName = self.modulePath+'.'+language
389179860b2SJed Brown        module     = __import__(moduleName)
3905b6bfdb9SJed Brown      except ImportError as e:
391179860b2SJed Brown        if not moduleName is None:
392179860b2SJed Brown          self.logPrint('Failure to find language module: '+str(e))
393179860b2SJed Brown        try:
394179860b2SJed Brown          moduleName = self.modulePath+'.'+language
395179860b2SJed Brown          module     = __import__(moduleName)
3965b6bfdb9SJed Brown        except ImportError as e:
397179860b2SJed Brown          self.logPrint('Failure to find language module: '+str(e))
398179860b2SJed Brown          moduleName = 'config.compile.'+language
399179860b2SJed Brown          module     = __import__(moduleName)
400179860b2SJed Brown      components = moduleName.split('.')
401179860b2SJed Brown      for component in components[1:]:
402179860b2SJed Brown        module   = getattr(module, component)
403179860b2SJed Brown      module._loadName = moduleName
404179860b2SJed Brown      self.languageModule[language] = module
405179860b2SJed Brown    return self.languageModule[language]
406179860b2SJed Brown
407179860b2SJed Brown  def getPreprocessorObject(self, language):
408179860b2SJed Brown    if not language in self.preprocessorObject:
409179860b2SJed Brown      self.preprocessorObject[language] = self.getLanguageModule(language).Preprocessor(self.argDB)
410179860b2SJed Brown      self.preprocessorObject[language].setup()
411179860b2SJed Brown    if not self.compilers is None:
412179860b2SJed Brown      self.preprocessorObject[language].configCompilers = self.compilers
413179860b2SJed Brown    if not self.versionControl is None:
414179860b2SJed Brown      self.preprocessorObject[language].versionControl  = self.versionControl
415179860b2SJed Brown    return self.preprocessorObject[language]
416179860b2SJed Brown
417179860b2SJed Brown  def setPreprocessorObject(self, language, preprocessor):
418179860b2SJed Brown    self.preprocessorObject[language] = preprocessor
419179860b2SJed Brown    return self.getPreprocessorObject(language)
420179860b2SJed Brown
421179860b2SJed Brown  def getCompilerObject(self, language):
422179860b2SJed Brown    if not language in self.compilerObject:
423179860b2SJed Brown      self.compilerObject[language] = self.getLanguageModule(language).Compiler(self.argDB)
424179860b2SJed Brown      self.compilerObject[language].setup()
425179860b2SJed Brown    if not self.compilers is None:
426179860b2SJed Brown      self.compilerObject[language].configCompilers = self.compilers
427179860b2SJed Brown    if not self.versionControl is None:
428179860b2SJed Brown      self.compilerObject[language].versionControl  = self.versionControl
429179860b2SJed Brown    return self.compilerObject[language]
430179860b2SJed Brown
431179860b2SJed Brown  def setCompilerObject(self, language, compiler):
432179860b2SJed Brown    self.compilerObject[language] = compiler
433179860b2SJed Brown    return self.getCompilerObject(language)
434179860b2SJed Brown
435179860b2SJed Brown  def getLinkerObject(self, language):
436179860b2SJed Brown    if not language in self.linkerObject:
437179860b2SJed Brown      self.linkerObject[language] = self.getLanguageModule(language).Linker(self.argDB)
438179860b2SJed Brown      self.linkerObject[language].setup()
439179860b2SJed Brown    if not self.compilers is None:
440179860b2SJed Brown      self.linkerObject[language].configCompilers = self.compilers
441179860b2SJed Brown    if not self.libraries is None:
442179860b2SJed Brown      self.linkerObject[language].configLibraries = self.libraries
443179860b2SJed Brown    if not self.versionControl is None:
444179860b2SJed Brown      self.linkerObject[language].versionControl  = self.versionControl
445179860b2SJed Brown    return self.linkerObject[language]
446179860b2SJed Brown
447179860b2SJed Brown  def setLinkerObject(self, language, linker):
448179860b2SJed Brown    self.linkerObject[language] = linker
449179860b2SJed Brown    return self.getLinkerObject(language)
450179860b2SJed Brown
451179860b2SJed Brown  def getSharedLinkerObject(self, language):
452179860b2SJed Brown    if not language in self.sharedLinkerObject:
453179860b2SJed Brown      self.sharedLinkerObject[language] = self.getLanguageModule(language).SharedLinker(self.argDB)
454179860b2SJed Brown      self.sharedLinkerObject[language].setup()
455179860b2SJed Brown    if not self.compilers is None:
456179860b2SJed Brown      self.sharedLinkerObject[language].configCompilers = self.compilers
457179860b2SJed Brown    if not self.libraries is None:
458179860b2SJed Brown      self.sharedLinkerObject[language].configLibraries = self.libraries
459179860b2SJed Brown    if not self.versionControl is None:
460179860b2SJed Brown      self.sharedLinkerObject[language].versionControl  = self.versionControl
461179860b2SJed Brown    return self.sharedLinkerObject[language]
462179860b2SJed Brown
463179860b2SJed Brown  def setSharedLinkerObject(self, language, linker):
464179860b2SJed Brown    self.sharedLinkerObject[language] = linker
465179860b2SJed Brown    return self.getSharedLinkerObject(language)
466179860b2SJed Brown
467179860b2SJed Brown  def getDynamicLinkerObject(self, language):
468179860b2SJed Brown    if not language in self.dynamicLinkerObject:
469179860b2SJed Brown      self.dynamicLinkerObject[language] = self.getLanguageModule(language).DynamicLinker(self.argDB)
470179860b2SJed Brown      self.dynamicLinkerObject[language].setup()
471179860b2SJed Brown    if not self.compilers is None:
472179860b2SJed Brown      self.dynamicLinkerObject[language].configCompilers = self.compilers
473179860b2SJed Brown    if not self.libraries is None:
474179860b2SJed Brown      self.dynamicLinkerObject[language].configLibraries = self.libraries
475179860b2SJed Brown    if not self.versionControl is None:
476179860b2SJed Brown      self.dynamicLinkerObject[language].versionControl  = self.versionControl
477179860b2SJed Brown    return self.dynamicLinkerObject[language]
478179860b2SJed Brown
479179860b2SJed Brown  def setDynamicLinkerObject(self, language, linker):
480179860b2SJed Brown    self.dynamicLinkerObject[language] = linker
481179860b2SJed Brown    return self.getDynamicLinkerObject(language)
482