| 1 |
|
|---|
| 2 |
import os |
|---|
| 3 |
import os.path |
|---|
| 4 |
import sys |
|---|
| 5 |
|
|---|
| 6 |
import SConsAddons.Util as sca_util |
|---|
| 7 |
from LibraryUtils import * |
|---|
| 8 |
|
|---|
| 9 |
pj = os.path.join |
|---|
| 10 |
|
|---|
| 11 |
class BuildInfoScanner(object): |
|---|
| 12 |
""" |
|---|
| 13 |
Recursively scans a directory tree for build.info files and constructs |
|---|
| 14 |
a list of libraries and their dependencies from their contents. |
|---|
| 15 |
|
|---|
| 16 |
- Finding build.info files: |
|---|
| 17 |
Every file found can override the settings inherited from parent |
|---|
| 18 |
directories. |
|---|
| 19 |
- Keep a stack of library names, we add to the top library. |
|---|
| 20 |
- All subdirectories of the baseDir are scanned, unless it is in |
|---|
| 21 |
ignoredDirs. |
|---|
| 22 |
- File names are relative to baseDir |
|---|
| 23 |
|
|---|
| 24 |
- Evaluating a build.info file: |
|---|
| 25 |
Input variables: |
|---|
| 26 |
- option_pass: If True, we only collect options. |
|---|
| 27 |
- opts: Either None or an Options object to add options to. |
|---|
| 28 |
- platform: The current plarform string. |
|---|
| 29 |
- compiler: The current compiler being used. |
|---|
| 30 |
Output variables: |
|---|
| 31 |
- library: Name of the library to which the current directory belongs. |
|---|
| 32 |
- stop_traversal: If True, ignore this directory and everything below it. |
|---|
| 33 |
|
|---|
| 34 |
- osg_dep_libs: List of OpenSG library names, this library depends upon (for linking). |
|---|
| 35 |
- libs: List of external library names, this library depends upon. |
|---|
| 36 |
- frameworks: List of framework names, this library depends upon. |
|---|
| 37 |
- cpppath: Additional include paths for building. |
|---|
| 38 |
- libpath: Additional library paths for linking. |
|---|
| 39 |
- frameworkpath: Additional framework paths to set. |
|---|
| 40 |
|
|---|
| 41 |
- osg_test_libs: List of OpenSG library names, this library depends |
|---|
| 42 |
upon for builing tests. |
|---|
| 43 |
- other_test_libs: List of external library names, this library depends |
|---|
| 44 |
upon for building tests. |
|---|
| 45 |
- test_cpppath: Additional include paths for building tests. |
|---|
| 46 |
- test_libpath: Additional library paths for linking tests. |
|---|
| 47 |
""" |
|---|
| 48 |
|
|---|
| 49 |
def __init__(self, baseDir, opts, env, ignoredDirs = None, verbose = False): |
|---|
| 50 |
self.baseDir = baseDir |
|---|
| 51 |
self.ignoredDirs = ignoredDirs |
|---|
| 52 |
self.opts = opts |
|---|
| 53 |
self.env = env |
|---|
| 54 |
self.platform = sca_util.GetPlatform(); |
|---|
| 55 |
self.verbose = verbose |
|---|
| 56 |
|
|---|
| 57 |
self.libMap = {} |
|---|
| 58 |
self.libNameStack = [] |
|---|
| 59 |
self.libAttributes = ["osg_dep_libs", "libs", "frameworks", "cpppath", |
|---|
| 60 |
"libpath", "frameworkpath","osg_test_libs", |
|---|
| 61 |
"other_test_libs","test_cpppath", "test_libpath"] |
|---|
| 62 |
|
|---|
| 63 |
def scan(self, scanDir = ""): |
|---|
| 64 |
"""Scan for build.info files in baseDir/scanDir keeping all file paths |
|---|
| 65 |
relative to baseDir. |
|---|
| 66 |
Returns the library map constructed from the files. |
|---|
| 67 |
""" |
|---|
| 68 |
self._recursiveScan(scanDir) |
|---|
| 69 |
return self.libMap |
|---|
| 70 |
|
|---|
| 71 |
def _recursiveScan(self, scanDir = ""): |
|---|
| 72 |
"""The actual recursive scanning routine. |
|---|
| 73 |
""" |
|---|
| 74 |
fullDir = pj(self.baseDir, scanDir) |
|---|
| 75 |
scanDirContents = [pj(scanDir, f) for f in os.listdir(fullDir)] |
|---|
| 76 |
files = [f for f in scanDirContents if os.path.isfile(pj(self.baseDir, f))] |
|---|
| 77 |
dirs = [d for d in scanDirContents if os.path.isdir(pj(self.baseDir, d))] |
|---|
| 78 |
|
|---|
| 79 |
hasBuildInfo = os.path.exists(pj(fullDir, "build.info")) |
|---|
| 80 |
|
|---|
| 81 |
if hasBuildInfo: |
|---|
| 82 |
biFilename = pj(fullDir, "build.info") |
|---|
| 83 |
|
|---|
| 84 |
if self.verbose: |
|---|
| 85 |
print " Reading: ", biFilename |
|---|
| 86 |
else: |
|---|
| 87 |
sys.stdout.write(".") |
|---|
| 88 |
|
|---|
| 89 |
biDict = dict([("option_pass", False), |
|---|
| 90 |
("opts", self.opts), |
|---|
| 91 |
("platform", self.platform), |
|---|
| 92 |
("compiler", self.env["CXX"]), |
|---|
| 93 |
("stop_traversal", False)]) |
|---|
| 94 |
|
|---|
| 95 |
for attrib in self.libAttributes: |
|---|
| 96 |
biDict[attrib] = [] |
|---|
| 97 |
|
|---|
| 98 |
execfile(biFilename, biDict) |
|---|
| 99 |
|
|---|
| 100 |
if biDict["stop_traversal"]: |
|---|
| 101 |
if self.verbose: |
|---|
| 102 |
print " Pruning traversal." |
|---|
| 103 |
return False |
|---|
| 104 |
|
|---|
| 105 |
if not biDict.has_key("library") or biDict["library"] == None: |
|---|
| 106 |
print "ERROR: No 'library' specified in build.info file: ", biFilename |
|---|
| 107 |
sys.exit(1) |
|---|
| 108 |
|
|---|
| 109 |
libName = biDict["library"] |
|---|
| 110 |
if not self.libMap.has_key(libName): |
|---|
| 111 |
self.libMap[libName] = LibraryInfo(name = libName) |
|---|
| 112 |
if self.verbose: |
|---|
| 113 |
print "Created new LibraryInfo: ", libName |
|---|
| 114 |
|
|---|
| 115 |
self.libNameStack.append(libName) |
|---|
| 116 |
|
|---|
| 117 |
if self.verbose: |
|---|
| 118 |
print "Library name: ", libName |
|---|
| 119 |
|
|---|
| 120 |
|
|---|
| 121 |
|
|---|
| 122 |
for attrib in self.libAttributes: |
|---|
| 123 |
attribList = getattr(self.libMap[libName], attrib) |
|---|
| 124 |
attribList.extend([a for a in biDict[attrib] if a not in attribList]) |
|---|
| 125 |
|
|---|
| 126 |
|
|---|
| 127 |
|
|---|
| 128 |
testFiles = [f for f in files if (os.path.basename(f).startswith("test") and |
|---|
| 129 |
os.path.splitext(f)[1] in [".cpp",".cc",".mm"])]; |
|---|
| 130 |
unittestFiles = [f for f in files if (os.path.basename(f).endswith("Test.cpp") and |
|---|
| 131 |
os.path.basename(f).startswith("OSG"))] |
|---|
| 132 |
sourceFiles = [f for f in files if (os.path.splitext(f)[1] in [".cpp", ".cc", ".mm"] and |
|---|
| 133 |
os.path.basename(f).startswith("OSG") and |
|---|
| 134 |
f not in testFiles and f not in unittestFiles)] |
|---|
| 135 |
headerFiles = [f for f in files if (os.path.splitext(f)[1] in [".h", ".inl", ".ins", ".hpp"] and |
|---|
| 136 |
os.path.basename(f).startswith("OSG"))] |
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
if (len(testFiles) or len(unittestFiles) or |
|---|
| 140 |
len(sourceFiles) or len(headerFiles)): |
|---|
| 141 |
if len(self.libNameStack) == 0 or self.libNameStack[-1] == "": |
|---|
| 142 |
print "ERROR: Attempt to add source files without library. " + \ |
|---|
| 143 |
"In dir: %s" % fullDir |
|---|
| 144 |
sys.exit(1) |
|---|
| 145 |
libName = self.libNameStack[-1] |
|---|
| 146 |
self.libMap[libName].source_files += sourceFiles |
|---|
| 147 |
self.libMap[libName].header_files += headerFiles |
|---|
| 148 |
self.libMap[libName].test_files += testFiles |
|---|
| 149 |
self.libMap[libName].unittest_files += unittestFiles |
|---|
| 150 |
|
|---|
| 151 |
|
|---|
| 152 |
for d in dirs: |
|---|
| 153 |
if not os.path.basename(d) in self.ignoredDirs: |
|---|
| 154 |
popStack = self._recursiveScan(d) |
|---|
| 155 |
if popStack: |
|---|
| 156 |
del self.libNameStack[-1] |
|---|
| 157 |
|
|---|
| 158 |
|
|---|
| 159 |
if hasBuildInfo: |
|---|
| 160 |
return True |
|---|
| 161 |
else: |
|---|
| 162 |
return False |
|---|