14 from .
import eupsForScons
15 from SCons.Script.SConscript
import SConsEnvironment
17 from .
import installation
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:
45 state.env[
'eupsProduct'] = eupsProduct
46 state.env[
'packageName'] = packageName
50 SCons.Script.Help(state.opts.GenerateHelpText(state.env))
51 state.env.installing = [t
for t
in SCons.Script.BUILD_TARGETS
if t ==
"install"]
52 state.env.declaring = [t
for t
in SCons.Script.BUILD_TARGETS
if t ==
"declare" or t ==
"current"]
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
63 state.log.traceback = state.env.GetOption(
"traceback")
64 state.log.verbose = state.env.GetOption(
"verbose")
65 packages =
PackageTree(packageName, noCfgFile=noCfgFile)
67 state.env.libs = {
"main": [],
"python": [],
"test": []}
68 state.env.doxygen = {
"tags": [],
"includes": []}
69 state.env[
'CPPPATH'] = []
70 state.env[
'LIBPATH'] = []
74 state.env[
'XCPPPATH'] = []
80 state.env[
'XCPPPREFIX'] =
"-isystem " 82 state.env[
'_CPPINCFLAGS'] = \
83 "$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)}"\
84 " ${_concat(XCPPPREFIX, XCPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)" 85 state.env[
'_SWIGINCFLAGS'] = state.env[
'_CPPINCFLAGS'] \
86 .replace(
"CPPPATH",
"SWIGPATH") \
87 .replace(
"XCPPPREFIX",
"SWIGINCPREFIX")
89 if state.env.linkFarmDir:
90 for d
in [state.env.linkFarmDir,
"#"]:
91 state.env.Append(CPPPATH=os.path.join(d,
"include"))
92 state.env.Append(LIBPATH=os.path.join(d,
"lib"))
93 state.env[
'SWIGPATH'] = state.env[
'CPPPATH']
95 if not state.env.GetOption(
"clean")
and not state.env.GetOption(
"help"):
96 packages.configure(state.env, check=state.env.GetOption(
"checkDependencies"))
97 for target
in state.env.libs:
98 state.log.info(
"Libraries in target '%s': %s" % (target, state.env.libs[target]))
99 state.env.dependencies = packages
124 dir, file = os.path.split(cfgFile)
125 name, ext = os.path.splitext(file)
126 return name, os.path.abspath(os.path.join(dir,
".."))
130 version, eupsPathDir, productDir, table, flavor = eupsForScons.getEups().
findSetupVersion(eupsProduct)
131 if productDir
is None:
132 productDir = eupsForScons.productDir(eupsProduct)
133 return version, productDir
161 def __init__(self, cfgFile, headers=(), libs=
None, hasSwigFiles=
True,
162 includeFileDirs=[
"include"], libFileDirs=[
"lib"],
163 hasDoxygenInclude=
False, hasDoxygenTag=
True, eupsProduct=
None):
165 if eupsProduct
is None:
166 eupsProduct = self.name
169 if version
is not None:
171 if productDir
is None:
172 state.log.warn(
"Could not find EUPS product dir for '%s'; using %s." 175 self.
root = os.path.realpath(productDir)
178 "tags": ([os.path.join(self.
root,
"doc",
"%s.tag" % self.name)]
179 if hasDoxygenTag
else []),
181 "includes": ([os.path.join(self.
root,
"doc",
"%s.inc" % self.name)]
182 if hasDoxygenInclude
else [])
196 self.
libs = {
"main": libs,
"python": [],
"test": []}
199 self.
paths[
"SWIGPATH"] = [os.path.join(self.
root,
"python")]
201 self.
paths[
"SWIGPATH"] = []
203 for pathName, subDirs
in [(
"CPPPATH", includeFileDirs),
204 (
"LIBPATH", libFileDirs)]:
205 self.
paths[pathName] = []
207 if state.env.linkFarmDir:
210 for subDir
in subDirs:
211 pathDir = os.path.join(self.
root, subDir)
212 if os.path.isdir(pathDir):
216 "headers": tuple(headers),
217 "libs": tuple(self.
libs[
"main"])
247 def configure(self, conf, packages, check=False, build=True):
248 assert(
not (check
and build))
249 conf.env.PrependUnique(**self.
paths)
250 state.log.info(
"Configuring package '%s'." % self.name)
251 conf.env.doxygen[
"includes"].extend(self.
doxygen[
"includes"])
253 conf.env.doxygen[
"tags"].extend(self.
doxygen[
"tags"])
254 for target
in self.
libs:
255 if target
not in conf.env.libs:
256 conf.env.libs[target] = self.
libs[target].copy()
257 state.log.info(
"Adding '%s' libraries to target '%s'." % (self.
libs[target], target))
259 for lib
in self.
libs[target]:
260 if lib
not in conf.env.libs[target]:
261 conf.env.libs[target].
append(lib)
262 state.log.info(
"Adding '%s' library to target '%s'." % (lib, target))
264 for header
in self.
provides[
"headers"]:
265 if not conf.CheckCXXHeader(header):
267 for lib
in self.
libs[
"main"]:
268 if not conf.CheckLib(lib, autoadd=
False, language=
"C++"):
303 def __init__(self, cfgFile, headers=(), libs=
None, eupsProduct=
None):
304 Configuration.__init__(self, cfgFile, headers, libs, eupsProduct=eupsProduct, hasSwigFiles=
False,
305 hasDoxygenTag=
False, hasDoxygenInclude=
False)
306 self.
paths[
"XCPPPATH"] = self.
paths[
"CPPPATH"]
307 del self.
paths[
"CPPPATH"]
322 context.Message(
"Checking if C compiler supports " + flag +
" flag ")
323 ccflags = context.env[
"CCFLAGS"]
324 context.env.Append(CCFLAGS=flag)
325 result = context.TryCompile(
"int main(int argc, char **argv) { return 0; }",
".c")
326 context.Result(result)
327 if not append
or not result:
328 context.env.Replace(CCFLAGS=ccflags)
342 context.Message(
"Checking if C++ compiler supports " + flag +
" flag ")
343 cxxflags = context.env[
"CXXFLAGS"]
344 context.env.Append(CXXFLAGS=flag)
345 result = context.TryCompile(
"int main(int argc, char **argv) { return 0; }",
".cc")
346 context.Result(result)
347 if not append
or not result:
348 context.env.Replace(CXXFLAGS=cxxflags)
362 context.Message(message)
365 if (env.GetOption(
"clean")
or env.GetOption(
"help")
or env.GetOption(
"no_exec")):
368 result = context.TryCompile(source, extension)
370 context.Result(result)
385 context.Message(message)
386 result = context.TryLink(source, extension)
387 context.Result(result)
423 "CustomCFlagCheck": CustomCFlagCheck,
424 "CustomCppFlagCheck": CustomCppFlagCheck,
425 "CustomCompileCheck": CustomCompileCheck,
426 "CustomLinkCheck": CustomLinkCheck,
435 state.log.fail(
"Failed to load primary package configuration for %s." % primaryName)
438 for dependency
in self.
primary.dependencies.get(
"required", ()):
440 missingDeps.append(dependency)
442 state.log.fail(
"Failed to load required dependencies: \"%s\"" %
'", "'.join(missingDeps))
445 for dependency
in self.
primary.dependencies.get(
"buildRequired", ()):
447 missingDeps.append(dependency)
449 state.log.fail(
"Failed to load required build dependencies: \"%s\"" %
'", "'.join(missingDeps))
451 for dependency
in self.
primary.dependencies.get(
"optional", ()):
454 for dependency
in self.
primary.dependencies.get(
"buildOptional", ()):
457 name = property(
lambda self: self.
primary.config.name)
461 conf = env.Configure(custom_tests=self.
customTests)
464 state.log.info(
"Skipping missing optional package %s." % name)
466 if not module.config.configure(conf, packages=self.
packages, check=check, build=
False):
467 state.log.fail(
"%s was found but did not pass configuration checks." % name)
469 self.
primary.config.configure(conf, packages=self.
packages, check=
False, build=
True)
470 env.AppendUnique(SWIGPATH=env[
"CPPPATH"])
471 env.AppendUnique(XSWIGPATH=env[
"XCPPPATH"])
475 for target
in env.libs:
476 env.libs[target].reverse()
483 has_key = __contains__
486 if name == self.
name:
491 def get(self, name, default=None):
492 if name == self.
name:
502 def _tryImport(self, name):
503 """Search for and import an individual configuration module from file.""" 505 filename = os.path.join(path, name +
".cfg")
506 if os.path.exists(filename):
508 module = imp.load_source(name +
"_cfg", filename)
509 except Exception
as e:
510 state.log.warn(
"Error loading configuration %s (%s)" % (filename, e))
512 state.log.info(
"Using configuration for package '%s' at '%s'." % (name, filename))
513 if not hasattr(module,
"dependencies")
or not isinstance(module.dependencies, dict):
514 state.log.warn(
"Configuration module for package '%s' lacks a dependencies dict." % name)
516 if not hasattr(module,
"config")
or not isinstance(module.config, Configuration):
517 state.log.warn(
"Configuration module for package '%s' lacks a config object." % name)
522 state.log.info(
"Failed to import configuration for optional package '%s'." % name)
524 def _recurse(self, name):
525 """Recursively load a dependency.""" 527 state.log.fail(
"Detected recursive dependency involving package '%s'" % name)
532 return self.
packages[name]
is not None 538 for dependency
in module.dependencies.get(
"required", ()):
544 state.log.warn(
"Could not load all dependencies for package '%s' (missing %s)." %
547 for dependency
in module.dependencies.get(
"optional", ()):
572 for category
in categories.split():
573 if category ==
"self":
576 for lib
in env.libs[category]:
581 libs.remove(env[
"packageName"])
587 SConsEnvironment.getLibs = getLibs
Base class for defining how to configure an LSST sconsUtils package.
def _tryImport(self, name)
def CustomCFlagCheck(context, flag, append=True)
A configuration test that checks whether a C compiler supports a particular flag. ...
def configure(self, env, check=False)
def CustomCppFlagCheck(context, flag, append=True)
A configuration test that checks whether a C++ compiler supports a particular flag.
def CustomLinkCheck(context, message, source, extension=".cc")
A configuration test that checks whether the given source code compiles and links.
def addCustomTests(self, tests)
Add custom SCons configuration tests to the Configure Context passed to the configure() method...
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
def configure(packageName, versionString=None, eupsProduct=None, eupsProductPath=None, noCfgFile=False)
Recursively configure a package using ups/.cfg files.
daf::base::PropertySet * set
def __contains__(self, name)
def getLibs(env, categories="main")
Get the libraries the package should be linked with.
def __init__(self, cfgFile, headers=(), libs=None, hasSwigFiles=True, includeFileDirs=["include"], libFileDirs=["lib"], hasDoxygenInclude=False, hasDoxygenTag=True, eupsProduct=None)
Initialize the configuration object.
def __init__(self, cfgFile, headers=(), libs=None, eupsProduct=None)
Initialize the configuration object.
def __init__(self, primaryName, noCfgFile=False)
Recursively load *.cfg files for packageName and all its dependencies.
def parseFilename(cfgFile)
def get(self, name, default=None)
def CustomCompileCheck(context, message, source, extension=".cc")
A configuration test that checks whether the given source code compiles.
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.
std::vector< SchemaItem< Flag > > * items
def getEupsData(eupsProduct)
def __getitem__(self, name)
daf::base::PropertyList * list
def configure(self, conf, packages, check=False, build=True)
Update an SCons environment to make use of the package.