LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
Classes | Functions
lsst.sconsUtils.builders Namespace Reference

Classes

class  DoxygenBuilder
 A callable to be used as an SCons Action to run Doxygen. More...
 

Functions

def SharedLibraryIncomplete
 
def SwigLoadableModule
 
def SourcesForSharedLibrary
 Prepare the list of files to be passed to a SharedLibrary constructor. More...
 
def filesToTag
 
def BuildETags
 Build Emacs tags (see man etags for more information). More...
 
def CleanTree
 Remove files matching the argument list starting at dir when scons is invoked with -c/–clean and no explicit targets are listed. More...
 
def ProductDir
 
def Doxygen
 Generate a Doxygen config file and run Doxygen on it. More...
 
def VersionModule
 

Function Documentation

def lsst.sconsUtils.builders.BuildETags (   env,
  root = None,
  fileRegex = None,
  ignoreDirs = None 
)

Build Emacs tags (see man etags for more information).

Files are chosen if they match fileRegex; toplevel directories in list ignoreDirs are ignored This routine won't do anything unless you specified a "TAGS" target

Definition at line 164 of file builders.py.

165 def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None):
166  toTag = filesToTag(root, fileRegex, ignoreDirs)
167  if toTag:
168  return env.Command("TAGS", toTag, "etags -o $TARGET $SOURCES")
169 
170 
171 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
def BuildETags
Build Emacs tags (see man etags for more information).
Definition: builders.py:164
def lsst.sconsUtils.builders.CleanTree (   self,
  files,
  dir = ".",
  recurse = True,
  verbose = False 
)

Remove files matching the argument list starting at dir when scons is invoked with -c/–clean and no explicit targets are listed.

E.g. CleanTree(r"*~ core")

If recurse is True, recursively descend the file system; if verbose is True, print each filename after deleting it

Definition at line 182 of file builders.py.

183 def CleanTree(self, files, dir=".", recurse=True, verbose=False):
184  #
185  # Generate command that we may want to execute
186  #
187  files_expr = ""
188  for file in SCons.Script.Split(files):
189  if files_expr:
190  files_expr += " -o "
191 
192  files_expr += "-name %s" % re.sub(r"(^|[^\\])([[*])", r"\1\\\2", file) # quote unquoted * and []
193  #
194  # don't use xargs --- who knows what needs quoting?
195  #
196  action = "find %s" % dir
197  action += r" \( -name .svn -prune -o -name \* \) "
198  if not recurse:
199  action += " ! -name . -prune"
200 
201  file_action = "rm -f"
202 
203  action += r" \( %s \) -exec %s {} \;" % \
204  (files_expr, file_action)
205 
206  if verbose:
207  action += " -print"
208  #
209  # Clean up scons files --- users want to be able to say scons -c and get a clean copy
210  # We can't delete .sconsign.dblite if we use "scons clean" instead of "scons --clean",
211  # so the former is no longer supported.
212  #
213  action += " ; rm -rf .sconf_temp .sconsign.dblite .sconsign.tmp config.log"
214  #
215  # Do we actually want to clean up? We don't if the command is e.g. "scons -c install"
216  #
217  if "clean" in SCons.Script.COMMAND_LINE_TARGETS:
218  state.log.fail("'scons clean' is no longer supported; please use 'scons --clean'.")
219  elif not SCons.Script.COMMAND_LINE_TARGETS and self.GetOption("clean"):
220  self.Execute(self.Action([action]))
221 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
222 
223 
224 # @brief Return a product's PRODUCT_DIR, or None
@memberOf(SConsEnvironment)
def memberOf
A Python decorator that injects functions into a class.
Definition: utils.py:157
def CleanTree
Remove files matching the argument list starting at dir when scons is invoked with -c/–clean and no e...
Definition: builders.py:182
def lsst.sconsUtils.builders.Doxygen (   self,
  config,
  kw 
)

Generate a Doxygen config file and run Doxygen on it.

Rather than parse a complete Doxygen config file for SCons sources and targets, this Doxygen builder builds a Doxygen config file, adding INPUT, FILE_PATTERNS, RECUSRIVE, EXCLUDE, XX_OUTPUT and GENERATE_XX options (and possibly others) to an existing proto-config file. Generated settings will override those in the proto-config file.

Parameters
configA Doxygen config file, usually with the extension .conf.in; a new file with the .in removed will be generated and passed to Doxygen. Settings in the original config file will be overridden by those generated by this method.
inputsA sequence of folders or files to be passed as the INPUT setting for Doxygen. This list will be turned into absolute paths by SCons, so the "#folder" syntax will work. Otherwise, the list is passed in as-is, but the builder will also examine those directories to find which source files the Doxygen output actually depends on.
patternsA sequence of glob patterns for the FILE_PATTERNS Doxygen setting. This will be passed directly to Doxygen, but it is also used to determine which source files should be considered dependencies.
recursiveWhether the inputs should be searched recursively (used for the Doxygen RECURSIVE setting).
outputsA sequence of output formats which will also be used as output directories.
excludeA sequence of folders or files (not globs) to be ignored by Doxygen (the Doxygen EXCLUDE setting). Hidden directories are automatically ignored.
includesA sequence of Doxygen config files to include. These will automatically be separated into paths and files to fill in the @INCLUDE_PATH and @INCLUDE settings.
useTagsA sequence of Doxygen tag files to use. It will be assumed that the html directory for each tag file is in an "html" subdirectory in the same directory as the tag file.
makeTagA string indicating the name of a tag file to be generated.
projectNameSets the Doxygen PROJECT_NAME setting.
projectNumberSets the Doxygen PROJECT_NUMBER setting.
excludeSwigIf True (default), looks for SWIG .i files in the input directories and adds Python and C++ files generated by SWIG to the list of files to exclude. For this to work, the SWIG-generated filenames must be the default ones ("module.i" generates "module.py" and "moduleLib_wrap.cc").
Note
When building documentation from a clean source tree, generated source files (like headers generated with M4) will not be included among the dependencies, because they aren't present when we walk the input folders. The workaround is just to build the docs after building the source.

Definition at line 454 of file builders.py.

455 def Doxygen(self, config, **kw):
456  inputs = [d for d in ["#doc", "#include", "#python", "#src"]
457  if os.path.exists(SCons.Script.Entry(d).abspath)]
458  defaults = {
459  "inputs": inputs,
460  "recursive": True,
461  "patterns": ["*.h", "*.cc", "*.py", "*.dox"],
462  "outputs": ["html", "xml"],
463  "excludes": [],
464  "includes": [],
465  "useTags": [],
466  "makeTag": None,
467  "projectName": None,
468  "projectNumber": None,
469  "excludeSwig": True
470  }
471  for k in defaults:
472  if kw.get(k) is None:
473  kw[k] = defaults[k]
474  builder = DoxygenBuilder(**kw)
475  return builder(self, config)
476 
477 
@memberOf(SConsEnvironment)
def memberOf
A Python decorator that injects functions into a class.
Definition: utils.py:157
def Doxygen
Generate a Doxygen config file and run Doxygen on it.
Definition: builders.py:454
A callable to be used as an SCons Action to run Doxygen.
Definition: builders.py:251
def lsst.sconsUtils.builders.filesToTag (   root = None,
  fileRegex = None,
  ignoreDirs = None 
)

Definition at line 124 of file builders.py.

125 def filesToTag(root=None, fileRegex=None, ignoreDirs=None):
126  if root is None:
127  root = "."
128  if fileRegex is None:
129  fileRegex = r"^[a-zA-Z0-9_].*\.(cc|h(pp)?|py)$"
130  if ignoreDirs is None:
131  ignoreDirs = ["examples", "tests"]
132 
133  if "TAGS" not in SCons.Script.COMMAND_LINE_TARGETS:
134  return []
135 
136  files = []
137  for dirpath, dirnames, filenames in os.walk(root):
138  if dirpath == ".":
139  dirnames[:] = [d for d in dirnames if not re.search(r"^(%s)$" % "|".join(ignoreDirs), d)]
140 
141  dirnames[:] = [d for d in dirnames if not re.search(r"^(\.svn)$", d)] # ignore .svn tree
142  #
143  # List of possible files to tag, but there's some cleanup required for machine-generated files
144  #
145  candidates = [f for f in filenames if re.search(fileRegex, f)]
146  #
147  # Remove files generated by swig
148  #
149  for swigFile in [f for f in filenames if re.search(r"\.i$", f)]:
150  name = os.path.splitext(swigFile)[0]
151  candidates = [f for f in candidates if not re.search(r"%s(_wrap\.cc?|\.py)$" % name, f)]
152 
153  files += [os.path.join(dirpath, f) for f in candidates]
154 
155  return files
156 
def lsst.sconsUtils.builders.ProductDir (   env,
  product 
)

Definition at line 225 of file builders.py.

226 def ProductDir(env, product):
227  from . import eupsForScons
228  global _productDirs
229  try:
230  _productDirs
231  except:
232  try:
233  _productDirs = eupsForScons.productDir(eupsenv=eupsForScons.getEups())
234  except TypeError: # old version of eups (pre r18588)
235  _productDirs = None
236  if _productDirs:
237  pdir = _productDirs.get(product)
238  else:
239  pdir = eupsForScons.productDir(product)
240  if pdir == "none":
241  pdir = None
242  return pdir
243 
244 
245 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
def lsst.sconsUtils.builders.SharedLibraryIncomplete (   self,
  target,
  source,
  keywords 
)

Definition at line 23 of file builders.py.

23 
24 def SharedLibraryIncomplete(self, target, source, **keywords):
25  myenv = self.Clone()
26  if myenv['PLATFORM'] == 'darwin':
27  myenv['SHLINKFLAGS'] += ["-undefined", "suppress", "-flat_namespace", "-headerpad_max_install_names"]
28  return myenv.SharedLibrary(target, source, **keywords)
29 
30 
31 # @brief Like LoadableModule, but don't insist that all symbols are resolved, and set
32 # some SWIG-specific flags.
@memberOf(SConsEnvironment)
def memberOf
A Python decorator that injects functions into a class.
Definition: utils.py:157
def lsst.sconsUtils.builders.SourcesForSharedLibrary (   self,
  files 
)

Prepare the list of files to be passed to a SharedLibrary constructor.

In particular, ensure that any files listed in env.NoOptFiles (set by the command line option noOptFile="file1 file2") are built without optimisation and files listed in env.optFiles are built with optimisation

The usage pattern in an SConscript file is: ccFiles = env.SourcesForSharedLibrary(Glob("../src/*/*.cc")) env.SharedLibrary('afw', ccFiles, LIBS=env.getLibs("self")))

This is automatically used by scripts.BasicSConscript.lib().

Definition at line 66 of file builders.py.

66 
67 def SourcesForSharedLibrary(self, files):
68 
69  files = [SCons.Script.File(file) for file in files]
70 
71  if not (self.get("optFiles") or self.get("noOptFiles")):
72  files.sort()
73  return files
74 
75  if self.get("optFiles"):
76  optFiles = self["optFiles"].replace(".", r"\.") # it'll be used in an RE
77  optFiles = SCons.Script.Split(optFiles.replace(",", " "))
78  optFilesRe = "/(%s)$" % "|".join(optFiles)
79  else:
80  optFilesRe = None
81 
82  if self.get("noOptFiles"):
83  noOptFiles = self["noOptFiles"].replace(".", r"\.") # it'll be used in an RE
84  noOptFiles = SCons.Script.Split(noOptFiles.replace(",", " "))
85  noOptFilesRe = "/(%s)$" % "|".join(noOptFiles)
86  else:
87  noOptFilesRe = None
88 
89  if self.get("opt"):
90  opt = int(self["opt"])
91  else:
92  opt = 0
93 
94  if opt == 0:
95  opt = 3
96 
97  CCFLAGS_OPT = re.sub(r"-O(\d|s)\s*", "-O%d " % opt, " ".join(self["CCFLAGS"]))
98  CCFLAGS_NOOPT = re.sub(r"-O(\d|s)\s*", "-O0 ", " ".join(self["CCFLAGS"])) # remove -O flags from CCFLAGS
99 
100  sources = []
101  for ccFile in files:
102  if optFilesRe and re.search(optFilesRe, ccFile.abspath):
103  self.SharedObject(ccFile, CCFLAGS=CCFLAGS_OPT)
104  ccFile = os.path.splitext(ccFile.abspath)[0] + self["SHOBJSUFFIX"]
105  elif noOptFilesRe and re.search(noOptFilesRe, ccFile.abspath):
106  self.SharedObject(ccFile, CCFLAGS=CCFLAGS_NOOPT)
107  ccFile = os.path.splitext(ccFile.abspath)[0] + self["SHOBJSUFFIX"]
108 
109  sources.append(ccFile)
110 
111  sources.sort()
112  return sources
113 
114 
115 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
116 
117 #
118 # @brief Return a list of files that need to be scanned for tags, starting at directory root
119 #
120 # These tags are for advanced Emacs users, and should not be confused with SVN tags or Doxygen tags.
121 #
122 # Files are chosen if they match fileRegex; toplevel directories in list ignoreDirs are ignored
123 # This routine won't do anything unless you specified a "TAGS" target
#
def SourcesForSharedLibrary
Prepare the list of files to be passed to a SharedLibrary constructor.
Definition: builders.py:66
def lsst.sconsUtils.builders.SwigLoadableModule (   self,
  target,
  source,
  keywords 
)

Definition at line 33 of file builders.py.

33 
34 def SwigLoadableModule(self, target, source, **keywords):
35  myenv = self.Clone()
36  if myenv['PLATFORM'] == 'darwin':
37  myenv.Append(LDMODULEFLAGS=["-undefined", "suppress",
38  "-flat_namespace", "-headerpad_max_install_names"])
39  #
40  # Swig-generated .cc files cast pointers to long longs and back,
41  # which is illegal. This flag tells g++ about the sin
42  #
43  try:
44  if myenv.whichCc == "gcc":
45  myenv.Append(CCFLAGS=["-fno-strict-aliasing"])
46  except AttributeError:
47  pass
48  return myenv.LoadableModule(target, source, **keywords)
49 
50 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
51 
def lsst.sconsUtils.builders.VersionModule (   self,
  filename,
  versionString = None 
)

Definition at line 478 of file builders.py.

479 def VersionModule(self, filename, versionString=None):
480  if versionString is None:
481  for n in ("git", "hg", "svn",):
482  if os.path.isdir(".%s" % n):
483  versionString = n
484 
485  if not versionString:
486  versionString = "git"
487 
488  def calcMd5(filename):
489  try:
490  import hashlib
491  md5 = hashlib.md5("\n".join(open(filename).readlines())).hexdigest()
492  except IOError:
493  md5 = None
494 
495  return md5
496 
497  oldMd5 = calcMd5(filename)
498 
499  def makeVersionModule(target, source, env):
500  try:
501  version = determineVersion(state.env, versionString)
502  except RuntimeError:
503  version = "unknown"
504  parts = version.split("+")
505 
506  names = []
507  with open(target[0].abspath, "w") as outFile:
508  outFile.write("#--------- This file is automatically generated by LSST's sconsUtils ---------#\n")
509 
510  what = "__version__"
511  outFile.write("%s = '%s'\n" % (what, version))
512  names.append(what)
513 
514  what = "__repo_version__"
515  outFile.write("%s = '%s'\n" % (what, parts[0]))
516  names.append(what)
517 
518  what = "__fingerprint__"
519  outFile.write("%s = '%s'\n" % (what, getFingerprint(versionString)))
520  names.append(what)
521 
522  try:
523  info = tuple(int(v) for v in parts[0].split("."))
524  what = "__version_info__"
525  names.append(what)
526  outFile.write("%s = %r\n" % (what, info))
527  except ValueError:
528  pass
529 
530  if len(parts) > 1:
531  try:
532  what = "__rebuild_version__"
533  outFile.write("%s = %s\n" % (what, int(parts[1])))
534  names.append(what)
535  except ValueError:
536  pass
537 
538  what = "__dependency_versions__"
539  names.append(what)
540  outFile.write("%s = {\n" % (what))
541  for name, mod in env.dependencies.packages.items():
542  if mod is None:
543  outFile.write(" '%s': None,\n" % name)
544  elif hasattr(mod.config, "version"):
545  outFile.write(" '%s': '%s',\n" % (name, mod.config.version))
546  else:
547  outFile.write(" '%s': 'unknown',\n" % name)
548  outFile.write("}\n")
549 
550  outFile.write("__all__ = %r\n" % (tuple(names),))
551 
552  if calcMd5(target[0].abspath) != oldMd5: # only print if something's changed
553  state.log.info("makeVersionModule([\"%s\"], [])" % str(target[0]))
554 
555  result = self.Command(filename, [], self.Action(makeVersionModule, strfunction=lambda *args: None))
556 
557  self.AlwaysBuild(result)
558  return result