13 from SCons.Script.SConscript
import SConsEnvironment
15 from .utils
import memberOf
16 from .installation
import determineVersion, getFingerprint
24 if myenv[
'PLATFORM'] ==
'darwin':
25 myenv[
'SHLINKFLAGS'] += [
"-undefined",
"suppress",
"-flat_namespace",
"-headerpad_max_install_names"]
26 return myenv.SharedLibrary(target, source, **keywords)
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)
59 files = [SCons.Script.File(file)
for file
in files]
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)]
65 if self.get(
"optFiles"):
66 optFiles = self[
"optFiles"].replace(
".",
r"\.")
67 optFiles = SCons.Script.Split(optFiles.replace(
",",
" "))
68 optFilesRe =
"/(%s)$" %
"|".join(optFiles)
72 if self.get(
"noOptFiles"):
73 noOptFiles = self[
"noOptFiles"].replace(
".",
r"\.")
74 noOptFiles = SCons.Script.Split(noOptFiles.replace(
",",
" "))
75 noOptFilesRe =
"/(%s)$" %
"|".join(noOptFiles)
80 opt =
int(self[
"opt"])
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"]))
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)
97 obj = self.SharedObject(ccFile)
100 objs = sorted(state.env.Flatten(objs), key=str)
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"]
122 if "TAGS" not in SCons.Script.COMMAND_LINE_TARGETS:
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 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)]
142 files += [os.path.join(dirpath, f)
for f
in candidates]
154 def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None):
155 toTag =
filesToTag(root, fileRegex, ignoreDirs)
157 return env.Command(
"TAGS", toTag,
"etags -o $TARGET $SOURCES")
172 def CleanTree(self, filePatterns, dirPatterns="", directory=".", verbose=False):
174 def genFindCommand(patterns, directory, verbose, filesOnly):
178 for pattern
in SCons.Script.Split(patterns):
182 expr +=
"-name %s" % re.sub(
r"(^|[^\\])([\[*])",
r"\1\\\2", pattern)
186 expr +=
" -type d -prune" 188 command =
"find " + directory
190 command +=
r" \( -name .svn -prune -o -name .git -prune -o -name \* \) " 191 command +=
r" \( " + expr +
r" \)" 193 command +=
r" -exec rm -f {} \;" 195 command +=
r" -exec rm -rf {} \;" 200 action = genFindCommand(filePatterns, directory, verbose, filesOnly=
True)
206 action +=
" ; rm -rf .sconf_temp .sconsign.dblite .sconsign.tmp config.log" 208 if dirPatterns !=
"":
210 action += genFindCommand(dirPatterns, directory, verbose, filesOnly=
False)
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]))
224 from .
import eupsForScons
230 _productDirs = eupsForScons.productDir(eupsenv=eupsForScons.getEups())
234 pdir = _productDirs.get(product)
236 pdir = eupsForScons.productDir(product)
252 self.__dict__.update(kw)
264 inConfigNode = SCons.Script.File(config)
265 outConfigName, ext = os.path.splitext(inConfigNode.abspath)
266 outConfigNode = SCons.Script.File(outConfigName)
268 tagNode = SCons.Script.File(self.
makeTag)
271 config = env.Command(target=outConfigNode, source=inConfigNode
if os.path.exists(config)
else None,
273 env.AlwaysBuild(config)
275 action=
"doxygen %s" % pipes.quote(outConfigNode.abspath))
278 env.Depends(doc, config)
285 if os.path.isdir(path):
286 for root, dirs, files
in os.walk(path):
287 if os.path.abspath(root)
in self.
excludes:
290 if not self.recursive:
295 if relDir.startswith(
"."):
297 absDir = os.path.abspath(os.path.join(root, relDir))
299 toKeep.append(relDir)
302 for relFile
in files:
303 base, ext = os.path.splitext(relFile)
307 for relFile
in files:
308 absFile = os.path.abspath(os.path.join(root, relFile))
311 for pattern
in self.patterns:
312 if fnmatch.fnmatch(relFile, pattern):
315 elif os.path.isfile(path):
319 for item
in self.outputs:
323 outConfigFile = open(target[0].abspath,
"w")
331 def _quote_path(path):
332 if " " in path
and not path.startswith(
'"')
and not path.endswith(
'"'):
333 return '"{}"'.
format(path)
336 def _quote_paths(pathList):
337 return " ".join(_quote_path(p)
for p
in pathList)
341 for incPath
in self.includes:
342 docDir, incFile = os.path.split(incPath)
343 docPaths.append(
'"%s"' % docDir)
344 incFiles.append(
'"%s"' % incFile)
347 outConfigFile.write(
'@INCLUDE_PATH = %s\n' % _quote_paths(docPaths))
348 for incFile
in incFiles:
349 outConfigFile.write(
'@INCLUDE = %s\n' % _quote_path(incFile))
352 docDir, tagFile = os.path.split(tagPath)
353 htmlDir = os.path.join(docDir,
"html")
354 outConfigFile.write(
'TAGFILES += "%s=%s"\n' % (tagPath, htmlDir))
356 if self.projectName
is not None:
357 outConfigFile.write(
"PROJECT_NAME = %s\n" % self.projectName)
358 if self.projectNumber
is not None:
359 outConfigFile.write(
"PROJECT_NUMBER = %s\n" % self.projectNumber)
360 outConfigFile.write(
"INPUT = %s\n" % _quote_paths(self.
inputs))
361 outConfigFile.write(
"EXCLUDE = %s\n" % _quote_paths(self.
excludes))
362 outConfigFile.write(
"FILE_PATTERNS = %s\n" %
" ".join(self.patterns))
363 outConfigFile.write(
"RECURSIVE = YES\n" if self.recursive
else "RECURSIVE = NO\n")
364 allOutputs =
set((
"html",
"latex",
"man",
"rtf",
"xml"))
365 for output, path
in zip(self.outputs, self.
outputPaths):
367 allOutputs.remove(output.lower())
369 state.log.fail(
"Unknown Doxygen output format '%s'." % output)
371 outConfigFile.write(
"GENERATE_%s = YES\n" % output.upper())
372 outConfigFile.write(
"%s_OUTPUT = %s\n" % (output.upper(), _quote_path(path.abspath)))
373 for output
in allOutputs:
374 outConfigFile.write(
"GENERATE_%s = NO\n" % output.upper())
376 outConfigFile.write(
"GENERATE_TAGFILE = %s\n" % _quote_path(self.
makeTag))
381 with open(source[0].abspath,
"r") as inConfigFile: 382 outConfigFile.write(inConfigFile.read()) 384 outConfigFile.close() 454 inputs = [d
for d
in [
"#doc",
"#include",
"#python",
"#src"]
455 if os.path.exists(SCons.Script.Entry(d).abspath)]
459 "patterns": [
"*.h",
"*.cc",
"*.py",
"*.dox"],
460 "outputs": [
"html",
"xml"],
466 "projectNumber":
None,
470 if kw.get(k)
is None:
473 return builder(self, config)
478 if versionString
is None:
479 for n
in (
"git",
"hg",
"svn",):
480 if os.path.isdir(
".%s" % n):
483 if not versionString:
484 versionString =
"git" 486 def calcMd5(filename):
489 md5 = hashlib.md5(open(filename,
"rb").read()).hexdigest()
495 oldMd5 = calcMd5(filename)
497 def makeVersionModule(target, source, env):
502 parts = version.split(
"+")
505 with open(target[0].abspath,
"w")
as outFile:
506 outFile.write(
"# -------- This file is automatically generated by LSST's sconsUtils -------- #\n")
509 outFile.write(
"%s = '%s'\n" % (what, version))
512 what =
"__repo_version__" 513 outFile.write(
"%s = '%s'\n" % (what, parts[0]))
516 what =
"__fingerprint__" 517 outFile.write(
"%s = '%s'\n" % (what,
getFingerprint(versionString)))
521 info = tuple(
int(v)
for v
in parts[0].split(
"."))
522 what =
"__version_info__" 524 outFile.write(
"%s = %r\n" % (what, info))
530 what =
"__rebuild_version__" 531 outFile.write(
"%s = %s\n" % (what,
int(parts[1])))
536 what =
"__dependency_versions__" 538 outFile.write(
"%s = {\n" % (what))
539 for name, mod
in env.dependencies.packages.items():
541 outFile.write(
" '%s': None,\n" % name)
542 elif hasattr(mod.config,
"version"):
543 outFile.write(
" '%s': '%s',\n" % (name, mod.config.version))
545 outFile.write(
" '%s': 'unknown',\n" % name)
549 outFile.write(
"__all__ = (\n")
551 outFile.write(
" {!r},\n".
format(n))
554 if calcMd5(target[0].abspath) != oldMd5:
555 state.log.info(
"makeVersionModule([\"%s\"], [])" %
str(target[0]))
557 result = self.Command(filename, [], self.Action(makeVersionModule, strfunction=
lambda *args:
None))
559 self.AlwaysBuild(result)
def Doxygen(self, config, kw)
Generate a Doxygen config file and run Doxygen on it.
def SourcesForSharedLibrary(self, files)
Prepare the list of files to be passed to a SharedLibrary constructor.
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...
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
daf::base::PropertySet * set
def buildConfig(self, target, source, env)
def BuildETags(env, root=None, fileRegex=None, ignoreDirs=None)
Build Emacs tags (see man etags for more information).
def Pybind11LoadableModule(self, target, source, keywords)
def __call__(self, env, config)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def determineVersion(env, versionString)
def SharedLibraryIncomplete(self, target, source, keywords)
def VersionModule(self, filename, versionString=None)
A callable to be used as an SCons Action to run Doxygen.
def ProductDir(env, product)
def filesToTag(root=None, fileRegex=None, ignoreDirs=None)
daf::base::PropertyList * list
def memberOf(cls, name=None)
A Python decorator that injects functions into a class.
def getFingerprint(versionString)