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