(file) Return to localize.py CVS log (file) (dir) Up to [Development] / JSOC

  1 arta  1.1 #!/home/jsoc/bin/linux_x86_64/activepython
  2           
  3           import sys
  4           import getopt
  5           import re
  6 arta  1.6 import os
  7           import stat
  8           import xml.etree.ElementTree as ET
  9 arta  1.1 from subprocess import check_output, CalledProcessError
 10           
 11           # Constants
 12           VERS_FILE = 'jsoc_version.h'
 13           SDP_CFG = 'configsdp.txt'
 14           NET_CFG = 'config.local'
 15           NET_CFGMAP = 'config.local.map'
 16           RET_SUCCESS = 0
 17           RET_NOTDRMS = 1
 18           
 19 arta  1.2 PREFIX = """# This file was auto-generated by localize.py. Please do not edit it directly (running
 20           # configure will run localize.py, which will then overwrite any edits manually performed).
 21           """
 22 arta  1.1 
 23 arta  1.2 C_PREFIX = """/* This file was auto-generated by localize.py. Please do not edit it directly (running
 24            * configure will run localize.py, which will then overwrite any edits manually performed). */
 25 arta  1.1 """
 26           
 27 arta  1.2 PERL_BINPATH = '#!/usr/bin/perl\n'
 28           
 29           PERL_INTIAL = """package drmsparams;
 30               
 31           use warnings;
 32           use strict;
 33           """
 34           
 35           PERL_FXNS_A = """sub new
 36 arta  1.1 {
 37               my($clname) = shift;
 38               
 39               my($self) = 
 40               {
 41                   _paramsH => undef
 42               };
 43               
 44               bless($self, $clname);
 45               $self->{_paramsH} = $self->initialize();
 46               
 47               return $self;
 48           }
 49               
 50           sub DESTROY
 51           {
 52               my($self) = shift;
 53           }
 54 arta  1.2 """
 55           
 56           PERL_FXNS_B = """sub get
 57           {
 58               my($self) = shift;
 59               my($name) = shift;
 60               my($rv);
 61 arta  1.1     
 62 arta  1.2     if (exists($self->{_paramsH}->{$name}))
 63               {
 64                   return $self->{_paramsH}->{$name};
 65               }
 66               else
 67               {
 68                   return undef;
 69               }
 70           }
 71           1;"""
 72 arta  1.1 
 73 arta  1.6 
 74           RULESPREFIX = """# Standard things
 75           sp 		:= $(sp).x
 76           dirstack_$(sp)	:= $(d)
 77           d		:= $(dir)
 78           """
 79           
 80           RULESSUFFIX = """dir	:= $(d)/example
 81           -include		$(SRCDIR)/$(dir)/Rules.mk
 82           dir	:= $(d)/cookbook
 83           -include		$(SRCDIR)/$(dir)/Rules.mk
 84           dir	:= $(d)/myproj
 85           -include		$(SRCDIR)/$(dir)/Rules.mk
 86           
 87           # Standard things
 88           d		:= $(dirstack_$(sp))
 89           sp		:= $(basename $(sp))
 90           """
 91           
 92           TARGETPREFIX = """$(PROJOBJDIR):\n\t+@[ -d $@ ] || mkdir -p $@"""
 93           
 94 arta  1.3 ICC_MAJOR = 9
 95           ICC_MINOR = 0
 96           GCC_MAJOR = 3
 97           GCC_MINOR = 0
 98           IFORT_MAJOR = 9
 99           IFORT_MINOR = 0
100           GFORT_MAJOR = 4
101           GFORT_MINOR = 2
102           
103           
104 arta  1.1 # Read arguments
105           #  d - localization directory
106           #  b - base name of all parameter files (e.g., -b drmsparams --> drmsparams.h, drmsparams.mk, drmsparams.pm, etc.)
107           #  m - make file
108           def GetArgs(args):
109               rv = bool(0)
110               optD = {}
111               
112               try:
113                   opts, remainder = getopt.getopt(args, "hd:b:",["dir=", "base="])
114               except getopt.GetoptError:
115                   print('Usage:')
116                   print('localize.py [-h] -d <localization directory> -b <parameter file base>')
117                   rv = bool(1)
118               
119               if rv == bool(0):
120                   for opt, arg in opts:
121                       if opt == '-h':
122                           print('localize.py [-h] -d <localization directory> -b <parameter file base>')
123                       elif opt in ("-d", "--dir"):
124                           regexp = re.compile(r"(\S+)/?")
125 arta  1.1                 matchobj = regexp.match(arg)
126                           if matchobj is None:
127                               rv = bool(1)
128                           else:
129                               optD['dir'] = matchobj.group(1)
130                       elif opt in ("-b", "--base"):
131                           optD['base'] = arg
132                       else:
133                           optD[opt] = arg
134           	
135               return optD
136           
137           def createMacroStr(key, val, keyColLen, status):
138               if keyColLen < len(key):
139                   status = bool(1)
140                   return None
141               else:
142                   nsp = keyColLen - len(key)
143                   spaces = str()
144                   for isp in range(nsp):
145                       spaces += ' '
146 arta  1.1         status = bool(0)
147                   return '#define ' + key + spaces + val + '\n'
148           
149           def createPerlConst(key, val, keyColLen, status):
150               if keyColLen < len(key):
151                   status = bool(1)
152                   return None
153               else:
154                   nsp = keyColLen - len(key)
155                   spaces = str()
156                   for isp in range(nsp):
157                       spaces += ' '
158                   status = bool(0)
159                   return 'use constant ' + key + ' => ' + spaces + val + ';\n'
160           
161 arta  1.3 def isSupportedPlat(plat):
162               regexp = re.compile(r"\s*(^x86_64|^ia32|^ia64|^avx)", re.IGNORECASE)
163               matchobj = regexp.match(plat);
164                   
165               if not matchobj is None:
166                   return bool(1);
167               else:
168                   return bool(0);
169           
170 arta  1.6 def processMakeParam(mDefs, key, val, platDict, machDict):
171 arta  1.3     varMach = None
172               regexp = re.compile(r"(\S+):(\S+)")
173               matchobj = regexp.match(key)
174               if not matchobj is None:
175                   varName = matchobj.group(1)
176                   varMach = matchobj.group(2)
177               else:
178                   varName = key
179               
180               varValu = val
181                   
182               if varMach is None:
183                   mDefs.extend(list('\n' + varName + ' = ' + varValu))
184               else:
185                   if isSupportedPlat(varMach):
186                       # The guard will compare varValu to $JSOC_MACHINE.
187                       if not varMach in platDict:
188                           platDict[varMach] = {}
189                       platDict[varMach][varName] = varValu
190                   else:
191                       # The guard will compare varValu to $MACHINETYPE (this is just the hostname of the machine on which localize.py is running).
192 arta  1.3             if not varMach in machDict:
193                           machDict[varMach] = {}
194                       machDict[varMach][varName] = varValu
195           
196 arta  1.6 def processParam(cfgfile, line, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, platDict, machDict, section):
197 arta  1.1     status = 0
198                       
199               if ''.join(section) == 'defs' or not cfgfile:
200                   matchobj = regexp.match(line)
201                   if not matchobj is None:
202                       # We have a key-value line
203                       keyCfgSp = matchobj.group(1)
204                       val = matchobj.group(2)
205                       
206                       # Must map the indirect name to the actual name
207                       if keymap:
208                           # Map to actual name only if the keymap is not empty (which signifies NA).
209                           if keyCfgSp in keymap:
210                               key = keymap[keyCfgSp]
211                           elif keyCfgSp == 'LOCAL_CONFIG_SET' or keyCfgSp == 'DRMS_SAMPLE_NAMESPACE':
212 arta  1.6                     # Ignore parameters that are not useful and shouldn't have been there in the first place. But
213                               # they have been released to the world, so we have to account for them.
214 arta  1.1                     return bool(0)
215                           elif not cfgfile:
216                               # Should not be doing mapping for addenda
217                               key = keyCfgSp
218                           else:
219                               raise Exception('badKeyMapKey', keyCfgSp)
220                       else:
221                           key = keyCfgSp
222                       
223                       matchobj = regexpQuote.match(key)
224                       if not matchobj is None:
225                           quote = matchobj.group(1)
226                           key = matchobj.group(2)
227           
228                           # master defs dictionary
229                           defs[key] = val
230                           
231                           # C header file
232                           if quote == "q":
233                               # Add double-quotes
234                               cDefs.extend(list(createMacroStr(key, '"' + val + '"', 40, status)))
235 arta  1.1                 elif quote == "p":
236                               # Add parentheses
237                               cDefs.extend(list(createMacroStr(key, '(' + val + ')', 40, status)))
238                           elif quote == "a":
239                               # Leave as-is
240                               cDefs.extend(list(createMacroStr(key, val, 40, status)))
241                           else:
242                               # Unknown quote type
243                               raise Exception('badQuoteQual', key)
244                           
245                           if status:
246                               raise Exception('paramNameTooLong', key)
247                           
248                           # Make file - val should never be quoted; just use as is
249 arta  1.4                 mDefsGen.extend(list('\n' + key + ' = ' + val))
250 arta  1.1                 
251                           # Perl file - val should ALWAYS be single-quote quoted
252                           # Save const info to a string
253                           perlConstSection.extend(list(createPerlConst(key, "'" + val + "'", 40, status)))
254                           
255                           if status:
256                               raise Exception('paramNameTooLong', key)
257                           
258                           # Save initialization information as a string. Now that we've defined
259                           # constants (the names of which are the parameter names) 
260                           # we can refer to those in the init section. The key variable holds the
261                           # name of the constant.
262 arta  1.2                 perlInitSection.extend(list('\n  $self->{_paramsH}->{' + key + '} = ' + "'" + val + "';"))
263 arta  1.1             else:
264                           # No quote qualifier
265                           raise Exception('missingQuoteQual', key)
266 arta  1.3     elif ''.join(section) == 'make' and cfgfile:
267                   # Configure the remaining make variables defined in the __MAKE__ section of the configuration file. Third-party
268                   # library make variables are specified in the __MAKE__ section.
269                   matchobj = regexp.match(line)
270                   if not matchobj is None:
271                       # We have a key-value line
272                       key = matchobj.group(1)
273                       val = matchobj.group(2)
274           
275                       # This information is for making make variables only. We do not need to worry about quoting any values
276                       defs[key] = val
277 arta  1.4             processMakeParam(mDefsMake, key, val, platDict, machDict)
278 arta  1.1     
279               return bool(0)
280           
281           # We have some extraneous line or a newline - ignore.
282           
283 arta  1.6 def processXML(xml, projRules, projTarget):
284               rv = bool(0)
285               
286               # <projects>
287               root = ET.fromstring(xml)
288               
289               # Iterate through each proj child.
290               for proj in root.iter('proj'):
291                   # Rules.mk
292                   nameElem = proj.find('name')
293                   rulesStr = 'dir     := $(d)/' + nameElem.text + '\n-include          $(SRCDIR)/$(dir)/Rules.mk\n'
294                   
295                   # make doesn't support logical operations in ifeq conditionals (you can't do ifeq (A AND B)), 
296                   # so we need to write:
297                   #   ifeq (A)
298                   #      ifeq (B)
299                   #        <do something>
300                   #      endif
301                   #   endif
302                       
303                   rulesPref = '';
304 arta  1.6         rulesSuff = '';
305               
306                   filters = proj.find('filters')
307                   if filters is not None:
308                       for filter in filters.findall('filter'):
309                           rulesPref += 'ifeq ($(' + filter.find('name').text + '),' + filter.find('value').text + ')\n'
310                           rulesSuff += 'endif\n'
311                       
312                   if len(rulesPref) > 0 and len(rulesSuff) > 0:
313                       projRules.extend(list(rulesPref))
314                       projRules.extend(list(rulesStr))
315                       projRules.extend(list(rulesSuff))
316                   else:
317                       projRules.extend(list(rulesStr))
318                   
319                   # target.mk
320                   subdirs = proj.find('subdirs')
321                   if subdirs is not None:
322                       for subdir in subdirs.findall('subdir'):
323                           targetStr = '\n\t+@[ -d $@/' + nameElem.text + '/' + subdir.text + ' ] || mkdir -p $@/' + nameElem.text + '/' + subdir.text
324                           projTarget.extend(list(targetStr))
325 arta  1.6 
326               return rv
327           
328           def determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg):
329               matchobj = regexpDefs.match(line)
330               if not matchobj is None:
331                   return 'defs'
332                   
333               matchobj = regexpMake.match(line)
334               if not matchobj is None:
335                   return 'make'
336                   
337               matchobj = regexpProjMkRules.match(line)
338               if not matchobj is None:
339                   return 'projmkrules'
340                   
341               matchobj = regexpProj.match(line)
342               if not matchobj is None:
343                   return 'proj'
344                   
345               matchobj = regexpProjCfg.match(line)
346 arta  1.6     if not matchobj is None:
347                   return 'projcfg'
348           
349               return None
350           
351 arta  1.1 # defs is a dictionary containing all parameters (should they be needed in this script)
352 arta  1.6 # projCfg is the list containing the configure script content.
353           # projMkRules is the list containing the make_basic.mk content.
354           # projRules is the list containing the Rules.mk content.
355           # projTargert is the list containing the target.mk content.
356           def parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection):
357 arta  1.1     rv = bool(0)
358               
359               # Open required config file (config.local)
360               try:
361                   # Examine each line, looking for key=value pairs.
362                   regexpDefs = re.compile(r"^__DEFS__")
363                   regexpMake = re.compile(r"^__MAKE__")
364 arta  1.6         regexpProjMkRules = re.compile(r"__PROJ_MK_RULES__")
365                   regexpProj = re.compile(r"^__PROJ__")
366                   regexpProjCfg = re.compile(r"^__PROJCFG__")
367 arta  1.1         regexpComm = re.compile(r"^\s*#")
368 arta  1.6         regexpSp = re.compile(r"^s*$")
369 arta  1.1         regexpQuote = re.compile(r"^\s*(\w):(.+)")
370 arta  1.6         regexpCustMkBeg = re.compile(r"^_CUST_")
371                   regexpCustMkEnd = re.compile(r"^_ENDCUST_")
372                   regexpDiv = re.compile(r"^__")
373 arta  1.3         regexp = re.compile(r"^\s*(\S+)\s+(\S+)")
374 arta  1.1         
375 arta  1.3         platDict = {}
376                   machDict = {}
377 arta  1.6         
378                   xml = None
379 arta  1.1         
380                   # Process the parameters in the configuration file
381                   if not fin is None:
382                       for line in fin:
383 arta  1.6                 matchobj = regexpComm.match(line)
384                           if not matchobj is None:
385                               # Skip comment line
386                               continue
387                           
388                           matchobj = regexpSp.match(line)
389                           if not matchobj is None:
390                               # Skip whitespace line
391                               continue
392 arta  1.1             
393 arta  1.6                 newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
394                           if not newSection is None:
395                               section = newSection
396               
397                           if section == 'make':
398                               # There are some blocks of lines in the __MAKE__ section that must be copied ver batim to the output make file. 
399                               # The blocks are defined by _CUST_/_ENDCUST_ tags.
400                               matchobj = regexpCustMkBeg.match(line)
401                                   
402                               if not matchobj is None:
403                                   mDefsMake.extend(list('\n'))
404                                   for line in fin:
405                                       matchobj = regexpCustMkEnd.match(line)
406                                       if not matchobj is None:
407                                           break;
408                                       mDefsMake.extend(list(line))
409                                   newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
410                                   if not newSection is None:
411                                       section = newSection
412                                   continue
413                               # Intentional fall through to next if statement
414 arta  1.6                 if section == 'defs' or section == 'make':
415                               iscfg = bool(1)
416                               ppRet = processParam(iscfg, line, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, platDict, machDict, section)
417                                           
418                               if ppRet:
419                                   break;
420                           elif section == 'projcfg':
421                               # Copy the line ver batim to the projCfg list (configure)
422                               for line in fin:
423                                   matchobj = regexpDiv.match(line)
424                                   if not matchobj is None:
425                                       break;
426                                   projCfg.extend(list(line))
427                               newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
428                               if not newSection is None:
429                                   section = newSection
430                               continue
431                           elif section == 'projmkrules':
432                               # Copy the line ver batim to the projMkRules list (make_basic.mk)
433                               for line in fin:
434                                   matchobj = regexpDiv.match(line)
435 arta  1.6                         if not matchobj is None:
436                                       break;
437                                   projMkRules.extend(list(line))
438                               newSection = determineSection(line, regexpDefs, regexpMake, regexpProjMkRules, regexpProj, regexpProjCfg)
439                               if not newSection is None:
440                                   section = newSection
441                               continue
442                           elif section == 'proj':
443                               # Must parse xml and use the project-specific information to populate the Rules.mk and target.mk files.
444                               # Collect all xml lines for now, then process after file-read loop.
445                               if xml is None:
446                                   xml = line
447                               else:
448                                   xml += line
449                           else:
450                               # Unknown section 
451                               raise Exception('unknownSection', section)
452 arta  1.1     except Exception as exc:
453 arta  1.6         msg = exc.args[0]
454 arta  1.1         if msg == 'badKeyMapKey':
455                       # If we are here, then there was a non-empty keymap, and the parameter came from
456                       # the configuration file.
457 arta  1.6             violator = exc.args[1]
458 arta  1.1             print('Unknown parameter name ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
459                       rv = bool(1)
460                   elif msg == 'badQuoteQual':
461                       # The bad quote qualifier came from the configuration file, not the addenda, since
462                       # we will have fixed any bad qualifiers in the addenda (which is populated by code).
463 arta  1.6             violator = exc.args[1]
464 arta  1.1             print('Unknown quote qualifier ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
465                       rv = bool(1)
466                   elif msg == 'missingQuoteQual':
467 arta  1.6             violator = exc.args[1]
468 arta  1.1             print('Missing quote qualifier for parameter ' + "'" + violator + "'" + ' in ' + cfgfile + '.', file=sys.stderr)
469                       rv = bool(1)
470                   elif msg == 'paramNameTooLong':
471 arta  1.6             violator = exc.args[1]
472 arta  1.1             print('Macro name ' + "'" + violator + "' is too long.", file=sys.stderr)
473                       rv = bool(1)
474 arta  1.6         elif msg == 'unknownSection':
475                       violator = exc.args[1]
476                       print('Unknown section ' + "'" + violator + "' in configuration file.", file=sys.stderr)
477                       rv = bool(1)
478 arta  1.1         else:
479                       # re-raise the exception
480                       raise
481           
482 arta  1.6     if not rv:
483                   if not xml is None:
484                       # Process xml.
485                       projRules.extend(list(RULESPREFIX))
486                       projTarget.extend(list(TARGETPREFIX))            
487                       rv = processXML(xml, projRules, projTarget)
488                       projRules.extend(RULESSUFFIX)
489           
490               # Process addenda - these are parameters that are not configurable and must be set in the 
491               # NetDRMS build.
492               if not rv:
493                   iscfg = bool(0)
494                   for key in addenda:
495                       item = key + ' ' + addenda[key]
496                       ppRet = processParam(iscfg, item, regexpQuote, regexp, keymap, defs, cDefs, mDefsGen, mDefsMake, perlConstSection, perlInitSection, platDict, machDict, 'defs')
497                       if ppRet:
498                           break;
499           
500 arta  1.4     # Put information collected in platDict and machDict into mDefs. Must do this here, and not in processParam, since
501               # we need to parse all platform-specific make variables before grouping them into platform categories.
502 arta  1.3     if not rv:
503                   for plat in platDict:
504 arta  1.4             mDefsMake.extend(list('\nifeq ($(JSOC_MACHINE), linux_' + plat.lower() + ')'))
505 arta  1.3             for var in platDict[plat]:
506 arta  1.4                 mDefsMake.extend(list('\n' + var + ' = ' + platDict[plat][var]))
507                       mDefsMake.extend(list('\nendif\n'))
508 arta  1.3                              
509               if not rv:
510                   for mach in machDict:
511 arta  1.4             mDefsMake.extend(list('\nifeq ($(MACHTYPE), ' + mach + ')'))
512 arta  1.7             for var in machDict[mach]:
513                           mDefsMake.extend(list('\n' + var + ' = ' + machDict[mach][var]))
514 arta  1.4             mDefsMake.extend(list('\nendif\n'))
515 arta  1.3                              
516 arta  1.1     return rv
517           
518           def getMgrUIDLine(defs, uidParam):
519               rv = bool(0)
520               
521               cmd = 'id -u ' + defs['SUMS_MANAGER']
522               try:
523                   ret = check_output(cmd, shell=True)
524                   uidParam['q:SUMS_MANAGER_UID'] = ret.decode("utf-8")
525               except ValueError:
526                   print('Unable to run cmd: ' + cmd + '.')
527                   rv = bool(1)
528               except CalledProcessError:
529                   print('Command ' + "'" + cmd + "'" + ' ran improperly.')
530                   rv = bool(1)
531           
532               return rv
533           
534 arta  1.3 def isVersion(maj, min, majDef, minDef):
535               res = 0
536               
537               if maj > majDef or (maj == majDef and min >= minDef):
538                   res = 1
539               
540               return res
541           
542           def configureComps(defs, mDefs):
543               rv = bool(0)
544 arta  1.6     autoConfig = bool(1)
545           
546               if 'AUTOSELCOMP' in defs:
547                   autoConfig = (not defs['AUTOSELCOMP'] == '0')
548 arta  1.3     
549               if autoConfig:
550                   hasicc = bool(0)
551                   hasgcc = bool(0)
552                   hasifort = bool(0)
553                   hasgfort = bool(0)
554                   
555                   # Try icc.
556                   cmd = 'icc -V 2>&1'
557                   try:
558                       ret = check_output(cmd, shell=True)
559                       ret = ret.decode("utf-8")
560                   except CalledProcessError:
561                       print('Command ' + "'" + cmd + "'" + ' ran improperly.')
562                       rv = bool(1)
563                   
564 arta  1.6         if not rv:
565 arta  1.3             regexp = re.compile(r".+Version\s+(\d+)[.](\d+)", re.DOTALL)
566                       matchobj = regexp.match(ret)
567                       if matchobj is None:
568                           raise Exception('unexpectedIccRet', ret)
569                       else:
570                           major = matchobj.group(1)
571                           minor = matchobj.group(2)
572                           if isVersion(int(major), int(minor), ICC_MAJOR, ICC_MINOR):
573                               hasicc = bool(1)
574                       
575                   # Try gcc.
576                   if not hasicc:
577                       cmd = 'gcc -v 2>&1'
578                       try:
579                           ret = check_output(cmd, shell=True)
580                           ret = ret.decode("utf-8")
581                       except CalledProcessError:
582                           print('Command ' + "'" + cmd + "'" + ' ran improperly.')
583                           rv = bool(1)
584           
585                       if rv == bool(0):
586 arta  1.3                 regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
587                           matchobj = regexp.match(ret)
588                           if matchobj is None:
589                               raise Exception('unexpectedGccRet', ret)
590                           else:
591                               major = matchobj.group(1)
592                               minor = matchobj.group(2)
593                               if isVersion(int(major), int(minor), GCC_MAJOR, GCC_MINOR):
594                                   hasgcc = bool(1)
595           
596                   # Try ifort.
597                   cmd = 'ifort -V 2>&1'
598                   try:
599                       ret = check_output(cmd, shell=True)
600                       ret = ret.decode("utf-8")
601                   except CalledProcessError:
602                       print('Command ' + "'" + cmd + "'" + ' ran improperly.')
603                       rv = bool(1)
604           
605 arta  1.6         if not rv:
606 arta  1.3             regexp = re.compile(r".+Version\s+(\d+)\.(\d+)", re.DOTALL)
607                       matchobj = regexp.match(ret)
608                       if matchobj is None:
609                           raise Exception('unexpectedIfortRet', ret)
610                       else:
611                           major = matchobj.group(1)
612                           minor = matchobj.group(2)
613                           if isVersion(int(major), int(minor), IFORT_MAJOR, IFORT_MINOR):
614                               hasifort = bool(1)
615                   
616                   # Try gfortran
617                   if not hasifort:
618                       cmd = 'gfortran -v 2>&1'
619                       try:
620                           ret = check_output(cmd, shell=True)
621                           ret = ret.decode("utf-8")
622                       except CalledProcessError:
623                           print('Command ' + "'" + cmd + "'" + ' ran improperly.')
624                           rv = bool(1)
625           
626                       if rv == bool(0):
627 arta  1.3                 regexp = re.compile(r".+gcc\s+version\s+(\d+)\.(\d+)", re.DOTALL)
628                           matchobj = regexp.match(ret)
629                           if matchobj is None:
630                               raise Exception('unexpectedGfortranRet', ret)
631                           else:
632                               major = matchobj.group(1)
633                               minor = matchobj.group(2)
634                               if isVersion(int(major), int(minor), GFORT_MAJOR, GFORT_MINOR):
635                                   hasgfort = bool(1)
636                   
637                   # Append the compiler make variables to the make file 
638                   if not hasicc and not hasgcc:
639                       print('Fatal error: Acceptable C compiler not found! You will be unable to build the DRMS library.', file=sys.stderr)
640                       rv = bool(1)
641                   elif hasicc:
642                       mDefs.extend(list('\nCOMPILER = icc'))
643                   else:
644                       mDefs.extend(list('\nCOMPILER = gcc'))
645           
646                   if not hasifort and not hasgfort:
647                       print('Warning: Acceptable Fortran compiler not found! Fortran interface will not be built, and you will be unable to build Fortran modules.', file=sys.stderr)
648 arta  1.3         elif hasifort:
649                       mDefs.extend(list('\nFCOMPILER = ifort'))
650                   else:
651                       mDefs.extend(list('\nFCOMPILER = gfortran'))
652               
653                   # Environment overrides. These get written, regardless of the disposition of auto-configuration.
654 arta  1.7         mDefs.extend(list('\nifneq ($(JSOC_COMPILER,))\n  COMPILER = $(JSOC_COMPILER)\nendif'))
655                   mDefs.extend(list('\nifneq ($(JSOC_FCOMPILER,))\n  FCOMPILER = $(JSOC_FCOMPILER)\nendif'))
656 arta  1.3 
657               return rv
658           
659 arta  1.6 def writeParamsFiles(base, cfile, mfile, pfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection):
660 arta  1.1     rv = bool(0)
661 arta  1.4 
662               # Merge mDefsGen, mDefsMake, and mDefsComps into a single string with compiler configuration first, general parameters next, then
663               # make-specific make variables (e.g., third-party library information) last.
664               mDefs = '\n# Compiler Selection\n' + ''.join(mDefsComps) + '\n\n# General Parameters\n' + ''.join(mDefsGen) + '\n\n# Parameters to Configure make\n' + ''.join(mDefsMake)
665 arta  1.1     
666               try:
667                   with open(cfile, 'w') as cout, open(mfile, 'w') as mout, open(pfile, 'w') as pout:
668                       # C file of macros
669 arta  1.2             print(C_PREFIX, file=cout)
670                       print('/* This file contains a set of preprocessor macros - one for each configuration parameter. */\n', file=cout)
671 arta  1.1             buf = '__' + base.upper() + '_H'
672                       print('#ifndef ' + buf, file=cout)
673                       print('#define ' + buf, file=cout)
674                       print(''.join(cDefs), file=cout)
675                       print('#endif', file=cout)
676                       
677                       # Make file of make variables
678 arta  1.2             print(PREFIX, file=mout)
679 arta  1.4             print('# This file contains a set of make-variable values. The first section contains compiler-selection variables, the second contains general configuration variables, and the third section contains variables that configure how make is run.', file=mout)
680                       print(mDefs, file=mout)
681 arta  1.1             
682 arta  1.2             # Perl module
683                       print(PERL_BINPATH, file=pout)
684                       print(PREFIX, file=pout)
685                       print('# This file contains a set of constants - one for each configuration parameter.\n', file=pout)
686                       print(PERL_INTIAL, file=pout)
687 arta  1.1             print(''.join(perlConstSection), file=pout)
688 arta  1.2             print(PERL_FXNS_A, file=pout)
689 arta  1.1             print('sub initialize', file=pout)
690                       print('{', file=pout)
691 arta  1.2             print('  my($self) = shift;', file=pout, end='')
692 arta  1.1             print('', file=pout)
693                       print(''.join(perlInitSection), file=pout)
694 arta  1.2             print('}\n', file=pout)
695                       print(PERL_FXNS_B, file=pout)
696 arta  1.1     except IOError as exc:
697 arta  1.6         type, value, traceback = sys.exc_info()
698                   print(exc.strerror, file=sys.stderr)
699                   print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)        
700                   rv = bool(1)
701           
702               return rv
703           
704           def writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget):
705               rv = bool(0)
706           
707               try:
708                   if projCfg:
709                       with open(pCfile, 'w') as cout:
710                           # configure
711                           print(''.join(projCfg), file=cout)
712                   
713                   if projMkRules:
714                       with open(pMfile, 'w') as mout:
715                           # make_basic.mk
716                           print(PREFIX, file=mout)
717                           print(''.join(projMkRules), file=mout)
718 arta  1.6     
719                   if projRules:
720                       with open(pRfile, 'w') as rout:
721                           # Rules.mk
722                           print(PREFIX, file=rout)
723                           print(''.join(projRules), file=rout)
724                   
725                   if projTarget:
726                       with open(pTfile, 'w') as tout:
727                           # target.mk
728                           print(PREFIX, file=tout)
729                           print(''.join(projTarget), file=tout)    
730               except IOError as exc:
731                   type, value, traceback = sys.exc_info()
732                   print(exc.strerror, file=sys.stderr)
733                   print('Unable to open ' + "'" + value.filename + "'.", file=sys.stderr)
734 arta  1.1         rv = bool(1)
735           
736 arta  1.6     if not rv:
737                   try:
738                       os.chmod(pCfile, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
739                   except OSError as exc:
740                       print(exc.strerror, file=sys.stderr)
741                       rv = bool(1)
742           
743 arta  1.1     return rv
744 arta  1.3 
745 arta  1.6 def configureNet(cfgfile, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, base, keymap):
746 arta  1.1     rv = bool(0)
747               
748               defs = {}
749               cDefs = list()
750 arta  1.4     mDefsGen = list()
751               mDefsMake = list()
752               mDefsComps = list()
753 arta  1.6     projCfg = list()
754               projMkRules = list()
755               projRules = list()
756               projTarget = list()
757 arta  1.1     perlConstSection = list()
758               perlInitSection = list()
759 arta  1.2     addenda = {}
760               
761 arta  1.6     # There are three parameters that were not included in the original config.local parameter set, for some reason.
762               # Due to this omission, then are not configurable, and must be set in the script.
763 arta  1.2     addenda['a:USER'] = 'NULL'
764               addenda['a:PASSWD'] = 'NULL'
765               addenda['p:DSDS_SUPPORT'] = '0'
766 arta  1.6     
767               # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
768 arta  1.2     addenda['a:BUILD_TYPE'] = 'NETDRMS' # Means a non-Stanford build. This will set two additional macros used by make:
769                                                   #   __LOCALIZED_DEFS__ and NETDRMS_BUILD. The former is to support legacy code
770                                                   #   which incorrectly used this macro, and the latter is for future use. 
771                                                   #   __LOCALIZED_DEFS__ is deprecated and should not be used in new code.
772 arta  1.1 
773               try:
774                   with open(cfgfile, 'r') as fin:
775 arta  1.3             # Process configuration parameters
776 arta  1.6             rv = parseConfig(fin, keymap, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection)
777                       if not rv:
778 arta  1.3                 # Must add a parameter for the SUMS_MANAGER UID (for some reason). This must be done after the
779                           # config file is processed since an input to getMgrUIDLine() is one of the config file's
780                           # parameter values.
781 arta  1.1                 uidParam = {}
782                           rv = getMgrUIDLine(defs, uidParam)
783                           if rv == bool(0):
784 arta  1.6                     rv = parseConfig(None, keymap, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection)
785 arta  1.3                 
786                       # Configure the compiler-selection make variables.
787 arta  1.6             if not rv:
788 arta  1.4                 rv = configureComps(defs, mDefsComps)
789 arta  1.1 
790 arta  1.3             # Write out the parameter files.
791 arta  1.6             if not rv:
792                           rv = writeParamsFiles(base, cfile, mfile, pfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection)
793           
794                       # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
795                       if not rv:
796                           rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
797           
798 arta  1.1     except IOError as exc:
799 arta  1.6         print(exc.strerror, file=sys.stderr)
800                   print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
801 arta  1.3     except Exception as exc:
802                   type, msg = exc.args
803                   if type == 'unexpectedIccRet':
804                       print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
805                       rv = bool(1)
806                   elif type == 'unexpectedGccRet':
807                       print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
808                       rv = bool(1)
809                   elif type == 'unexpectedIfortRet':
810                       print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
811                       rv = bool(1)
812                   elif type == 'unexpectedGfortranRet':
813                       print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
814                       rv = bool(1)
815                   else:
816                       # re-raise the exception
817                       raise
818 arta  1.1         
819 arta  1.2     return rv
820 arta  1.1 
821 arta  1.6 def configureSdp(cfgfile, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, base):
822 arta  1.1     rv = bool(0)
823               
824               defs = {}
825               cDefs = list()
826 arta  1.5     mDefsGen = list()
827               mDefsMake = list()
828 arta  1.6     projCfg = list()
829               projMkRules = list()
830               projRules = list()
831               projTarget = list()
832 arta  1.5     mDefsComps = list()
833 arta  1.1     perlConstSection = list()
834               perlInitSection = list()
835 arta  1.2     addenda = {}
836               
837 arta  1.6     # There are three parameters that were not included in the original config.local parameter set, for some reason.
838               # Due to this omission, then are not configurable, and must be set in the script.
839 arta  1.5     addenda['a:USER'] = 'NULL'
840               addenda['a:PASSWD'] = 'NULL'
841               addenda['p:DSDS_SUPPORT'] = '1'
842 arta  1.6     
843               # This parameter is not configurable. BUILD_TYPE is used to distinguish between a NetDRMS and an JSOC-SDP build.
844 arta  1.5     addenda['a:BUILD_TYPE'] = 'JSOC_SDP' # Means a Stanford build. This will set one additional macro used by make: JSOC_SDP_BUILD.
845 arta  1.1     
846               try:
847                   with open(cfgfile, 'r') as fin:
848 arta  1.6             rv = parseConfig(fin, None, addenda, defs, cDefs, mDefsGen, mDefsMake, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection)
849                       
850                       if not rv:
851 arta  1.2                 # Must add a parameter for the SUMS_MANAGER UID (for some reason)
852                           uidParam = {}
853                           rv = getMgrUIDLine(defs, uidParam)
854 arta  1.6                 if not rv:
855                               rv = parseConfig(None, None, uidParam, defs, cDefs, mDefsGen, None, projCfg, projMkRules, projRules, projTarget, perlConstSection, perlInitSection)
856           
857 arta  1.5                 # Configure the compiler-selection make variables.
858 arta  1.6                 if not rv:
859 arta  1.5                     rv = configureComps(defs, mDefsComps)
860 arta  1.3                 
861 arta  1.6                 # Write out the parameter files.
862                           if not rv:
863                               rv = writeParamsFiles(base, cfile, mfile, pfile, cDefs, mDefsGen, mDefsMake, mDefsComps, perlConstSection, perlInitSection)
864           
865                           # Write out the project-specific make files (make_basic.mk, Rules.mk, and target.mk).
866                           if not rv:
867                               rv = writeProjFiles(pCfile, pMfile, pRfile, pTfile, projCfg, projMkRules, projRules, projTarget)
868 arta  1.1     except IOError as exc:
869 arta  1.6         print(exc.strerror, file=sys.stderr)
870                   print('Unable to read configuration file ' + cfgfile + '.', file=sys.stderr)
871 arta  1.5     except Exception as exc:
872 arta  1.6         type = exc.args[0]
873 arta  1.5         if type == 'unexpectedIccRet':
874 arta  1.6             msg = exc.args[1]
875 arta  1.5             print('icc -V returned this unexpected message:\n' + msg, file=sys.stderr)
876                       rv = bool(1)
877                   elif type == 'unexpectedGccRet':
878 arta  1.6             msg = exc.args[1]
879 arta  1.5             print('gcc -v returned this unexpected message:\n' + msg, file=sys.stderr)
880                       rv = bool(1)
881                   elif type == 'unexpectedIfortRet':
882 arta  1.6             msg = exc.args[1]
883 arta  1.5             print('ifort -V returned this unexpected message:\n' + msg, file=sys.stderr)
884                       rv = bool(1)
885                   elif type == 'unexpectedGfortranRet':
886 arta  1.6             msg = exc.args[1]
887 arta  1.5             print('gfortran -v returned this unexpected message:\n' + msg, file=sys.stderr)
888                       rv = bool(1)
889                   else:
890                       # re-raise the exception
891                       raise
892                   
893 arta  1.2     return rv
894           
895 arta  1.1 # Beginning of program
896           rv = RET_SUCCESS
897           net = bool(1)
898           
899           # Parse arguments
900           if __name__ == "__main__":
901               optD = GetArgs(sys.argv[1:])
902           
903           if not(optD is None):
904               # Ensure we are configuring a DRMS tree
905               cdir = os.path.realpath(os.getcwd())
906               versfile = cdir + '/base/' + VERS_FILE
907           
908               if not os.path.isfile(versfile):
909                   rv = RET_NOTDRMS
910           
911           # Determine whether we are localizing a Stanford build, or a NetDRMS build. If configsdp.txt exists, then
912           # it is a Stanford build, otherwise it is a NetDRMS build.
913           if rv == RET_SUCCESS:
914               stanfordFile = cdir + '/' + SDP_CFG
915               if os.path.isfile(stanfordFile):
916 arta  1.1         net = bool(0)
917               
918               cfile = optD['dir'] + '/' + optD['base'] + '.h'
919               mfile = optD['dir'] + '/' + optD['base'] + '.mk'
920               pfile = optD['dir'] + '/' + optD['base'] + '.pm'
921 arta  1.6     pCfile = optD['dir'] + '/configure'
922               pMfile = optD['dir'] + '/make_basic.mk'
923               pRfile = optD['dir'] + '/Rules.mk'
924               pTfile = optD['dir'] + '/target.mk'
925 arta  1.1 
926               if net:
927                   try:
928                       with open(NET_CFGMAP, 'r') as fin:
929                           regexpComm = re.compile(r"^\s*#")
930                           regexp = re.compile(r"^\s*(\S+)\s+(\w:\S+)")
931                           # Must map from config.local namespace to DRMS namespace (e.g., the names used for the C macros)
932                           keymap = {}
933                           for line in fin:
934                               matchobj = regexpComm.match(line)
935                               if not matchobj is None:
936                                   # Skip comment line
937                                   continue
938           
939                               matchobj = regexp.match(line)
940                               if not(matchobj is None):
941                                   # We have a key-value line
942                                   key = matchobj.group(1)
943                                   val = matchobj.group(2)
944                                   keymap[key] = val
945                   except OSError:
946 arta  1.1             sys.stderr.write('Unable to read configuration map-file ' + NET_CFGMAP + '.')
947                       rv = bool(1)
948           
949                   # We also need to set the UID of the SUMS manager. We have the name of the
950                   # SUMS manager (it is in the configuration file)
951 arta  1.6         configureNet(NET_CFG, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, optD['base'], keymap)
952 arta  1.1     else:
953 arta  1.6         configureSdp(SDP_CFG, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
954 arta  1.1     
955               
956           

Karen Tian
Powered by
ViewCVS 0.9.4