1 """SCons.Defaults
2
3 Builders and other things for the local site. Here's where we'll
4 duplicate the functionality of autoconf until we move it into the
5 installation procedure or use something like qmconf.
6
7 The code that reads the registry to find MSVC components was borrowed
8 from distutils.msvccompiler.
9
10 """
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 __revision__ = "src/engine/SCons/Defaults.py 2928 2008/04/29 22:44:09 knight"
36
37
38
39 import os
40 import os.path
41 import shutil
42 import stat
43 import string
44 import time
45 import types
46 import sys
47
48 import SCons.Action
49 import SCons.Builder
50 import SCons.CacheDir
51 import SCons.Environment
52 import SCons.PathList
53 import SCons.Subst
54 import SCons.Tool
55
56
57
58
59
60 _default_env = None
61
62
63
65 """
66 Returns the already-created default construction environment.
67 """
68 global _default_env
69 return _default_env
70
72 """
73 Initial public entry point for creating the default construction
74 Environment.
75
76 After creating the environment, we overwrite our name
77 (DefaultEnvironment) with the _fetch_DefaultEnvironment() function,
78 which more efficiently returns the initialized default construction
79 environment without checking for its existence.
80
81 (This function still exists with its _default_check because someone
82 else (*cough* Script/__init__.py *cough*) may keep a reference
83 to this function. So we can't use the fully functional idiom of
84 having the name originally be a something that *only* creates the
85 construction environment and then overwrites the name.)
86 """
87 global _default_env
88 if not _default_env:
89 import SCons.Util
90 _default_env = apply(SCons.Environment.Environment, args, kw)
91 if SCons.Util.md5:
92 _default_env.Decider('MD5')
93 else:
94 _default_env.Decider('timestamp-match')
95 global DefaultEnvironment
96 DefaultEnvironment = _fetch_DefaultEnvironment
97 _default_env._CacheDir_path = None
98 return _default_env
99
100
101
102
104 for tgt in target:
105 tgt.attributes.shared = None
106 return (target, source)
107
109 for tgt in target:
110 tgt.attributes.shared = 1
111 return (target, source)
112
114 same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME')
115 if same == '0' or same == '' or same == 'False':
116 for src in source:
117 try:
118 shared = src.attributes.shared
119 except AttributeError:
120 shared = None
121 if not shared:
122 raise SCons.Errors.UserError, "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])
123
124 SharedCheck = SCons.Action.Action(SharedFlagChecker, None)
125
126
127
128
129
130 CScan = SCons.Tool.CScanner
131 DScan = SCons.Tool.DScanner
132 LaTeXScan = SCons.Tool.LaTeXScanner
133 ObjSourceScan = SCons.Tool.SourceFileScanner
134 ProgScan = SCons.Tool.ProgramScanner
135
136
137
138
139 import SCons.Scanner.Dir
140 DirScanner = SCons.Scanner.Dir.DirScanner()
141 DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner()
142
143
144 CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR")
145 ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR")
146 CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR")
147 ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR")
148
149 ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR")
150 ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR")
151
152 LinkAction = SCons.Action.Action("$LINKCOM", "$LINKCOMSTR")
153 ShLinkAction = SCons.Action.Action("$SHLINKCOM", "$SHLINKCOMSTR")
154
155 LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR")
156
157
158
159 ActionFactory = SCons.Action.ActionFactory
160
162
163 if SCons.Util.is_List(dest):
164 elem_strs = []
165 for element in dest:
166 elem_strs.append('"' + str(element) + '"')
167 return '[' + string.join(elem_strs, ', ') + ']'
168 else:
169 return '"' + str(dest) + '"'
170
172 if not SCons.Util.is_List(dest):
173 dest = [dest]
174 for element in dest:
175 os.chmod(str(element), mode)
176
178 return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode)
179
180 Chmod = ActionFactory(chmod_func, chmod_strfunc)
181
183 if SCons.Util.is_List(src) and os.path.isdir(dest):
184 for file in src:
185 shutil.copy2(file, dest)
186 return 0
187 elif os.path.isfile(src):
188 return shutil.copy2(src, dest)
189 else:
190 return shutil.copytree(src, dest, 1)
191
192 Copy = ActionFactory(copy_func,
193 lambda dest, src: 'Copy("%s", "%s")' % (dest, src),
194 convert=str)
195
197 if not SCons.Util.is_List(dest):
198 dest = [dest]
199 for entry in dest:
200 entry = str(entry)
201 if not must_exist and not os.path.exists(entry):
202 continue
203 if not os.path.exists(entry) or os.path.isfile(entry):
204 os.unlink(entry)
205 continue
206 else:
207 shutil.rmtree(entry, 1)
208 continue
209
211 return 'Delete(%s)' % get_paths_str(dest)
212
213 Delete = ActionFactory(delete_func, delete_strfunc)
214
216 if not SCons.Util.is_List(dest):
217 dest = [dest]
218 for entry in dest:
219 os.makedirs(str(entry))
220
221 Mkdir = ActionFactory(mkdir_func,
222 lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
223
224 Move = ActionFactory(lambda dest, src: os.rename(src, dest),
225 lambda dest, src: 'Move("%s", "%s")' % (dest, src),
226 convert=str)
227
229 if not SCons.Util.is_List(dest):
230 dest = [dest]
231 for file in dest:
232 file = str(file)
233 mtime = int(time.time())
234 if os.path.exists(file):
235 atime = os.path.getatime(file)
236 else:
237 open(file, 'w')
238 atime = mtime
239 os.utime(file, (atime, mtime))
240
241 Touch = ActionFactory(touch_func,
242 lambda file: 'Touch(%s)' % get_paths_str(file))
243
244
245
246 -def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
247 """
248 Creates a new list from 'list' by first interpolating each element
249 in the list using the 'env' dictionary and then calling f on the
250 list, and finally calling _concat_ixes to concatenate 'prefix' and
251 'suffix' onto each element of the list.
252 """
253 if not list:
254 return list
255
256 l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
257 if not l is None:
258 list = l
259
260 return _concat_ixes(prefix, list, suffix, env)
261
263 """
264 Creates a new list from 'list' by concatenating the 'prefix' and
265 'suffix' arguments onto each element of the list. A trailing space
266 on 'prefix' or leading space on 'suffix' will cause them to be put
267 into separate list elements rather than being concatenated.
268 """
269
270 result = []
271
272
273 prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
274 suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
275
276 for x in list:
277 if isinstance(x, SCons.Node.FS.File):
278 result.append(x)
279 continue
280 x = str(x)
281 if x:
282
283 if prefix:
284 if prefix[-1] == ' ':
285 result.append(prefix[:-1])
286 elif x[:len(prefix)] != prefix:
287 x = prefix + x
288
289 result.append(x)
290
291 if suffix:
292 if suffix[0] == ' ':
293 result.append(suffix[1:])
294 elif x[-len(suffix):] != suffix:
295 result[-1] = result[-1]+suffix
296
297 return result
298
299 -def _stripixes(prefix, list, suffix, stripprefixes, stripsuffixes, env, c=None):
300 """
301 This is a wrapper around _concat()/_concat_ixes() that checks for the
302 existence of prefixes or suffixes on list elements and strips them
303 where it finds them. This is used by tools (like the GNU linker)
304 that need to turn something like 'libfoo.a' into '-lfoo'.
305 """
306
307 if not list:
308 return list
309
310 if not callable(c):
311 env_c = env['_concat']
312 if env_c != _concat and callable(env_c):
313
314
315
316
317 c = env_c
318 else:
319 c = _concat_ixes
320
321 stripprefixes = map(env.subst, SCons.Util.flatten(stripprefixes))
322 stripsuffixes = map(env.subst, SCons.Util.flatten(stripsuffixes))
323
324 stripped = []
325 for l in SCons.PathList.PathList(list).subst_path(env, None, None):
326 if isinstance(l, SCons.Node.FS.File):
327 stripped.append(l)
328 continue
329
330 if not SCons.Util.is_String(l):
331 l = str(l)
332
333 for stripprefix in stripprefixes:
334 lsp = len(stripprefix)
335 if l[:lsp] == stripprefix:
336 l = l[lsp:]
337
338 break
339
340 for stripsuffix in stripsuffixes:
341 lss = len(stripsuffix)
342 if l[-lss:] == stripsuffix:
343 l = l[:-lss]
344
345 break
346
347 stripped.append(l)
348
349 return c(prefix, stripped, suffix, env)
350
351 -def _defines(prefix, defs, suffix, env, c=_concat_ixes):
352 """A wrapper around _concat_ixes that turns a list or string
353 into a list of C preprocessor command-line definitions.
354 """
355 if SCons.Util.is_List(defs):
356 l = []
357 for d in defs:
358 if SCons.Util.is_List(d) or type(d) is types.TupleType:
359 l.append(str(d[0]) + '=' + str(d[1]))
360 else:
361 l.append(str(d))
362 elif SCons.Util.is_Dict(defs):
363
364
365
366
367
368
369 l = []
370 keys = defs.keys()
371 keys.sort()
372 for k in keys:
373 v = defs[k]
374 if v is None:
375 l.append(str(k))
376 else:
377 l.append(str(k) + '=' + str(v))
378 else:
379 l = [str(defs)]
380 return c(prefix, env.subst_path(l), suffix, env)
381
383 """This is a callable class that can be used in place of other
384 command generators if you don't want them to do anything.
385
386 The __call__ method for this class simply returns the thing
387 you instantiated it with.
388
389 Example usage:
390 env["DO_NOTHING"] = NullCmdGenerator
391 env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
392 """
393
396
397 - def __call__(self, target, source, env, for_signature=None):
399
401 """A class for finding a construction variable on the stack and
402 calling one of its methods.
403
404 We use this to support "construction variables" in our string
405 eval()s that actually stand in for methods--specifically, use
406 of "RDirs" in call to _concat that should actually execute the
407 "TARGET.RDirs" method. (We used to support this by creating a little
408 "build dictionary" that mapped RDirs to the method, but this got in
409 the way of Memoizing construction environments, because we had to
410 create new environment objects to hold the variables.)
411 """
413 self.variable = variable
414 self.method = method
416 try: 1/0
417 except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
418 variable = self.variable
419 while frame:
420 if frame.f_locals.has_key(variable):
421 v = frame.f_locals[variable]
422 if v:
423 method = getattr(v, self.method)
424 return apply(method, args, kw)
425 frame = frame.f_back
426 return None
427
428 ConstructionEnvironment = {
429 'BUILDERS' : {},
430 'SCANNERS' : [],
431 'CONFIGUREDIR' : '#/.sconf_temp',
432 'CONFIGURELOG' : '#/config.log',
433 'CPPSUFFIXES' : SCons.Tool.CSuffixes,
434 'DSUFFIXES' : SCons.Tool.DSuffixes,
435 'ENV' : {},
436 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
437 'LATEXSUFFIXES' : SCons.Tool.LaTeXSuffixes,
438 '_concat' : _concat,
439 '_defines' : _defines,
440 '_stripixes' : _stripixes,
441 '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
442 '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
443 '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
444 '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
445 'TEMPFILE' : NullCmdGenerator,
446 'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
447 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
448 'File' : Variable_Method_Caller('TARGET', 'File'),
449 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
450 }
451