Lumiera  0.pre.03
»edityourfreedom«
Buildhelper.py
Go to the documentation of this file.
1 # -*- python -*-
2 
5 
6 # Copyright (C) Lumiera.org
7 # 2008, Hermann Vosseler <Ichthyostega@web.de>
8 #
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License as
11 # published by the Free Software Foundation; either version 2 of
12 # the License, or (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 
23 
24 import os
25 import sys
26 import glob
27 import fnmatch
28 
29 from SCons import Util
30 
31 
32 
33 #
34 # Common Helper Functions
35 #
37  return env.GetOption('clean')
38 
40  """ this is a hack: SCons does all configure tests even if only
41  the help message is requested. SCons doesn't export the
42  help option for retrieval by env.GetOption(),
43  so we scan the commandline directly.
44  """
45  return '-h' in sys.argv or '--help' in sys.argv
46 
47 
48 
49 def srcSubtree(tree, **args):
50  """ convenience wrapper: scan the given subtree, which is relative
51  to the current SConscript, and find all source files.
52  """
53  return list(scanSubtree(tree, **args))
54 
55 
56 
57 SRCPATTERNS = ['*.c','*.cpp','*.cc']
58 
59 def scanSubtree(roots, patterns=SRCPATTERNS):
60  """ first expand (possible) wildcards and filter out non-dirs.
61  Then scan the given subtree for source filenames
62  (python generator function)
63  """
64  for root in globRootdirs(roots):
65  for (d,_,files) in os.walk(root):
66  if d.startswith('./'):
67  d = d[2:]
68  for p in patterns:
69  for f in fnmatch.filter(files, p):
70  yield os.path.join(d,f)
71 
72 
73 
74 def globRootdirs(roots):
75  """ helper: expand shell wildcards and filter the resulting list,
76  so that it only contains existing directories
77  """
78  isDirectory = lambda f: os.path.isdir(f) and os.path.exists(f)
79  roots = glob.glob(roots)
80  return (d for d in roots if isDirectory(d) )
81 
82 
83 
84 def findSrcTrees(location, patterns=SRCPATTERNS):
85  """ find possible source tree roots, starting with the given location.
86  When delving down from the initial location(s), a source tree is defined
87  as a directory containing source files and possibly further sub directories.
88  After having initially expanded the given location with #globRootdirs, each
89  directory is examined depth first, until encountering a directory containing
90  source files, which then yields a result. Especially, this can be used to traverse
91  an organisational directory structure and find out all possible source trees
92  to be built into packages, plugins, individual tool executables etc.
93  @return: the relative path names of all source root dirs found (generator function).
94  """
95  for directory in globRootdirs(location):
96  if isSrcDir (directory,patterns):
97  yield directory
98  else:
99  for result in findSrcTrees (str(directory)+'/*'):
100  yield result
101 
102 
103 def isSrcDir(path, patterns=SRCPATTERNS):
104  """ helper: investigate the given (relative) path
105  @param patterns: list of wildcards to define what counts as "source file"
106  @return: True if it's a directory containing any source file
107  """
108  if not os.path.isdir(path):
109  return False
110  else:
111  for p in patterns:
112  if glob.glob(path+'/'+p):
113  return True
114 
115 
116 
117 def filterNodes(nlist, removeName=None):
118  """ filter out scons build nodes using the given criteria.
119  removeName: if set, remove all nodes with this srcname
120  """
121  if removeName:
122  predicate = lambda n : not fnmatch.fnmatch(os.path.basename(str(n[0])), removeName)
123  else:
124  predicate = lambda n : True
125 
126  return filter(predicate, nlist)
127 
128 
129 
130 def getDirname (d, basePrefix=None):
131  """ extract directory name without leading path,
132  or without the explicitly given basePrefix
133  """
134  d = os.path.realpath(d)
135  if not os.path.isdir(d):
136  d,_ = os.path.split(d)
137  if basePrefix:
138  basePrefix = os.path.realpath(basePrefix)
139  name = str(d)
140  if str(d).startswith(basePrefix):
141  name = name[len(basePrefix):]
142  else:
143  _, name = os.path.split(d)
144  return name
145 
146 
147 
148 def createPlugins(env, directory, **kw):
149  """ investigate the given source directory to identify all contained source trees.
150  @return: a list of build nodes defining a plugin for each of these source trees.
151  """
152  return [env.LumieraPlugin( getDirname(tree)
153  , srcSubtree(tree)
154  , **kw
155  )
156  for tree in findSrcTrees(directory)
157  ]
158 
159 
160 
161 def checkCommandOption(env, optID, val=None, cmdName=None):
162  """ evaluate and verify an option, which may point at a command.
163  besides specifying a path, the option may read True, yes or 1,
164  denoting that the system default for this command should be used.
165  @return: True, if the key has been expanded and validated,
166  False, if this failed and the key was removed
167  """
168  if not val:
169  if not env.get(optID): return False
170  else:
171  val = env.get(optID)
172 
173  if val=='True' or val=='true' or val=='yes' or val=='1' or val == 1 :
174  if not cmdName:
175  print "WARNING: no default for %s, please specify a full path." % optID
176  del env[optID]
177  return False
178  else:
179  val = env.WhereIs(cmdName)
180  if not val:
181  print "WARNING: %s not found, please specify a full path" % cmdName
182  del env[optID]
183  return False
184 
185  if not os.path.isfile(val):
186  val = env.WhereIs(val)
187 
188  if val and os.path.isfile(val):
189  env[optID] = val
190  return True
191  else:
192  del env[optID]
193  return False
194 
195 
196 
197 
198 class Record(dict):
199  """ a set of properties with record style access.
200  Record is a dictionary, but the elements can be accessed
201  conveniently as if they where object fields
202  """
203  def __init__(self, defaults=None, **props):
204  if defaults:
205  defaults.update(props)
206  props = defaults
207  dict.__init__(self,props)
208 
209  def __getattr__(self,key):
210  if key=='__get__' or key=='__set__':
211  raise AttributeError
212  return self.setdefault(key)
213 
214  def __setattr__(self,key,val):
215  self[key] = val
216 
217 
218 def extract_localPathDefs (localDefs):
219  """ extracts the directory configuration values.
220  For sake of simplicity, paths and directories are defined
221  immediately as global variables in the SConstruct. This helper
222  extracts from the given dict the variables matching some magical
223  pattern and returns them wrapped into a Record for convenient access
224  """
225  def relevantPathDefs (mapping):
226  for (k,v) in mapping.items():
227  if (k.startswith('src') or k.startswith('build') or k.startswith('install')) and Util.is_String(v):
228  v = v.strip()
229  if not v.endswith('/'): v += '/'
230  yield (k,v)
231 
232  return dict(relevantPathDefs(localDefs))
def isSrcDir(path, patterns=SRCPATTERNS)
Definition: Buildhelper.py:103
def extract_localPathDefs(localDefs)
Definition: Buildhelper.py:218
def getDirname(d, basePrefix=None)
Definition: Buildhelper.py:130
def isCleanupOperation(env)
Definition: Buildhelper.py:36
def __setattr__(self, key, val)
Definition: Buildhelper.py:214
def globRootdirs(roots)
Definition: Buildhelper.py:74
def __getattr__(self, key)
Definition: Buildhelper.py:209
def createPlugins(env, directory, kw)
Definition: Buildhelper.py:148
def findSrcTrees(location, patterns=SRCPATTERNS)
Definition: Buildhelper.py:84
def __init__(self, defaults=None, props)
Definition: Buildhelper.py:203
def scanSubtree(roots, patterns=SRCPATTERNS)
Definition: Buildhelper.py:59
def isHelpRequest()
Definition: Buildhelper.py:39
def srcSubtree(tree, args)
Definition: Buildhelper.py:49
def filterNodes(nlist, removeName=None)
Definition: Buildhelper.py:117
def checkCommandOption(env, optID, val=None, cmdName=None)
Definition: Buildhelper.py:161