LSSTApplications  16.0-10-g0ee56ad+4,16.0-11-ga33d1f2+4,16.0-12-g3ef5c14+2,16.0-12-g71e5ef5+17,16.0-12-gbdf3636+2,16.0-13-g118c103+2,16.0-13-g8f68b0a+2,16.0-15-gbf5c1cb+3,16.0-16-gfd17674+2,16.0-17-g7c01f5c+2,16.0-18-g0a50484,16.0-20-ga20f992+7,16.0-21-g0e05fd4+5,16.0-21-g15e2d33+3,16.0-22-g62d8060+3,16.0-22-g847a80f+3,16.0-25-gf00d9b8,16.0-28-g3990c221+3,16.0-3-gf928089+2,16.0-32-g88a4f23+4,16.0-34-gd7987ad+2,16.0-37-gc7333cb+1,16.0-4-g10fc685+1,16.0-4-g18f3627+25,16.0-4-g5f3a788+25,16.0-5-gaf5c3d7+3,16.0-5-gcc1f4bb,16.0-6-g3b92700+3,16.0-6-g4412fcd+2,16.0-6-g7235603+3,16.0-69-g2562ce1b+1,16.0-7-g0913a87,16.0-8-g14ebd58+3,16.0-8-g2df868b,16.0-8-g4cec79c+5,16.0-8-gadf6c7a,16.0-82-g59ec2a54a,16.0-9-g5400cdc+1,16.0-9-ge6233d7+4,master-g2880f2d8cf+2,v17.0.rc1
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 (self, target, source, keywords)
 
def Pybind11LoadableModule (self, target, source, keywords)
 
def SourcesForSharedLibrary (self, files)
 Prepare the list of files to be passed to a SharedLibrary constructor. More...
 
def filesToTag (root=None, fileRegex=None, ignoreDirs=None)
 
def BuildETags (env, root=None, fileRegex=None, ignoreDirs=None)
 Build Emacs tags (see man etags for more information). More...
 
def CleanTree (self, filePatterns, dirPatterns="", directory=".", verbose=False)
 Remove files matching the argument list starting at directory when scons is invoked with -c/–clean and no explicit targets are listed. More...
 
def ProductDir (env, product)
 
def Doxygen (self, config, kw)
 Generate a Doxygen config file and run Doxygen on it. More...
 
def VersionModule (self, filename, versionString=None)
 

Function Documentation

◆ BuildETags()

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 154 of file builders.py.

154 def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None):
155  toTag = filesToTag(root, fileRegex, ignoreDirs)
156  if toTag:
157  return env.Command("TAGS", toTag, "etags -o $TARGET $SOURCES")
158 
159 
160 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
161 
def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None)
Build Emacs tags (see man etags for more information).
Definition: builders.py:154
def filesToTag(root=None, fileRegex=None, ignoreDirs=None)
Definition: builders.py:114

◆ CleanTree()

def lsst.sconsUtils.builders.CleanTree (   self,
  filePatterns,
  dirPatterns = "",
  directory = ".",
  verbose = False 
)

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

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

dirPatterns allows the specification of directories to be removed If verbose is True, print each filename after deleting it

Definition at line 172 of file builders.py.

172 def CleanTree(self, filePatterns, dirPatterns="", directory=".", verbose=False):
173 
174  def genFindCommand(patterns, directory, verbose, filesOnly):
175  # Generate find command to clean up (find-glob) patterns, either files
176  # or directories.
177  expr = ""
178  for pattern in SCons.Script.Split(patterns):
179  if expr != "":
180  expr += " -o "
181  # Quote unquoted * and [
182  expr += "-name %s" % re.sub(r"(^|[^\\])([\[*])", r"\1\\\2", pattern)
183  if filesOnly:
184  expr += " -type f"
185  else:
186  expr += " -type d -prune"
187 
188  command = "find " + directory
189  # Don't look into .svn or .git directories to save time.
190  command += r" \( -name .svn -prune -o -name .git -prune -o -name \* \) "
191  command += r" \( " + expr + r" \)"
192  if filesOnly:
193  command += r" -exec rm -f {} \;"
194  else:
195  command += r" -exec rm -rf {} \;"
196  if verbose:
197  command += " -print"
198  return command
199 
200  action = genFindCommand(filePatterns, directory, verbose, filesOnly=True)
201 
202  # Clean up scons files --- users want to be able to say scons -c and get a
203  # clean copy.
204  # We can't delete .sconsign.dblite if we use "scons clean" instead of
205  # "scons --clean", so the former is no longer supported.
206  action += " ; rm -rf .sconf_temp .sconsign.dblite .sconsign.tmp config.log"
207 
208  if dirPatterns != "":
209  action += " ; "
210  action += genFindCommand(dirPatterns, directory, verbose, filesOnly=False)
211  # Do we actually want to clean up? We don't if the command is e.g.
212  # "scons -c install"
213  if "clean" in SCons.Script.COMMAND_LINE_TARGETS:
214  state.log.fail("'scons clean' is no longer supported; please use 'scons --clean'.")
215  elif not SCons.Script.COMMAND_LINE_TARGETS and self.GetOption("clean"):
216  self.Execute(self.Action([action]))
217 
218 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
219 
220 
221 # @brief Return a product's PRODUCT_DIR, or None
222 @memberOf(SConsEnvironment)
def CleanTree(self, filePatterns, dirPatterns="", directory=".", verbose=False)
Remove files matching the argument list starting at directory when scons is invoked with -c/–clean a...
Definition: builders.py:172
def memberOf(cls, name=None)
A Python decorator that injects functions into a class.
Definition: utils.py:185

◆ Doxygen()

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 453 of file builders.py.

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

◆ filesToTag()

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

Definition at line 114 of file builders.py.

114 def filesToTag(root=None, fileRegex=None, ignoreDirs=None):
115  if root is None:
116  root = "."
117  if fileRegex is None:
118  fileRegex = r"^[a-zA-Z0-9_].*\.(cc|h(pp)?|py)$"
119  if ignoreDirs is None:
120  ignoreDirs = ["examples", "tests"]
121 
122  if "TAGS" not in SCons.Script.COMMAND_LINE_TARGETS:
123  return []
124 
125  files = []
126  for dirpath, dirnames, filenames in os.walk(root):
127  if dirpath == ".":
128  dirnames[:] = [d for d in dirnames if not re.search(r"^(%s)$" % "|".join(ignoreDirs), d)]
129 
130  dirnames[:] = [d for d in dirnames if not re.search(r"^(\.svn)$", d)] # ignore .svn tree
131  #
132  # List of possible files to tag, but there's some cleanup required for machine-generated files
133  #
134  candidates = [f for f in filenames if re.search(fileRegex, f)]
135  #
136  # Remove files generated by swig
137  #
138  for swigFile in [f for f in filenames if f.endswith(".i")]:
139  name = os.path.splitext(swigFile)[0]
140  candidates = [f for f in candidates if not re.search(r"%s(_wrap\.cc?|\.py)$" % name, f)]
141 
142  files += [os.path.join(dirpath, f) for f in candidates]
143 
144  return files
145 
146 
def filesToTag(root=None, fileRegex=None, ignoreDirs=None)
Definition: builders.py:114

◆ ProductDir()

def lsst.sconsUtils.builders.ProductDir (   env,
  product 
)

Definition at line 223 of file builders.py.

223 def ProductDir(env, product):
224  from . import eupsForScons
225  global _productDirs
226  try:
227  _productDirs
228  except Exception:
229  try:
230  _productDirs = eupsForScons.productDir(eupsenv=eupsForScons.getEups())
231  except TypeError: # old version of eups (pre r18588)
232  _productDirs = None
233  if _productDirs:
234  pdir = _productDirs.get(product)
235  else:
236  pdir = eupsForScons.productDir(product)
237  if pdir == "none":
238  pdir = None
239  return pdir
240 
241 
242 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
243 
def ProductDir(env, product)
Definition: builders.py:223

◆ Pybind11LoadableModule()

def lsst.sconsUtils.builders.Pybind11LoadableModule (   self,
  target,
  source,
  keywords 
)

Definition at line 32 of file builders.py.

32 def Pybind11LoadableModule(self, target, source, **keywords):
33  myenv = self.Clone()
34  myenv.Append(CCFLAGS=["-fvisibility=hidden"])
35  if myenv['PLATFORM'] == 'darwin':
36  myenv.Append(LDMODULEFLAGS=["-undefined", "suppress",
37  "-flat_namespace", "-headerpad_max_install_names"])
38  return myenv.LoadableModule(target, source, **keywords)
39 
40 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
41 
42 
def Pybind11LoadableModule(self, target, source, keywords)
Definition: builders.py:32

◆ SharedLibraryIncomplete()

def lsst.sconsUtils.builders.SharedLibraryIncomplete (   self,
  target,
  source,
  keywords 
)

Definition at line 22 of file builders.py.

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

◆ SourcesForSharedLibrary()

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 57 of file builders.py.

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

◆ VersionModule()

def lsst.sconsUtils.builders.VersionModule (   self,
  filename,
  versionString = None 
)

Definition at line 477 of file builders.py.

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