12 from SCons.Script.SConscript
import SConsEnvironment
14 from .utils
import memberOf
15 from .installation
import determineVersion, getFingerprint
22 if myenv[
'PLATFORM'] ==
'darwin':
23 myenv[
'SHLINKFLAGS'] += [
"-undefined",
"suppress",
"-flat_namespace"]
24 return myenv.SharedLibrary(target, source, **keywords)
31 if myenv[
'PLATFORM'] ==
'darwin':
32 myenv.Append(LDMODULEFLAGS = [
"-undefined",
"suppress",
"-flat_namespace",])
38 if myenv.whichCc ==
"gcc":
39 myenv.Append(CCFLAGS = [
"-fno-strict-aliasing",])
40 except AttributeError:
42 return myenv.LoadableModule(target, source, **keywords)
62 files = [SCons.Script.File(file)
for file
in files]
64 if not (self.get(
"optFiles")
or self.get(
"noOptFiles")):
68 if self.get(
"optFiles"):
69 optFiles = self[
"optFiles"].replace(
".",
r"\.")
70 optFiles = SCons.Script.Split(optFiles.replace(
",",
" "))
71 optFilesRe =
"/(%s)$" %
"|".join(optFiles)
75 if self.get(
"noOptFiles"):
76 noOptFiles = self[
"noOptFiles"].replace(
".",
r"\.")
77 noOptFiles = SCons.Script.Split(noOptFiles.replace(
",",
" "))
78 noOptFilesRe =
"/(%s)$" %
"|".join(noOptFiles)
83 opt = int(self[
"opt"])
90 CCFLAGS_OPT = re.sub(
r"-O(\d|s)\s*",
"-O%d " % opt,
" ".join(self[
"CCFLAGS"]))
91 CCFLAGS_NOOPT = re.sub(
r"-O(\d|s)\s*",
"-O0 ",
" ".join(self[
"CCFLAGS"]))
95 if optFilesRe
and re.search(optFilesRe, ccFile.abspath):
96 self.SharedObject(ccFile, CCFLAGS=CCFLAGS_OPT)
97 ccFile = os.path.splitext(ccFile.abspath)[0] + self[
"SHOBJSUFFIX"]
98 elif noOptFilesRe
and re.search(noOptFilesRe, ccFile.abspath):
99 self.SharedObject(ccFile, CCFLAGS=CCFLAGS_NOOPT)
100 ccFile = os.path.splitext(ccFile.abspath)[0] + self[
"SHOBJSUFFIX"]
102 sources.append(ccFile)
118 if root
is None: root =
"."
119 if fileRegex
is None: fileRegex =
r"^[a-zA-Z0-9_].*\.(cc|h(pp)?|py)$"
120 if ignoreDirs
is None: ignoreDirs = [
"examples",
"tests"]
122 if len(filter(
lambda t: t ==
"TAGS", SCons.Script.COMMAND_LINE_TARGETS)) == 0:
126 for dirpath, dirnames, filenames
in os.walk(root):
128 dirnames[:] = [d
for d
in dirnames
if not re.search(
r"^(%s)$" %
"|".join(ignoreDirs), d)]
130 dirnames[:] = [d
for d
in dirnames
if not re.search(
r"^(\.svn)$", d)]
134 candidates = [f
for f
in filenames
if re.search(fileRegex, f)]
138 for swigFile
in [f
for f
in filenames
if re.search(
r"\.i$", f)]:
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)]
142 files += [os.path.join(dirpath, f)
for f
in candidates]
153 def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None):
154 toTag =
filesToTag(root, fileRegex, ignoreDirs)
156 return env.Command(
"TAGS", toTag,
"etags -o $TARGET $SOURCES")
170 def CleanTree(self, files, dir=".", recurse=True, verbose=False):
175 for file
in SCons.Script.Split(files):
179 files_expr +=
"-name %s" % re.sub(
r"(^|[^\\])([[*])",
r"\1\\\2",file)
183 action =
"find %s" % dir
184 action +=
r" \( -name .svn -prune -o -name \* \) "
186 action +=
" ! -name . -prune"
188 file_action =
"rm -f"
190 action +=
r" \( %s \) -exec %s {} \;" % \
191 (files_expr, file_action)
200 action +=
" ; rm -rf .sconf_temp .sconsign.dblite .sconsign.tmp config.log"
204 if "clean" in SCons.Script.COMMAND_LINE_TARGETS:
205 state.log.fail(
"'scons clean' is no longer supported; please use 'scons --clean'.")
206 elif not SCons.Script.COMMAND_LINE_TARGETS
and self.GetOption(
"clean"):
207 self.Execute(self.Action([action]))
219 _productDirs = eupsForScons.productDir(eupsenv=eupsForScons.getEups())
223 pdir = _productDirs.get(product)
225 pdir = eupsForScons.productDir(product)
240 self.__dict__.update(kw)
245 self.
inputs = list(SCons.Script.Entry(item).abspath
for item
in self.
inputs)
247 self.
outputPaths = list(SCons.Script.Dir(item)
for item
in self.outputs)
252 inConfigNode = SCons.Script.File(config)
253 outConfigName, ext = os.path.splitext(inConfigNode.abspath)
254 outConfigNode = SCons.Script.File(outConfigName)
256 tagNode = SCons.Script.File(self.
makeTag)
258 self.targets.append(tagNode)
259 config = env.Command(target=outConfigNode, source=inConfigNode
if os.path.exists(config)
else None,
261 env.AlwaysBuild(config)
263 action=
"doxygen %s" % outConfigNode.abspath)
266 env.Depends(doc, config)
267 self.results.extend(config)
268 self.results.extend(doc)
273 if os.path.isdir(path):
274 for root, dirs, files
in os.walk(path):
275 if os.path.abspath(root)
in self.
excludes:
278 if not self.recursive:
283 if relDir.startswith(
"."):
285 absDir = os.path.abspath(os.path.join(root, relDir))
287 toKeep.append(relDir)
290 for relFile
in files:
291 base, ext = os.path.splitext(relFile)
293 self.excludes.append(os.path.join(root, base +
".py"))
294 self.excludes.append(os.path.join(root, base +
"_wrap.cc"))
295 for relFile
in files:
296 absFile = os.path.abspath(os.path.join(root, relFile))
299 for pattern
in self.patterns:
300 if fnmatch.fnmatch(relFile, pattern):
301 self.sources.append(SCons.Script.File(absFile))
303 elif os.path.isfile(path):
304 self.sources.append(SCons.Script.File(path))
307 for item
in self.outputs:
308 self.targets.append(SCons.Script.Dir(item))
311 outConfigFile = open(target[0].abspath,
"w")
313 docDir, tagFile = os.path.split(tagPath)
314 htmlDir = os.path.join(docDir,
"html")
315 outConfigFile.write(
'TAGFILES += "%s=%s"\n' % (tagPath, htmlDir))
316 self.sources.append(SCons.Script.Dir(docDir))
319 for incPath
in self.includes:
320 docDir, incFile = os.path.split(incPath)
321 docPaths.append(
'"%s"' % docDir)
322 incFiles.append(
'"%s"' % incFile)
323 self.sources.append(SCons.Script.File(incPath))
325 outConfigFile.write(
'@INCLUDE_PATH = %s\n' %
" ".join(docPaths))
326 for incFile
in incFiles:
327 outConfigFile.write(
'@INCLUDE = %s\n' % incFile)
328 if self.projectName
is not None:
329 outConfigFile.write(
"PROJECT_NAME = %s\n" % self.projectName)
330 if self.projectNumber
is not None:
331 outConfigFile.write(
"PROJECT_NUMBER = %s\n" % self.projectNumber)
332 outConfigFile.write(
"INPUT = %s\n" %
" ".join(self.
inputs))
333 outConfigFile.write(
"EXCLUDE = %s\n" %
" ".join(self.
excludes))
334 outConfigFile.write(
"FILE_PATTERNS = %s\n" %
" ".join(self.patterns))
335 outConfigFile.write(
"RECURSIVE = YES\n" if self.recursive
else "RECURSIVE = NO\n")
336 allOutputs = set((
"html",
"latex",
"man",
"rtf",
"xml"))
337 for output, path
in zip(self.outputs, self.
outputPaths):
339 allOutputs.remove(output.lower())
341 state.log.fail(
"Unknown Doxygen output format '%s'." % output)
343 outConfigFile.write(
"GENERATE_%s = YES\n" % output.upper())
344 outConfigFile.write(
"%s_OUTPUT = %s\n" % (output.upper(), path.abspath))
345 for output
in allOutputs:
346 outConfigFile.write(
"GENERATE_%s = NO\n" % output.upper())
348 outConfigFile.write(
"GENERATE_TAGFILE = %s\n" % self.
makeTag)
353 with open(source[0].abspath,
"r") as inConfigFile:
354 outConfigFile.write(inConfigFile.read())
356 outConfigFile.close()
425 inputs = [d
for d
in [
"#doc",
"#include",
"#python",
"#src"]
426 if os.path.exists(SCons.Script.Entry(d).abspath)]
430 "patterns": [
"*.h",
"*.cc",
"*.py",
"*.dox"],
431 "outputs": [
"html",],
437 "projectNumber":
None,
441 if kw.get(k)
is None:
444 return builder(self, config)
448 if versionString
is None:
449 for n
in (
"git",
"hg",
"svn",):
450 if os.path.isdir(
".%s" % n):
453 if not versionString:
454 versionString =
"git"
456 def calcMd5(filename):
459 md5 = hashlib.md5(
"\n".join(open(filename).readlines())).hexdigest()
465 oldMd5 = calcMd5(filename)
467 def makeVersionModule(target, source, env):
472 parts = version.split(
"+")
475 with open(target[0].abspath,
"w")
as outFile:
476 outFile.write(
"#--------- This file is automatically generated by LSST's sconsUtils ---------#\n")
479 outFile.write(
"%s = '%s'\n" % (what, version))
482 what =
"__repo_version__"
483 outFile.write(
"%s = '%s'\n" % (what, parts[0]))
486 what =
"__repo_version__"
487 outFile.write(
"%s = '%s'\n" % (what, parts[0]))
490 what =
"__fingerprint__"
491 outFile.write(
"%s = '%s'\n" % (what,
getFingerprint(versionString)))
495 info = tuple(int(v)
for v
in parts[0].split(
"."))
496 what =
"__version_info__"
498 outFile.write(
"%s = %r\n" % (what, info))
504 what =
"__rebuild_version__"
505 outFile.write(
"%s = %s\n" % (what, int(parts[1])))
510 what =
"__dependency_versions__"
512 outFile.write(
"%s = {\n" % (what))
513 for name, mod
in env.dependencies.packages.iteritems():
515 outFile.write(
" '%s': None,\n" % name)
516 elif hasattr(mod.config,
"version"):
517 outFile.write(
" '%s': '%s',\n" % (name, mod.config.version))
519 outFile.write(
" '%s': 'unknown',\n" % name)
522 outFile.write(
"__all__ = %r\n" % (tuple(names),))
524 if calcMd5(target[0].abspath) != oldMd5:
525 print "makeVersionModule([\"%s\"], [])" % str(target[0])
527 result = self.Command(filename, [], self.Action(makeVersionModule, strfunction=
lambda *args:
None))
529 self.AlwaysBuild(result)
def getFingerprint
Return a unique fingerprint for a version (e.g.
def memberOf
A Python decorator that injects functions into a class.
def filesToTag
Return a list of files that need to be scanned for tags, starting at directory root.
def CleanTree
Remove files matching the argument list starting at dir when scons is invoked with -c/–clean and no e...
def ProductDir
Return a product's PRODUCT_DIR, or None.
def determineVersion
Set a version ID from env, or a version control ID string ($name$ or $HeadURL$)
def Doxygen
Generate a Doxygen config file and run Doxygen on it.
def SharedLibraryIncomplete
Like SharedLibrary, but don't insist that all symbols are resolved.
def BuildETags
Build Emacs tags (see man etags for more information).
def SwigLoadableModule
Like LoadableModule, but don't insist that all symbols are resolved, and set some SWIG-specific flags...
def SourcesForSharedLibrary
Prepare the list of files to be passed to a SharedLibrary constructor.
A callable to be used as an SCons Action to run Doxygen.