9 from __future__
import absolute_import, division, print_function
12 from distutils.spawn
import find_executable
14 from .
import dependencies
15 from .
import builders
16 from .
import installation
21 name, ext = os.path.splitext(os.path.basename(str(node)))
52 def __new__(cls, packageName, versionString=None, eupsProduct=None, eupsProductPath=None, cleanExt=None,
53 defaultTargets=(
"lib",
"python",
"tests",
"examples",
"doc"),
54 subDirList=
None, ignoreRegex=
None,
55 versionModuleName=
"python/lsst/%s/version.py", noCfgFile=
False):
56 cls.initialize(packageName, versionString, eupsProduct, eupsProductPath, cleanExt,
57 versionModuleName, noCfgFile=noCfgFile)
58 cls.finish(defaultTargets, subDirList, ignoreRegex)
83 def initialize(cls, packageName, versionString=None, eupsProduct=None, eupsProductPath=None,
84 cleanExt=
None, versionModuleName=
"python/lsst/%s/version.py", noCfgFile=
False):
86 state.log.fail(
"Recursion detected; an SConscript file should not call BasicSConstruct.")
87 cls._initializing =
True
89 cleanExt =
r"*~ core *.so *.os *.o *.pyc *.pkgc"
90 dependencies.configure(packageName, versionString, eupsProduct, eupsProductPath, noCfgFile)
91 state.env.BuildETags()
92 state.env.CleanTree(cleanExt)
93 if versionModuleName
is not None:
95 versionModuleName = versionModuleName %
"/".join(packageName.split(
"_"))
98 state.targets[
"version"] = state.env.VersionModule(versionModuleName)
99 for root, dirs, files
in os.walk(
"."):
100 if "SConstruct" in files
and root !=
".":
103 dirs[:] = [d
for d
in dirs
if (
not d.startswith(
'.'))]
105 if "SConscript" in files:
106 state.log.info(
"Using Sconscript at %s/SConscript" % root)
107 SCons.Script.SConscript(os.path.join(root,
"SConscript"))
108 cls._initializing =
False
129 def finish(defaultTargets=(
"lib",
"python",
"tests",
"examples",
"doc"),
130 subDirList=
None, ignoreRegex=
None):
131 if ignoreRegex
is None:
132 ignoreRegex =
r"(~$|\.pyc$|^\.svn$|\.o|\.os$)"
133 if subDirList
is None:
135 for path
in os.listdir(
"."):
136 if os.path.isdir(path)
and not path.startswith(
"."):
137 subDirList.append(path)
138 install = state.env.InstallLSST(state.env[
"prefix"],
139 [subDir
for subDir
in subDirList],
140 ignoreRegex=ignoreRegex)
141 for name, target
in state.targets.items():
142 state.env.Requires(install, target)
143 state.env.Alias(name, target)
144 state.env.Requires(state.targets[
"python"], state.targets[
"version"])
145 declarer = state.env.Declare()
146 state.env.Requires(declarer, install)
147 state.env.Default([t
for t
in defaultTargets
if os.path.exists(t)])
148 if "version" in state.targets:
149 state.env.Default(state.targets[
"version"])
150 state.env.Requires(state.targets[
"tests"], state.targets[
"version"])
151 state.env.Decider(
"MD5-timestamp")
158 if "tests" in [str(t)
for t
in BUILD_TARGETS]:
159 testsDir = os.path.join(os.getcwd(),
"tests",
".tests")
160 checkTestStatus_command = state.env.Command(
'checkTestStatus', [],
"""
161 @ if [ -d %s ]; then \
162 nfail=`find %s -name \*.failed | wc -l | sed -e 's/ //g'`; \
163 if [ $$nfail -gt 0 ]; then \
164 echo "$$nfail tests failed" >&2; exit 1; \
167 """ % (testsDir, testsDir))
169 state.env.Depends(checkTestStatus_command, BUILD_TARGETS)
170 BUILD_TARGETS.extend(checkTestStatus_command)
171 state.env.AlwaysBuild(checkTestStatus_command)
195 def lib(libName=None, src=None, libs="self"):
197 libName = state.env[
"packageName"]
199 src = Glob(
"#src/*.cc") + Glob(
"#src/*/*.cc") + Glob(
"#src/*/*/*.cc") + Glob(
"#src/*/*/*/*.cc")
200 src = state.env.SourcesForSharedLibrary(src)
201 if isinstance(libs, basestring):
202 libs = state.env.getLibs(libs)
205 result = state.env.SharedLibrary(libName, src, LIBS=libs)
206 state.targets[
"lib"].extend(result)
224 def python(swigNameList=None, libs="main python", swigSrc=None):
225 if swigNameList
is None:
226 swigNameList = [state.env[
"packageName"].split(
"_")[-1] +
"Lib"]
227 swigFileList = [File(name +
".i")
for name
in swigNameList]
230 for name, node
in zip(swigNameList, swigFileList):
231 swigSrc.setdefault(name, []).append(node)
232 if isinstance(libs, basestring):
233 libs = state.env.getLibs(libs)
237 for name, src
in swigSrc.items():
238 result.extend(state.env.SwigLoadableModule(
"_" + name, src, LIBS=libs))
239 state.targets[
"python"].extend(result)
253 def doc(config="doxygen.conf.in", projectName=None, projectNumber=None, **kw):
254 if not find_executable(
"doxygen"):
255 state.log.warn(
"doxygen executable not found; skipping documentation build.")
257 if projectName
is None:
258 projectName =
".".join([
"lsst"] + state.env[
"packageName"].split(
"_"))
259 if projectNumber
is None:
260 projectNumber = state.env[
"version"]
261 result = state.env.Doxygen(
262 config, projectName=projectName, projectNumber=projectNumber,
263 includes=state.env.doxygen[
"includes"],
264 useTags=state.env.doxygen[
"tags"],
265 makeTag=(state.env[
"packageName"] +
".tag"),
268 state.targets[
"doc"].extend(result)
299 def tests(pyList=None, ccList=None, swigNameList=None, swigSrc=None,
300 ignoreList=
None, noBuildList=
None,
302 if noBuildList
is None:
304 if swigNameList
is None:
305 swigFileList = Glob(
"*.i")
306 swigNameList = [
_getFileBase(node)
for node
in swigFileList]
308 swigFileList = [File(name +
".i")
for name
in swigNameList]
312 for name, node
in zip(swigNameList, swigFileList):
313 src = swigSrc.setdefault(name, [])
314 allSwigSrc.update(str(element)
for element
in src)
317 pyList = [node
for node
in Glob(
"*.py")
319 and os.path.basename(str(node))
not in noBuildList]
321 ccList = [node
for node
in Glob(
"*.cc")
322 if (
not str(node).endswith(
"_wrap.cc"))
and str(node)
not in allSwigSrc
323 and os.path.basename(str(node))
not in noBuildList]
324 if ignoreList
is None:
326 s =
lambda l: [str(i)
for i
in l]
327 state.log.info(
"SWIG modules for tests: %s" % s(swigFileList))
328 state.log.info(
"Python tests: %s" % s(pyList))
329 state.log.info(
"C++ tests: %s" % s(ccList))
330 state.log.info(
"Files that will not be built: %s" % noBuildList)
331 state.log.info(
"Ignored tests: %s" % ignoreList)
332 control =
tests.Control(state.env, ignoreList=ignoreList, args=args, verbose=
True)
333 for ccTest
in ccList:
334 state.env.Program(ccTest, LIBS=state.env.getLibs(
"main test"))
336 for name, src
in swigSrc.items():
338 state.env.SwigLoadableModule(
"_" + name, src, LIBS=state.env.getLibs(
"main python"))
340 ccList = [control.run(str(node))
for node
in ccList]
341 pyList = [control.run(str(node))
for node
in pyList]
342 for pyTest
in pyList:
343 state.env.Depends(pyTest, swigMods)
344 state.env.Depends(pyTest, state.targets[
"python"])
345 result = ccList + pyList
346 state.targets[
"tests"].extend(result)
361 def examples(ccList=None, swigNameList=None, swigSrc=None):
362 if swigNameList
is None:
363 swigFileList = Glob(
"*.i")
364 swigNameList = [
_getFileBase(node)
for node
in swigFileList]
366 swigFileList = [File(name)
for name
in swigNameList]
370 for name, node
in zip(swigNameList, swigFileList):
371 src = swigSrc.setdefault(name, [])
372 allSwigSrc.update(str(element)
for element
in src)
375 ccList = [node
for node
in Glob(
"*.cc")
376 if (
not str(node).endswith(
"_wrap.cc"))
and str(node)
not in allSwigSrc]
377 state.log.info(
"SWIG modules for examples: %s" % swigFileList)
378 state.log.info(
"C++ examples: %s" % ccList)
381 results.extend(state.env.Program(src, LIBS=state.env.getLibs(
"main")))
383 for name, src
in swigSrc.items():
385 state.env.SwigLoadableModule(
"_" + name, src, LIBS=state.env.getLibs(
"main python"))
387 for result
in results:
388 state.env.Depends(result, state.targets[
"lib"])
389 state.targets[
"examples"].extend(results)
def lib
Convenience function to replace standard lib/SConscript boilerplate.
def initialize
Convenience function to replace standard SConstruct boilerplate (step 1).
def finish
Convenience function to replace standard SConstruct boilerplate (step 2).
def doc
Convenience function to replace standard doc/SConscript boilerplate.
A scope-only class for SConstruct-replacement convenience functions.
A scope-only class for SConscript-replacement convenience functions.
def examples
Convenience function to replace standard examples/SConscript boilerplate.
def __new__
Convenience function to replace standard SConstruct boilerplate.
A class to control unit tests.
def tests
Convenience function to replace standard tests/SConscript boilerplate.
def python
Convenience function to replace standard python/*/SConscript boilerplate.