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.8 # A Stanford user can override the parameters in configsdp.txt by copying that file to config.local,
954 # and then editing config.local. So, if config.local exists, use that.
955 if os.path.isfile(cdir + '/' + NET_CFG):
956 configureSdp(NET_CFG, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
957 else:
958 configureSdp(SDP_CFG, cfile, mfile, pfile, pCfile, pMfile, pRfile, pTfile, optD['base'])
|