LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
dependencies.py
Go to the documentation of this file.
1 ##
2 # @file dependencies.py
3 #
4 # Dependency configuration and definition.
5 #
6 # @defgroup sconsUtilsDependencies Dependencies and Configuration
7 # @{
8 ##
9 
10 import os.path
11 import collections
12 import imp
13 import sys
14 import SCons.Script
15 import eupsForScons
16 from SCons.Script.SConscript import SConsEnvironment
17 
18 from . import installation
19 from . import state
20 
21 ##
22 # @brief Recursively configure a package using ups/.cfg files.
23 #
24 # Aliased as lsst.sconsUtils.configure().
25 #
26 # Usually, LSST packages will call this function through scripts.BasicSConstruct.
27 #
28 # @param packageName Name of the package being built; must correspond to a .cfg file in ups/.
29 # @param versionString Version-control system string to be parsed for version information
30 # ($HeadURL$ for SVN).
31 # @param eupsProduct Name of the EUPS product being built. Defaults to and is almost always
32 # the name of the package.
33 # @param eupsProductPath An alternate directory where the package should be installed.
34 # @param noCfgFile If True, this package has no .cfg file
35 #
36 # @return an SCons Environment object (which is also available as lsst.sconsUtils.env).
37 ##
38 def configure(packageName, versionString=None, eupsProduct=None, eupsProductPath=None, noCfgFile=False):
39  if not state.env.GetOption("no_progress"):
40  state.log.info("Setting up environment to build package '%s'." % packageName)
41  if eupsProduct is None:
42  eupsProduct = packageName
43  if versionString is None:
44  versionString = "git"
45  state.env['eupsProduct'] = eupsProduct
46  state.env['packageName'] = packageName
47  #
48  # Setup installation directories and variables
49  #
50  SCons.Script.Help(state.opts.GenerateHelpText(state.env))
51  state.env.installing = filter(lambda t: t == "install", SCons.Script.BUILD_TARGETS)
52  state.env.declaring = filter(lambda t: t == "declare" or t == "current", SCons.Script.BUILD_TARGETS)
53  state.env.linkFarmDir = state.env.GetOption("linkFarmDir")
54  if state.env.linkFarmDir:
55  state.env.linkFarmDir = os.path.abspath(os.path.expanduser(state.env.linkFarmDir))
56  prefix = installation.setPrefix(state.env, versionString, eupsProductPath)
57  state.env['prefix'] = prefix
58  state.env["libDir"] = "%s/lib" % prefix
59  state.env["pythonDir"] = "%s/python" % prefix
60  #
61  # Process dependencies
62  #
63  state.log.traceback = state.env.GetOption("traceback")
64  state.log.verbose = state.env.GetOption("verbose")
65  packages = PackageTree(packageName, noCfgFile=noCfgFile)
66  state.log.flush() # if we've already hit a fatal error, die now.
67  state.env.libs = {"main":[], "python":[], "test":[]}
68  state.env.doxygen = {"tags":[], "includes":[]}
69  state.env['CPPPATH'] = []
70  state.env['LIBPATH'] = []
71 
72  # XCPPPATH is a new variable defined by sconsUtils - it's like CPPPATH, but the headers
73  # found there aren't treated as dependencies. This can make scons a lot faster.
74  state.env['XCPPPATH'] = []
75  state.env['_CPPINCFLAGS'] = \
76  "$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)}"\
77  " ${_concat(INCPREFIX, XCPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)"
78  state.env['_SWIGINCFLAGS'] = state.env['_CPPINCFLAGS'].replace("CPPPATH", "SWIGPATH")
79 
80  if state.env.linkFarmDir:
81  for d in [state.env.linkFarmDir, "#"]:
82  state.env.Append(CPPPATH=os.path.join(d, "include"))
83  state.env.Append(LIBPATH=os.path.join(d, "lib"))
84  state.env['SWIGPATH'] = state.env['CPPPATH']
85 
86  if not state.env.GetOption("clean") and not state.env.GetOption("help"):
87  packages.configure(state.env, check=state.env.GetOption("checkDependencies"))
88  for target in state.env.libs:
89  state.log.info("Libraries in target '%s': %s" % (target, state.env.libs[target]))
90  state.env.dependencies = packages
91  state.log.flush()
92 
93 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
94 
95 ##
96 # @brief Base class for defining how to configure an LSST sconsUtils package.
97 #
98 # Aliased as lsst.sconsUtils.Configuration.
99 #
100 # An ups/*.cfg file should contain an instance of this class called
101 # "config". Most LSST packages will be able to use this class directly
102 # instead of subclassing it.
103 #
104 # The only important method is configure(), which modifies an SCons
105 # environment to use the package. If a subclass overrides configure,
106 # it may not need to call the base class __init__(), whose only
107 # purpose is to define a number of instance variables used by configure().
108 ##
109 class Configuration(object):
110 
111  ## @brief Parse the name of a .cfg file, returning the package name and root directory.
112  @staticmethod
113  def parseFilename(cfgFile):
114  dir, file = os.path.split(cfgFile)
115  name, ext = os.path.splitext(file)
116  return name, os.path.abspath(os.path.join(dir, ".."))
117 
118  @staticmethod
119  def getEupsData(eupsProduct):
120  version, eupsPathDir, productDir, table, flavor = eupsForScons.getEups().findSetupVersion(eupsProduct)
121  if productDir is None:
122  productDir = eupsForScons.productDir(eupsProduct)
123  return version, productDir
124 
125  ##
126  # @brief Initialize the configuration object.
127  #
128  # @param cfgFile The name of the calling .cfg file, usually just passed in with the special
129  # variable __file__. This will be parsed to extract the package name and
130  # root.
131  # @param headers A list of headers provided by the package, to be used in autoconf-style
132  # tests.
133  # @param libs A list or dictionary of libraries provided by the package. If a dictionary
134  # is provided, libs["main"] should contain a list of regular libraries
135  # provided
136  # by the library. Other keys are "python" and "test", which refer to
137  # libraries that are only linked against compiled Python modules and unit
138  # tests, respectively. If a list is provided, the list is used as "main".
139  # These are used both for autoconf-style tests and to support
140  # env.getLibs(...), which recursively computes the libraries a package
141  # must be linked with.
142  # @param hasSwigFiles If True, the package provides SWIG interface files in "<root>/python".
143  # @param hasDoxygenInclude If True, the package provides a Doxygen include file with the
144  # name "<root>/doc/<name>.inc".
145  # @param hasDoxygenTag If True, the package generates a Doxygen TAG file.
146  # @param includeFileDirs List of directories that should be searched for include files
147  # @param libFileDirs List of directories that should be searched for libraries
148  # @param eupsProduct Name of the EUPS product for the package, if different from the name of the
149  # .cfg file.
150  ##
151  def __init__(self, cfgFile, headers=(), libs=None, hasSwigFiles=True,
152  includeFileDirs=["include",], libFileDirs=["lib",],
153  hasDoxygenInclude=False, hasDoxygenTag=True, eupsProduct=None):
154  self.name, self.root = self.parseFilename(cfgFile)
155  if eupsProduct is None:
156  eupsProduct = self.name
157  self.eupsProduct = eupsProduct
158  version, productDir = self.getEupsData(self.eupsProduct)
159  if version is not None:
160  self.version = version
161  if productDir is None:
162  state.log.warn("Could not find EUPS product dir for '%s'; using %s."
163  % (self.eupsProduct, self.root))
164  else:
165  self.root = os.path.realpath(productDir)
166  self.doxygen = {
167  # Doxygen tag files generated by this package
168  "tags": ([os.path.join(self.root, "doc", "%s.tag" % self.name)]
169  if hasDoxygenTag else []),
170  # Doxygen include files to include in the configuration of dependent products
171  "includes": ([os.path.join(self.root, "doc", "%s.inc" % self.name)]
172  if hasDoxygenInclude else [])
173  }
174  if libs is None:
175  self.libs = {
176  # Normal libraries provided by this package
177  "main": [self.name],
178  # Libraries provided that should only be linked with Python modules
179  "python":[],
180  # Libraries provided that should only be linked with unit test code
181  "test":[],
182  }
183  elif "main" in libs:
184  self.libs = libs
185  else:
186  self.libs = {"main": libs, "python": [], "test": []}
187  self.paths = {}
188  if hasSwigFiles:
189  self.paths["SWIGPATH"] = [os.path.join(self.root, "python")]
190  else:
191  self.paths["SWIGPATH"] = []
192 
193  for pathName, subDirs in [("CPPPATH", includeFileDirs),
194  ("LIBPATH", libFileDirs),]:
195  self.paths[pathName] = []
196 
197  if state.env.linkFarmDir:
198  continue
199 
200  for subDir in subDirs:
201  pathDir = os.path.join(self.root, subDir)
202  if os.path.isdir(pathDir):
203  self.paths[pathName].append(pathDir)
204 
205  self.provides = {
206  "headers": tuple(headers),
207  "libs": tuple(self.libs["main"])
208  }
209 
210  ##
211  # @brief Add custom SCons configuration tests to the Configure Context passed to the
212  # configure() method.
213  #
214  # This needs to be done up-front so we can pass in a dictionary of custom tests when
215  # calling env.Configure(), and use the same configure context for all packages.
216  #
217  # @param tests A dictionary to add custom tests to. This will be passed as the
218  # custom_tests argument to env.Configure().
219  ##
220  def addCustomTests(self, tests):
221  pass
222 
223  ##
224  # @brief Update an SCons environment to make use of the package.
225  #
226  # @param conf An SCons Configure context. The SCons Environment conf.env should be updated
227  # by the configure function.
228  # @param packages A dictionary containing the configuration modules of all dependencies (or None if
229  # the dependency was optional and was not found). The <module>.config.configure(...)
230  # method will have already been called on all dependencies.
231  # @param check If True, perform autoconf-style tests to verify that key components are in
232  # fact in place.
233  # @param build If True, this is the package currently being built, and packages in
234  # "buildRequired" and "buildOptional" dependencies will also be present in
235  # the packages dict.
236  ##
237  def configure(self, conf, packages, check=False, build=True):
238  assert(not (check and build))
239  conf.env.PrependUnique(**self.paths)
240  state.log.info("Configuring package '%s'." % self.name)
241  conf.env.doxygen["includes"].extend(self.doxygen["includes"])
242  if not build:
243  conf.env.doxygen["tags"].extend(self.doxygen["tags"])
244  for target in self.libs:
245  if target not in conf.env.libs:
246  conf.env.libs[target] = lib[target].copy()
247  state.log.info("Adding '%s' libraries to target '%s'." % (self.libs[target], target))
248  else:
249  for lib in self.libs[target]:
250  if lib not in conf.env.libs[target]:
251  conf.env.libs[target].append(lib)
252  state.log.info("Adding '%s' library to target '%s'." % (lib, target))
253  if check:
254  for header in self.provides["headers"]:
255  if not conf.CheckCXXHeader(header): return False
256  for lib in self.libs["main"]:
257  if not conf.CheckLib(lib, autoadd=False, language="C++"): return False
258  return True
259 
260 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
261 
262 ##
263 # @brief A Configuration subclass for external (third-party) packages.
264 #
265 # Aliased as lsst.sconsUtils.ExternalConfiguration.
266 #
267 # ExternalConfiguration doesn't assume the package uses SWIG or Doxygen,
268 # and tells SCons not to consider header files this package provides as dependencies
269 # (by setting XCPPPATH instead of CPPPATH). This means things SCons won't waste time
270 # looking for changes in it every time you build.
271 ##
273 
274  ##
275  # @brief Initialize the configuration object.
276  #
277  # @param cfgFile The name of the calling .cfg file, usually just passed in with the special
278  # variable __file__. This will be parsed to extract the package name and root.
279  # @param headers A list of headers provided by the package, to be used in autoconf-style tests.
280  # @param libs A list or dictionary of libraries provided by the package. If a dictionary
281  # is provided, libs["main"] should contain a list of regular libraries provided
282  # by the library. Other keys are "python" and "test", which refer to libraries
283  # that are only linked against compiled Python modules and unit tests, respectively.
284  # If a list is provided, the list is used as "main". These are used both for
285  # autoconf-style tests and to support env.getLibs(...), which recursively computes
286  # the libraries a package must be linked with.
287  ##
288  def __init__(self, cfgFile, headers=(), libs=None, eupsProduct=None):
289  Configuration.__init__(self, cfgFile, headers, libs, eupsProduct=eupsProduct, hasSwigFiles=False,
290  hasDoxygenTag=False, hasDoxygenInclude=False)
291  self.paths["XCPPPATH"] = self.paths["CPPPATH"]
292  del self.paths["CPPPATH"]
293 
294 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
295 
296 ##
297 # @brief A configuration test that checks whether a C compiler supports
298 # a particular flag.
299 #
300 # @param context Configuration context.
301 # @param flag Flag to test, e.g. "-fvisibility-inlines-hidden".
302 # @param append Automatically append the flag to context.env["CCFLAGS"]
303 # if the compiler supports it?
304 ##
305 def CustomCFlagCheck(context, flag, append=True):
306  context.Message("Checking if C compiler supports " + flag + " flag ")
307  ccflags = context.env["CCFLAGS"];
308  context.env.Append(CCFLAGS = flag)
309  result = context.TryCompile("int main(int argc, char **argv) { return 0; }", ".c")
310  context.Result(result)
311  if not append or not result:
312  context.env.Replace(CCFLAGS = ccflags)
313  return result
314 
315 ##
316 # @brief A configuration test that checks whether a C++ compiler supports
317 # a particular flag.
318 #
319 # @param context Configuration context.
320 # @param flag Flag to test, e.g. "-fvisibility-inlines-hidden".
321 # @param append Automatically append the flag to context.env["CXXFLAGS"]
322 # if the compiler supports it?
323 ##
324 def CustomCppFlagCheck(context, flag, append=True):
325  context.Message("Checking if C++ compiler supports " + flag + " flag ")
326  cxxflags = context.env["CXXFLAGS"];
327  context.env.Append(CXXFLAGS = flag)
328  result = context.TryCompile("int main(int argc, char **argv) { return 0; }", ".cc")
329  context.Result(result)
330  if not append or not result:
331  context.env.Replace(CXXFLAGS = cxxflags)
332  return result
333 
334 ##
335 # @brief A configuration test that checks whether the given source code
336 # compiles.
337 # @param context Configuration context.
338 # @param message Message disaplyed on console prior to running the test.
339 # @param source Source code to compile.
340 # param extension Identifies the language of the source code. Use ".c" for C, and ".cc"
341 # for C++ (the default).
342 ##
343 def CustomCompileCheck(context, message, source, extension=".cc"):
344  context.Message(message)
345 
346  env = context.env
347  if (env.GetOption("clean") or env.GetOption("help") or env.GetOption("no_exec")):
348  result = True
349  else:
350  result = context.TryCompile(source, extension)
351 
352  context.Result(result)
353 
354  return result
355 
356 ##
357 # @brief A configuration test that checks whether the given source code
358 # compiles and links.
359 # @param context Configuration context.
360 # @param message Message disaplyed on console prior to running the test.
361 # @param source Source code to compile.
362 # param extension Identifies the language of the source code. Use ".c" for C, and ".cc"
363 # for C++ (the default).
364 ##
365 def CustomLinkCheck(context, message, source, extension=".cc"):
366  context.Message(message)
367  result = context.TryLink(source, extension)
368  context.Result(result)
369  return result
370 
371 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
372 
373 ##
374 # @brief A class for loading and managing the dependency tree of a package, as defined by its
375 # configuration module (.cfg) file.
376 #
377 # This tree isn't actually stored as a tree; it's flattened into an ordered dictionary
378 # as it is recursively loaded.
379 #
380 # The main SCons produced by configure() and available as sconsUtils.env will contain
381 # an instance of this class as env.dependencies.
382 #
383 # Its can be used like a read-only dictionary to check whether an optional package has been
384 # configured; a package that was not found will have a value of None, while a configured
385 # package's value will be its imported .cfg module.
386 ##
387 class PackageTree(object):
388 
389  ##
390  # @brief Recursively load *.cfg files for packageName and all its dependencies.
391  #
392  # @param primaryName The name of the primary package being built.
393  # @param noCfgFile If True, this package has no .cfg file
394  #
395  # After __init__, self.primary will be set to the configuration module for the primary package,
396  # and self.packages will be an OrderedDict of dependencies (excluding self.primary), ordered
397  # such that configuration can proceed in iteration order.
398  ##
399  def __init__(self, primaryName, noCfgFile=False):
400  self.cfgPath = state.env.cfgPath
401  self.packages = collections.OrderedDict()
402  self.customTests = {
403  "CustomCFlagCheck" : CustomCFlagCheck,
404  "CustomCppFlagCheck" : CustomCppFlagCheck,
405  "CustomCompileCheck" : CustomCompileCheck,
406  "CustomLinkCheck" : CustomLinkCheck,
407  }
408  self._current = set([primaryName])
409  if noCfgFile:
410  self.primary = None
411  return
412 
413  self.primary = self._tryImport(primaryName)
414  if self.primary is None:
415  state.log.fail("Failed to load primary package configuration for %s." % primaryName)
416 
417  missingDeps = []
418  for dependency in self.primary.dependencies.get("required", ()):
419  if not self._recurse(dependency):
420  missingDeps.append(dependency)
421  if missingDeps:
422  state.log.fail("Failed to load required dependencies: \"%s\"" % '", "'.join(missingDeps))
423 
424  missingDeps = []
425  for dependency in self.primary.dependencies.get("buildRequired", ()):
426  if not self._recurse(dependency):
427  missingDeps.append(dependency)
428  if missingDeps:
429  state.log.fail("Failed to load required build dependencies: \"%s\"" % '", "'.join(missingDeps))
430 
431  for dependency in self.primary.dependencies.get("optional", ()):
432  self._recurse(dependency)
433 
434  for dependency in self.primary.dependencies.get("buildOptional", ()):
435  self._recurse(dependency)
436 
437  name = property(lambda self: self.primary.config.name)
438 
439  ## @brief Configure the entire dependency tree in order. and return an updated environment."""
440  def configure(self, env, check=False):
441  conf = env.Configure(custom_tests=self.customTests)
442  for name, module in self.packages.iteritems():
443  if module is None:
444  state.log.info("Skipping missing optional package %s." % name)
445  continue
446  if not module.config.configure(conf, packages=self.packages, check=check, build=False):
447  state.log.fail("%s was found but did not pass configuration checks." % name)
448  if self.primary:
449  self.primary.config.configure(conf, packages=self.packages, check=False, build=True)
450  env.AppendUnique(SWIGPATH=env["CPPPATH"])
451  env.AppendUnique(XSWIGPATH=env["XCPPPATH"])
452  # reverse the order of libraries in env.libs, so libraries that fulfill a dependency
453  # of another appear after it. required by the linker to successfully resolve symbols
454  # in static libraries.
455  for target in env.libs:
456  env.libs[target].reverse()
457  env = conf.Finish()
458  return env
459 
460  def __contains__(self, name):
461  return name == self.name or name in self.packages
462 
463  has_key = __contains__
464 
465  def __getitem__(self, name):
466  if name == self.name:
467  return self.primary
468  else:
469  return self.packages[name]
470 
471  def get(self, name, default=None):
472  if name == self.name:
473  return self.primary
474  else:
475  return self.packages.get(name)
476 
477  def keys(self):
478  k = self.packages.keys()
479  k.append(self.name)
480  return k
481 
482  def _tryImport(self, name):
483  """Search for and import an individual configuration module from file."""
484  filenames = []
485  envVars = ("%s_DIR_EXTRA" % name.upper(), "%s_DIR" % name.upper())
486  paths = [os.path.join(os.environ[v], "ups") for v in envVars if v in os.environ]
487  paths.extend(self.cfgPath)
488  for path in paths:
489  filename = os.path.join(path, name + ".cfg")
490  if os.path.exists(filename):
491  try:
492  module = imp.load_source(name + "_cfg", filename)
493  except Exception, e:
494  state.log.warn("Error loading configuration %s (%s)" % (filename, e))
495  continue
496  state.log.info("Using configuration for package '%s' at '%s'." % (name, filename))
497  if not hasattr(module, "dependencies") or not isinstance(module.dependencies, dict):
498  state.log.warn("Configuration module for package '%s' lacks a dependencies dict." % name)
499  return None
500  if not hasattr(module, "config") or not isinstance(module.config, Configuration):
501  state.log.warn("Configuration module for package '%s' lacks a config object." % name)
502  return None
503  else:
504  module.config.addCustomTests(self.customTests)
505  return module
506  state.log.info("Failed to import configuration for optional package '%s'." % name)
507 
508  def _recurse(self, name):
509  """Recursively load a dependency."""
510  if name in self._current:
511  state.log.fail("Detected recursive dependency involving package '%s'" % name)
512  else:
513  self._current.add(name)
514  if name in self.packages:
515  self._current.remove(name)
516  return self.packages[name] is not None
517  module = self._tryImport(name)
518  if module is None:
519  self.packages[name] = None
520  self._current.remove(name)
521  return False
522  for dependency in module.dependencies.get("required", ()):
523  if not self._recurse(dependency):
524  # We can't configure this package because a required dependency wasn't found.
525  # But this package might itself be optional, so we don't die yet.
526  self.packages[name] = None
527  self._current.remove(name)
528  state.log.warn("Could not load all dependencies for package '%s' (missing %s)." %
529  (name, dependency))
530  return False
531  for dependency in module.dependencies.get("optional", ()):
532  self._recurse(dependency)
533  # This comes last to ensure the ordering puts all dependencies first.
534  self.packages[name] = module
535  self._current.remove(name)
536  return True
537 
538 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
539 
540 ##
541 # @brief Get the libraries the package should be linked with.
542 #
543 # @param categories A string containing whitespace-delimited categories. Standard
544 # categories are "main", "python", and "test". Default is "main".
545 # A special virtual category "self" can be provided, returning
546 # the results of targets="main" with the env["packageName"] removed.
547 #
548 # Typically, main libraries will be linked with LIBS=getLibs("self"),
549 # Python modules will be linked with LIBS=getLibs("main python") and
550 # C++-coded test programs will be linked with LIBS=getLibs("main test").
551 # """
552 def getLibs(env, categories="main"):
553  libs = []
554  removeSelf = False
555  for category in categories.split():
556  if category == "self":
557  category = "main"
558  removeSelf = True
559  for lib in env.libs[category]:
560  if lib not in libs:
561  libs.append(lib)
562  if removeSelf:
563  try:
564  libs.remove(env["packageName"])
565  except ValueError:
566  pass
567  return libs
568 
569 SConsEnvironment.getLibs = getLibs
570 
571 ## @}
Base class for defining how to configure an LSST sconsUtils package.
def CustomCppFlagCheck
A configuration test that checks whether a C++ compiler supports a particular flag.
def CustomLinkCheck
A configuration test that checks whether the given source code compiles and links.
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Definition: eigen.h:390
def configure
Recursively configure a package using ups/.cfg files.
Definition: dependencies.py:38
def getLibs
Get the libraries the package should be linked with.
def configure
Update an SCons environment to make use of the package.
def __init__
Recursively load *.cfg files for packageName and all its dependencies.
def CustomCompileCheck
A configuration test that checks whether the given source code compiles.
def __init__
Initialize the configuration object.
def CustomCFlagCheck
A configuration test that checks whether a C compiler supports a particular flag. ...
def __init__
Initialize the configuration object.
A class for loading and managing the dependency tree of a package, as defined by its configuration mo...
A Configuration subclass for external (third-party) packages.
def configure
Configure the entire dependency tree in order.
def addCustomTests
Add custom SCons configuration tests to the Configure Context passed to the configure() method...
def parseFilename
Parse the name of a .cfg file, returning the package name and root directory.