Carsten Neumann wrote:
> Hi,
>
> Allen Bierbaum wrote:
>> Gerrit Voss wrote:
>>> For example some of the stuff in SConstruct (roughly up to line 500)
>>> should be in scons-addons (from an OpenSG only perspective). So it is
>>> reusable for people who want to write their own applications.
>>>
>> I agree there is a lot of utility code in there. I am not sure if it
>> all makes sense in scons-addons (some of it does), but the OpenSG part
>> IMHO should actually be put into some utility libraries in
>> OpenSG2/Tools/scons-build where the LibraryUtils module currently is.
>
> I had a patch for this, but before I had a chance to convince myself
> that it completely works, there were changes to SConstruct that
> diff/patch were unable to merge in and simply concatenated both variants
> of the file :(
> Anyway, I'll recreate that patch ASAP.
here it is. I did not commit it, because it's not fully tested and I was
using cpu time for building NFIO stuff - which worked with this one applied.
Changelog:
* Tools/scons-build/BuildInfoScanner.py: new file.
* Tools/scons-build/RevisionTagWriter.py: new file.
* SConstruct: removed BuildInfoScanner and RevisionTagWriter code,
include and use the new files instead.
Carsten
Index: Tools/scons-build/BuildInfoScanner.py
===================================================================
--- Tools/scons-build/BuildInfoScanner.py (revision 0)
+++ Tools/scons-build/BuildInfoScanner.py (revision 0)
@@ -0,0 +1,162 @@
+
+import os
+import os.path
+import sys
+
+import SConsAddons.Util as sca_util
+from LibraryUtils import *
+
+pj = os.path.join
+
+class BuildInfoScanner(object):
+ """
+ Recursively scans a directory tree for build.info files and constructs
+ a list of libraries and their dependencies from their contents.
+
+ - Finding build.info files:
+ Every file found can override the settings inherited from parent
+ directories.
+ - Keep a stack of library names, we add to the top library.
+ - All subdirectories of the baseDir are scanned, unless it is in
+ ignoredDirs.
+ - File names are relative to baseDir
+
+ - Evaluating a build.info file:
+ Input variables:
+ - option_pass: If True, we only collect options.
+ - opts: Either None or an Options object to add options to.
+ - platform: The current plarform string.
+ - compiler: The current compiler being used.
+ Output variables:
+ - library: Name of the library to which the current directory belongs.
+ - stop_traversal: If True, ignore this directory and everything below it.
+
+ - osg_dep_libs: List of OpenSG library names, this library depends upon (for linking).
+ - libs: List of external library names, this library depends upon.
+ - frameworks: List of framework names, this library depends upon.
+ - cpppath: Additional include paths for building.
+ - libpath: Additional library paths for linking.
+ - frameworkpath: Additional framework paths to set.
+
+ - osg_test_libs: List of OpenSG library names, this library depends
+ upon for builing tests.
+ - other_test_libs: List of external library names, this library depends
+ upon for building tests.
+ - test_cpppath: Additional include paths for building tests.
+ - test_libpath: Additional library paths for linking tests.
+ """
+
+ def __init__(self, baseDir, opts, env, ignoredDirs = None, verbose = False):
+ self.baseDir = baseDir
+ self.ignoredDirs = ignoredDirs
+ self.opts = opts
+ self.env = env
+ self.platform = sca_util.GetPlatform();
+ self.verbose = verbose
+
+ self.libMap = {}
+ self.libNameStack = []
+ self.libAttributes = ["osg_dep_libs", "libs", "frameworks", "cpppath",
+ "libpath", "frameworkpath","osg_test_libs",
+ "other_test_libs","test_cpppath", "test_libpath"]
+
+ def scan(self, scanDir = ""):
+ """Scan for build.info files in baseDir/scanDir keeping all file paths
+ relative to baseDir.
+ Returns the library map constructed from the files.
+ """
+ self._recursiveScan(scanDir)
+ return self.libMap
+
+ def _recursiveScan(self, scanDir = ""):
+ """The actual recursive scanning routine.
+ """
+ fullDir = pj(self.baseDir, scanDir)
+ scanDirContents = [pj(scanDir, f) for f in os.listdir(fullDir)]
+ files = [f for f in scanDirContents if os.path.isfile(pj(self.baseDir, f))]
+ dirs = [d for d in scanDirContents if os.path.isdir(pj(self.baseDir, d))]
+
+ hasBuildInfo = os.path.exists(pj(fullDir, "build.info"))
+
+ if hasBuildInfo:
+ biFilename = pj(fullDir, "build.info")
+
+ if self.verbose:
+ print " Reading: ", biFilename
+ else:
+ sys.stdout.write(".")
+
+ biDict = dict([("option_pass", False),
+ ("opts", self.opts),
+ ("platform", self.platform),
+ ("compiler", self.env["CXX"]),
+ ("stop_traversal", False)])
+
+ for attrib in self.libAttributes:
+ biDict[attrib] = []
+
+ execfile(biFilename, biDict)
+
+ if biDict["stop_traversal"]:
+ if self.verbose:
+ print " Pruning traversal."
+ return False
+
+ if not biDict.has_key("library") or biDict["library"] == None:
+ print "ERROR: No 'library' specified in build.info file: ", biFilename
+ sys.exit(1)
+
+ libName = biDict["library"]
+ if not self.libMap.has_key(libName):
+ self.libMap[libName] = LibraryInfo(name = libName)
+ if self.verbose:
+ print "Created new LibraryInfo: ", libName
+
+ self.libNameStack.append(libName)
+
+ if self.verbose:
+ print "Library name: ", libName
+
+ # Add all the lib options from the evaluation
+ # - Only add on the unique ones
+ for attrib in self.libAttributes:
+ attribList = getattr(self.libMap[libName], attrib)
+ attribList.extend([a for a in biDict[attrib] if a not in attribList])
+
+ # Collect source files from all directories and put them into
+ # the active library object
+ testFiles = [f for f in files if (os.path.basename(f).startswith("test") and
+ os.path.splitext(f)[1] in [".cpp",".cc",".mm"])];
+ unittestFiles = [f for f in files if (os.path.basename(f).endswith("Test.cpp") and
+ os.path.basename(f).startswith("OSG"))]
+ sourceFiles = [f for f in files if (os.path.splitext(f)[1] in [".cpp", ".cc", ".mm"] and
+ os.path.basename(f).startswith("OSG") and
+ f not in testFiles and f not in unittestFiles)]
+ headerFiles = [f for f in files if (os.path.splitext(f)[1] in [".h", ".inl", ".ins", ".hpp"] and
+ os.path.basename(f).startswith("OSG"))]
+
+ # Add files to their library object
+ if (len(testFiles) or len(unittestFiles) or
+ len(sourceFiles) or len(headerFiles)):
+ if len(self.libNameStack) == 0 or self.libNameStack[-1] == "":
+ print "ERROR: Attempt to add source files without library. " + \
+ "In dir: %s" % fullDir
+ sys.exit(1)
+ libName = self.libNameStack[-1]
+ self.libMap[libName].source_files += sourceFiles
+ self.libMap[libName].header_files += headerFiles
+ self.libMap[libName].test_files += testFiles
+ self.libMap[libName].unittest_files += unittestFiles
+
+ # Recurse into subdirectories
+ for d in dirs:
+ if not os.path.basename(d) in self.ignoredDirs:
+ popStack = self._recursiveScan(d)
+ if popStack:
+ del self.libNameStack[-1]
+
+ # return if anything was added to the libNameStack
+ if hasBuildInfo:
+ return True
+ else:
+ return False
Property changes on: Tools/scons-build/BuildInfoScanner.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Index: Tools/scons-build/RevisionTagWriter.py
===================================================================
--- Tools/scons-build/RevisionTagWriter.py (revision 0)
+++ Tools/scons-build/RevisionTagWriter.py (revision 0)
@@ -0,0 +1,112 @@
+
+import os;
+import os.path;
+
+pj = os.path.join;
+
+# If we have pysvn, load it
+try:
+ import pysvn
+ have_pysvn = True
+except:
+ have_pysvn = False
+
+
+class RevisionTagWriter(object):
+ """
+ For each library the corresponding <Libname>Def.cpp file is located and
+ the highest revision number of any of the lib's source files is recorded
+ together with a marker if the lib contains local changes.
+ """
+ def __init__(self, libMap):
+ """
+ Create a new tag writer that uses the libraries from the given libMap.
+ Also checks if pysvn is available - without it tagging is not possible.
+ """
+ if not have_pysvn:
+ raise "The module pysvn is required to perform revision tagging!"
+
+ self.libMap = libMap
+ self.maxRev = 0
+ self.svnClient = pysvn.Client()
+ self.versionString = open("VERSION").readline().strip()
+
+ def run(self):
+ """
+ Write revision tags.
+ """
+ for (libName, libObj) in self.libMap.iteritems():
+ libMaxRev = 0
+ modifiedStr = ""
+
+ for file in libObj.source_files + libObj.header_files:
+ filename = pj("Source", file)
+
+ fileRev, fileModified = self._getSVNInfo(filename)
+
+ if libMaxRev < fileRev:
+ libMaxRev = fileRev
+
+ # we modify the <libname>Def.cpp files ourselves
+ if fileModified and filename[-7:] != "Def.cpp":
+ print "%s: file %s is modified!" % (libName, filename)
+ modifiedStr = " !MODIFIED!"
+
+ if modifiedStr != "":
+ print "%s: There are modified files, revision might be inaccurate!" % libName
+ print "%s: Highest revision: %d." % (libName, libMaxRev)
+
+ if self.maxRev < libMaxRev:
+ self.maxRev = libMaxRev
+
+ for file in libObj.source_files:
+ if file[-7:] == "Def.cpp":
+ filename = pj("Source", file)
+ fileInfo = self.svnClient.info(filename)
+ repoPath = fileInfo.url[len(fileInfo.repos):-len(filename)-1]
+
+ fileContents = open(filename).readlines()
+ for i in range(len(fileContents)):
+ if fileContents[i][:22] == '#define SVN_REVISION "':
+ fileContents[i] = '#define SVN_REVISION "%d (%s)%s"\n' % (libMaxRev, repoPath, modifiedStr)
+ break
+ open(filename, "w").writelines(fileContents)
+
+ # Update the documentation mainfile
+ # Find the high version for stuff in Doc/, too
+ modifiedStr = ""
+ for file in glob.glob("Doc/*"):
+ print file
+ fileRev, fileMod = self._getSVNInfo(file)
+
+ if self.maxRev < fileRev:
+ self.maxRev = fileRev
+ if fileMod:
+ modifiedStr = " !Modified!"
+
+ filename = "Doc/mainpage.dox"
+ fileContents = open(filename).readlines()
+ for i in range(len(fileContents)):
+ if fileContents[i][:7] == 'version':
+ fileContents[i] = 'version %s r%d %s\n' % (self.versionString, self.maxRev, modifiedStr)
+ break
+ open(filename,'w').writelines(fileContents)
+
+ def _getSVNInfo(self, filename):
+ """
+ Get the svn info for the given file.
+ Returns a version, modified tuple.
+ """
+ fileInfo = self.svnClient.info (filename)
+ fileStatus = self.svnClient.status(filename)
+
+ fileRev = 0
+ fileMod = False
+
+ # Ignore unversioned files
+ if pysvn.wc_status_kind.unversioned != fileStatus[0].text_status and \
+ pysvn.wc_status_kind.ignored != fileStatus[0].text_status:
+ fileRev = fileInfo.revision.number
+ fileMod = pysvn.wc_status_kind.modified == fileStatus[0].text_status
+
+ return fileRev, fileMod
Property changes on: Tools/scons-build/RevisionTagWriter.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Index: SConstruct
===================================================================
--- SConstruct (revision 546)
+++ SConstruct (working copy)
@@ -40,6 +40,9 @@
from LibraryUtils import *
from sets import Set
+from BuildInfoScanner import BuildInfoScanner
+from RevisionTagWriter import RevisionTagWriter
+
# If we have pysvn, load it
try:
import pysvn
@@ -235,263 +238,6 @@
for i in self.value.split(os.pathsep):
exec("env.Append(%s = [i])" % self.key)
-# -------------------------------- #
-# --- build.info file handling --- #
-# -------------------------------- #
-
-class BuildInfoScanner(object):
- """
- Recursively scans a directory tree for build.info files and constructs
- a list of libraries and their dependencies from their contents.
-
- - Finding build.info files:
- Every file found can override the settings inherited from parent
- directories.
- - Keep a stack of library names, we add to the top library.
- - All subdirectories of the baseDir are scanned, unless it is in
- ignoredDirs.
- - File names are relative to baseDir
-
- - Evaluating a build.info file:
- Input variables:
- - option_pass: If True, we only collect options.
- - opts: Either None or an Options object to add options to.
- - platform: The current plarform string.
- - compiler: The current compiler being used.
- Output variables:
- - library: Name of the library to which the current directory belongs.
- - stop_traversal: If True, ignore this directory and everything below it.
-
- - osg_dep_libs: List of OpenSG library names, this library depends upon (for linking).
- - libs: List of external library names, this library depends upon.
- - frameworks: List of framework names, this library depends upon.
- - cpppath: Additional include paths for building.
- - libpath: Additional library paths for linking.
- - frameworkpath: Additional framework paths to set.
-
- - osg_test_libs: List of OpenSG library names, this library depends
- upon for builing tests.
- - other_test_libs: List of external library names, this library depends
- upon for building tests.
- - test_cpppath: Additional include paths for building tests.
- - test_libpath: Additional library paths for linking tests.
- """
-
- def __init__(self, baseDir, ignoredDirs = None, verbose = False):
- self.baseDir = baseDir
- self.ignoredDirs = ignoredDirs
- self.verbose = verbose
-
- self.libMap = {}
- self.libNameStack = []
- self.libAttributes = ["osg_dep_libs", "libs", "frameworks", "cpppath",
- "libpath", "frameworkpath","osg_test_libs",
- "other_test_libs","test_cpppath", "test_libpath"]
-
- def scan(self, scanDir = ""):
- """Scan for build.info files in baseDir/scanDir keeping all file paths
- relative to baseDir.
- Returns the library map constructed from the files.
- """
- self._recursiveScan(scanDir)
- return self.libMap
-
- def _recursiveScan(self, scanDir = ""):
- """The actual recursive scanning routine.
- """
- fullDir = pj(self.baseDir, scanDir)
- scanDirContents = [pj(scanDir, f) for f in os.listdir(fullDir)]
- files = [f for f in scanDirContents if os.path.isfile(pj(self.baseDir, f))]
- dirs = [d for d in scanDirContents if os.path.isdir(pj(self.baseDir, d))]
-
- hasBuildInfo = os.path.exists(pj(fullDir, "build.info"))
-
- if hasBuildInfo:
- biFilename = pj(fullDir, "build.info")
-
- if self.verbose:
- print " Reading: ", biFilename
- else:
- sys.stdout.write(".")
-
- biDict = dict([("option_pass", False),
- ("opts", opts),
- ("platform", platform),
- ("compiler", common_env["CXX"]),
- ("stop_traversal", False)])
-
- for attrib in self.libAttributes:
- biDict[attrib] = []
-
- execfile(biFilename, biDict)
-
- if biDict["stop_traversal"]:
- if self.verbose:
- print " Pruning traversal."
- return False
-
- if not biDict.has_key("library") or biDict["library"] == None:
- print "ERROR: No 'library' specified in build.info file: ", biFilename
- sys.exit(1)
-
- libName = biDict["library"]
- if not self.libMap.has_key(libName):
- self.libMap[libName] = LibraryInfo(name = libName)
- if self.verbose:
- print "Created new LibraryInfo: ", libName
-
- self.libNameStack.append(libName)
-
- if self.verbose:
- print "Library name: ", libName
-
- # Add all the lib options from the evaluation
- # - Only add on the unique ones
- for attrib in self.libAttributes:
- attribList = getattr(self.libMap[libName], attrib)
- attribList.extend([a for a in biDict[attrib] if a not in attribList])
-
- # Collect source files from all directories and put them into
- # the active library object
- testFiles = [f for f in files if (os.path.basename(f).startswith("test") and
- os.path.splitext(f)[1] in [".cpp",".cc",".mm"])];
- unittestFiles = [f for f in files if (os.path.basename(f).endswith("Test.cpp") and
- os.path.basename(f).startswith("OSG"))]
- sourceFiles = [f for f in files if (os.path.splitext(f)[1] in [".cpp", ".cc", ".mm"] and
- os.path.basename(f).startswith("OSG") and
- f not in testFiles and f not in unittestFiles)]
- headerFiles = [f for f in files if (os.path.splitext(f)[1] in [".h", ".inl", ".ins", ".hpp"] and
- os.path.basename(f).startswith("OSG"))]
-
- # Add files to their library object
- if (len(testFiles) or len(unittestFiles) or
- len(sourceFiles) or len(headerFiles)):
- if len(self.libNameStack) == 0 or self.libNameStack[-1] == "":
- print "ERROR: Attempt to add source files without library. " + \
- "In dir: %s" % fullDir
- sys.exit(1)
- libName = self.libNameStack[-1]
- self.libMap[libName].source_files += sourceFiles
- self.libMap[libName].header_files += headerFiles
- self.libMap[libName].test_files += testFiles
- self.libMap[libName].unittest_files += unittestFiles
-
- # Recurse into subdirectories
- for d in dirs:
- if not os.path.basename(d) in self.ignoredDirs:
- popStack = self._recursiveScan(d)
- if popStack:
- del self.libNameStack[-1]
-
- # return if anything was added to the libNameStack
- if hasBuildInfo:
- return True
- else:
- return False
-
-# ----------------------------- #
-# --- revision tag handling --- #
-# ----------------------------- #
-
-class RevisionTagWriter(object):
- """
- For each library the corresponding <Libname>Def.cpp file is located and
- the highest revision number of any of the lib's source files is recorded
- together with a marker if the lib contains local changes.
- """
- def __init__(self, libMap):
- """
- Create a new tag writer that uses the libraries from the given libMap.
- Also checks if pysvn is available - without it tagging is not possible.
- """
- if not have_pysvn:
- raise "The module pysvn is require to perform revision tagging!"
-
- self.libMap = libMap
- self.maxRev = 0
- self.svnClient = pysvn.Client()
-
- def run(self):
- """
- Write revision tags.
- """
- for (libName, libObj) in self.libMap.iteritems():
- libMaxRev = 0
- modifiedStr = ""
-
- for file in libObj.source_files + libObj.header_files:
- filename = pj("Source", file)
-
- fileRev, fileModified = self._getSVNInfo(filename)
-
- if libMaxRev < fileRev:
- libMaxRev = fileRev
-
- # we modify the <libname>Def.cpp files ourselves
- if fileModified and filename[-7:] != "Def.cpp":
- print "%s: file %s is modified!" % (libName, filename)
- modifiedStr = " !MODIFIED!"
-
- if modifiedStr != "":
- print "%s: There are modified files, revision might be inaccurate!" % libName
- print "%s: Highest revision: %d." % (libName, libMaxRev)
-
- if self.maxRev < libMaxRev:
- self.maxRev = libMaxRev
-
- for file in libObj.source_files:
- if file[-7:] == "Def.cpp":
- filename = pj("Source", file)
- fileInfo = self.svnClient.info(filename)
- repoPath = fileInfo.url[len(fileInfo.repos):-len(filename)-1]
-
- fileContents = open(filename).readlines()
- for i in range(len(fileContents)):
- if fileContents[i][:22] == '#define SVN_REVISION "':
- fileContents[i] = '#define SVN_REVISION "%d (%s)%s"\n' % (libMaxRev, repoPath, modifiedStr)
- break
- open(filename, "w").writelines(fileContents)
-
- # Update the documentation mainfile
- # Find the high version for stuff in Doc/, too
- modifiedStr = ""
- for file in glob.glob("Doc/*"):
- print file
- fileRev, fileMod = self._getSVNInfo(file)
-
- if self.maxRev < fileRev:
- self.maxRev = fileRev
- if fileMod:
- modifiedStr = " !Modified!"
-
- filename = "Doc/mainpage.dox"
- fileContents = open(filename).readlines()
- for i in range(len(fileContents)):
- if fileContents[i][:7] == 'version':
- fileContents[i] = 'version %s r%d %s\n' % (opensg_version_string, self.maxRev, modifiedStr)
- break
- open(filename,'w').writelines(fileContents)
-
- def _getSVNInfo(self, filename):
- """
- Get the svn info for the given file.
- Returns a version, modified tuple.
- """
- fileInfo = self.svnClient.info (filename)
- fileStatus = self.svnClient.status(filename)
-
- fileRev = 0
- fileMod = False
-
- # Ignore unversioned files
- if pysvn.wc_status_kind.unversioned != fileStatus[0].text_status and \
- pysvn.wc_status_kind.ignored != fileStatus[0].text_status:
- fileRev = fileInfo.revision.number
- fileMod = pysvn.wc_status_kind.modified == fileStatus[0].text_status
-
- return fileRev, fileMod
-
-
# ---------------------------------------------------------------------------- #
# ----------------------------- Main build setup ----------------------------- #
# ---------------------------------------------------------------------------- #
@@ -839,7 +585,8 @@
# Trigger recursive scanning of library directorties
if not verbose_build:
print "Scanning libraries: ",
- biScanner = BuildInfoScanner("Source", [".svn", "ES", "EGL"], verbose_build)
+ biScanner = BuildInfoScanner("Source", opts, common_env,
+ [".svn", "ES", "EGL"], verbose_build)
lib_map = biScanner.scan()
if not verbose_build:
print " found %s libraries" % len(lib_map)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core