Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
Buildhelper.py
Go to the documentation of this file.
1# coding: utf-8
2
5
6# Copyright (C)
7# 2008-2025 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
15import os
16import sys
17import glob
18import fnmatch
19
20from SCons import Util
21
22
23
24#
25# Common Helper Functions
26#
27def isCleanupOperation(env):
28 return env.GetOption('clean')
29
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
40def 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
48SRCPATTERNS = ['*.c','*.cpp','*.cc']
49
50def 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
64def 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
74def 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
93def 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
107def getDirname (d, basePrefix=None):
108 """ extract directory name without leading path,
109 or without the explicitly given basePrefix
110 """
111 d = os.path.realpath(d)
112 if not os.path.isdir(d):
113 d,_ = os.path.split(d)
114 if basePrefix:
115 basePrefix = os.path.realpath(basePrefix)
116 name = stripPrefix(str(d), basePrefix)
117 else:
118 _, name = os.path.split(d)
119 return name
120
121
122
123def stripPrefix(path, prefix):
124 if path.startswith(prefix):
125 path = path[len(prefix):]
126 return path
127
128
129
130def createPlugins(env, directory, **kw):
131 """ investigate the given source directory to identify all contained source trees.
132 @return: a list of build nodes defining a plugin for each of these source trees.
133 """
134 return [env.LumieraPlugin( getDirname(tree)
135 , srcSubtree(tree)
136 , **kw
137 )
138 for tree in findSrcTrees(directory)
139 ]
140
141
142
143def checkCommandOption(env, optID, val=None, cmdName=None):
144 """ evaluate and verify an option, which may point at a command.
145 besides specifying a path, the option may read True, yes or 1,
146 denoting that the system default for this command should be used.
147 @return: True, if the key has been expanded and validated,
148 False, if this failed and the key was removed
149 """
150 if not val:
151 if not env.get(optID): return False
152 else:
153 val = env.get(optID)
154
155 if val=='True' or val=='true' or val=='yes' or val=='1' or val == 1 :
156 if not cmdName:
157 print("WARNING: no default for %s, please specify a full path." % optID)
158 del env[optID]
159 return False
160 else:
161 val = env.WhereIs(cmdName)
162 if not val:
163 print("WARNING: %s not found, please specify a full path" % cmdName)
164 del env[optID]
165 return False
166
167 if not os.path.isfile(val):
168 val = env.WhereIs(val)
169
170 if val and os.path.isfile(val):
171 env[optID] = val
172 return True
173 else:
174 del env[optID]
175 return False
176
177
178
179
180class Record(dict):
181 """ a set of properties with record style access.
182 Record is a dictionary, but the elements can be accessed
183 conveniently as if they where object fields
184 """
185 def __init__(self, defaults=None, **props):
186 if defaults:
187 defaults.update(props)
188 props = defaults
189 dict.__init__(self,props)
190
191 def __getattr__(self,key):
192 if key=='__get__' or key=='__set__':
193 raise AttributeError
194 return self.setdefault(key)
195
196 def __setattr__(self,key,val):
197 self[key] = val
198
199
200def extract_localPathDefs (localDefs):
201 """ extracts the directory configuration values.
202 For sake of simplicity, paths and directories are defined
203 immediately as global variables in the SConstruct. This helper
204 extracts from the given dict the variables matching some magical
205 pattern and returns them wrapped into a Record for convenient access
206 """
207 def relevantPathDefs (mapping):
208 for (k,v) in mapping.items():
209 if (k.startswith('src') or k.startswith('build') or k.startswith('install')) and Util.is_String(v):
210 v = v.strip()
211 if not v.endswith('/'): v += '/'
212 yield (k,v)
213
214 return dict(relevantPathDefs(localDefs))
a set of properties with record style access.
__setattr__(self, key, val)
__getattr__(self, key)
__init__(self, defaults=None, **props)
srcSubtree(tree, **args)
convenience wrapper: scan the given subtree, which is relative to the current SConscript,...
isHelpRequest()
this is a hack: SCons does all configure tests even if only the help message is requested.
extract_localPathDefs(localDefs)
extracts the directory configuration values.
stripPrefix(path, prefix)
isSrcDir(path, patterns=SRCPATTERNS)
helper: investigate the given (relative) path
checkCommandOption(env, optID, val=None, cmdName=None)
evaluate and verify an option, which may point at a command.
globRootdirs(roots)
helper: expand shell wildcards and filter the resulting list, so that it only contains existing direc...
getDirname(d, basePrefix=None)
extract directory name without leading path, or without the explicitly given basePrefix
scanSubtree(roots, patterns=SRCPATTERNS)
first expand (possible) wildcards and filter out non-dirs.
createPlugins(env, directory, **kw)
investigate the given source directory to identify all contained source trees.
findSrcTrees(location, patterns=SRCPATTERNS)
find possible source tree roots, starting with the given location.