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 5110 2010/07/25 16:14:38 bdeegan"
36
37
38
39 import os
40 import os.path
41 import errno
42 import shutil
43 import stat
44 import string
45 import time
46 import types
47 import sys
48
49 import SCons.Action
50 import SCons.Builder
51 import SCons.CacheDir
52 import SCons.Environment
53 import SCons.PathList
54 import SCons.Subst
55 import SCons.Tool
56
57
58
59
60
61 _default_env = None
62
63
64
66 """
67 Returns the already-created default construction environment.
68 """
69 global _default_env
70 return _default_env
71
73 """
74 Initial public entry point for creating the default construction
75 Environment.
76
77 After creating the environment, we overwrite our name
78 (DefaultEnvironment) with the _fetch_DefaultEnvironment() function,
79 which more efficiently returns the initialized default construction
80 environment without checking for its existence.
81
82 (This function still exists with its _default_check because someone
83 else (*cough* Script/__init__.py *cough*) may keep a reference
84 to this function. So we can't use the fully functional idiom of
85 having the name originally be a something that *only* creates the
86 construction environment and then overwrites the name.)
87 """
88 global _default_env
89 if not _default_env:
90 import SCons.Util
91 _default_env = apply(SCons.Environment.Environment, args, kw)
92 if SCons.Util.md5:
93 _default_env.Decider('MD5')
94 else:
95 _default_env.Decider('timestamp-match')
96 global DefaultEnvironment
97 DefaultEnvironment = _fetch_DefaultEnvironment
98 _default_env._CacheDir_path = None
99 return _default_env
100
101
102
103
105 for tgt in target:
106 tgt.attributes.shared = None
107 return (target, source)
108
110 for tgt in target:
111 tgt.attributes.shared = 1
112 return (target, source)
113
115 same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME')
116 if same == '0' or same == '' or same == 'False':
117 for src in source:
118 try:
119 shared = src.attributes.shared
120 except AttributeError:
121 shared = None
122 if not shared:
123 raise SCons.Errors.UserError, "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])
124
125 SharedCheck = SCons.Action.Action(SharedFlagChecker, None)
126
127
128
129
130
131 CScan = SCons.Tool.CScanner
132 DScan = SCons.Tool.DScanner
133 LaTeXScan = SCons.Tool.LaTeXScanner
134 ObjSourceScan = SCons.Tool.SourceFileScanner
135 ProgScan = SCons.Tool.ProgramScanner
136
137
138
139
140 import SCons.Scanner.Dir
141 DirScanner = SCons.Scanner.Dir.DirScanner()
142 DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner()
143
144
145 CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR")
146 ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR")
147 CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR")
148 ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR")
149
150 ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR")
151 ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR")
152
153 LinkAction = SCons.Action.Action("$LINKCOM", "$LINKCOMSTR")
154 ShLinkAction = SCons.Action.Action("$SHLINKCOM", "$SHLINKCOMSTR")
155
156 LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR")
157
158
159
160 ActionFactory = SCons.Action.ActionFactory
161
163
164 if SCons.Util.is_List(dest):
165 elem_strs = []
166 for element in dest:
167 elem_strs.append('"' + str(element) + '"')
168 return '[' + string.join(elem_strs, ', ') + ']'
169 else:
170 return '"' + str(dest) + '"'
171
178
180 return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode)
181
182 Chmod = ActionFactory(chmod_func, chmod_strfunc)
183
194
195 Copy = ActionFactory(copy_func,
196 lambda dest, src: 'Copy("%s", "%s")' % (dest, src),
197 convert=str)
198
213
215 return 'Delete(%s)' % get_paths_str(dest)
216
217 Delete = ActionFactory(delete_func, delete_strfunc)
218
220 SCons.Node.FS.invalidate_node_memos(dest)
221 if not SCons.Util.is_List(dest):
222 dest = [dest]
223 for entry in dest:
224 try:
225 os.makedirs(str(entry))
226 except os.error, e:
227 p = str(entry)
228 if (e[0] == errno.EEXIST or (sys.platform=='win32' and e[0]==183)) \
229 and os.path.isdir(str(entry)):
230 pass
231 else:
232 raise
233
234 Mkdir = ActionFactory(mkdir_func,
235 lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
236
241
242 Move = ActionFactory(move_func,
243 lambda dest, src: 'Move("%s", "%s")' % (dest, src),
244 convert=str)
245
247 SCons.Node.FS.invalidate_node_memos(dest)
248 if not SCons.Util.is_List(dest):
249 dest = [dest]
250 for file in dest:
251 file = str(file)
252 mtime = int(time.time())
253 if os.path.exists(file):
254 atime = os.path.getatime(file)
255 else:
256 open(file, 'w')
257 atime = mtime
258 os.utime(file, (atime, mtime))
259
260 Touch = ActionFactory(touch_func,
261 lambda file: 'Touch(%s)' % get_paths_str(file))
262
263
264
265 -def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
266 """
267 Creates a new list from 'list' by first interpolating each element
268 in the list using the 'env' dictionary and then calling f on the
269 list, and finally calling _concat_ixes to concatenate 'prefix' and
270 'suffix' onto each element of the list.
271 """
272 if not list:
273 return list
274
275 l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
276 if l is not None:
277 list = l
278
279 return _concat_ixes(prefix, list, suffix, env)
280
282 """
283 Creates a new list from 'list' by concatenating the 'prefix' and
284 'suffix' arguments onto each element of the list. A trailing space
285 on 'prefix' or leading space on 'suffix' will cause them to be put
286 into separate list elements rather than being concatenated.
287 """
288
289 result = []
290
291
292 prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
293 suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
294
295 for x in list:
296 if isinstance(x, SCons.Node.FS.File):
297 result.append(x)
298 continue
299 x = str(x)
300 if x:
301
302 if prefix:
303 if prefix[-1] == ' ':
304 result.append(prefix[:-1])
305 elif x[:len(prefix)] != prefix:
306 x = prefix + x
307
308 result.append(x)
309
310 if suffix:
311 if suffix[0] == ' ':
312 result.append(suffix[1:])
313 elif x[-len(suffix):] != suffix:
314 result[-1] = result[-1]+suffix
315
316 return result
317
318 -def _stripixes(prefix, list, suffix, stripprefixes, stripsuffixes, env, c=None):
319 """
320 This is a wrapper around _concat()/_concat_ixes() that checks for the
321 existence of prefixes or suffixes on list elements and strips them
322 where it finds them. This is used by tools (like the GNU linker)
323 that need to turn something like 'libfoo.a' into '-lfoo'.
324 """
325
326 if not list:
327 return list
328
329 if not callable(c):
330 env_c = env['_concat']
331 if env_c != _concat and callable(env_c):
332
333
334
335
336 c = env_c
337 else:
338 c = _concat_ixes
339
340 stripprefixes = map(env.subst, SCons.Util.flatten(stripprefixes))
341 stripsuffixes = map(env.subst, SCons.Util.flatten(stripsuffixes))
342
343 stripped = []
344 for l in SCons.PathList.PathList(list).subst_path(env, None, None):
345 if isinstance(l, SCons.Node.FS.File):
346 stripped.append(l)
347 continue
348
349 if not SCons.Util.is_String(l):
350 l = str(l)
351
352 for stripprefix in stripprefixes:
353 lsp = len(stripprefix)
354 if l[:lsp] == stripprefix:
355 l = l[lsp:]
356
357 break
358
359 for stripsuffix in stripsuffixes:
360 lss = len(stripsuffix)
361 if l[-lss:] == stripsuffix:
362 l = l[:-lss]
363
364 break
365
366 stripped.append(l)
367
368 return c(prefix, stripped, suffix, env)
369
371 """process defines, resolving strings, lists, dictionaries, into a list of
372 strings
373 """
374 if SCons.Util.is_List(defs):
375 l = []
376 for d in defs:
377 if SCons.Util.is_List(d) or type(d) is types.TupleType:
378 l.append(str(d[0]) + '=' + str(d[1]))
379 else:
380 l.append(str(d))
381 elif SCons.Util.is_Dict(defs):
382
383
384
385
386
387
388 l = []
389 keys = defs.keys()
390 keys.sort()
391 for k in keys:
392 v = defs[k]
393 if v is None:
394 l.append(str(k))
395 else:
396 l.append(str(k) + '=' + str(v))
397 else:
398 l = [str(defs)]
399 return l
400
401 -def _defines(prefix, defs, suffix, env, c=_concat_ixes):
402 """A wrapper around _concat_ixes that turns a list or string
403 into a list of C preprocessor command-line definitions.
404 """
405
406 return c(prefix, env.subst_path(processDefines(defs)), suffix, env)
407
409 """This is a callable class that can be used in place of other
410 command generators if you don't want them to do anything.
411
412 The __call__ method for this class simply returns the thing
413 you instantiated it with.
414
415 Example usage:
416 env["DO_NOTHING"] = NullCmdGenerator
417 env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
418 """
419
422
423 - def __call__(self, target, source, env, for_signature=None):
425
427 """A class for finding a construction variable on the stack and
428 calling one of its methods.
429
430 We use this to support "construction variables" in our string
431 eval()s that actually stand in for methods--specifically, use
432 of "RDirs" in call to _concat that should actually execute the
433 "TARGET.RDirs" method. (We used to support this by creating a little
434 "build dictionary" that mapped RDirs to the method, but this got in
435 the way of Memoizing construction environments, because we had to
436 create new environment objects to hold the variables.)
437 """
439 self.variable = variable
440 self.method = method
442 try: 1/0
443 except ZeroDivisionError:
444
445
446 frame = sys.exc_info()[2].tb_frame.f_back
447 variable = self.variable
448 while frame:
449 if frame.f_locals.has_key(variable):
450 v = frame.f_locals[variable]
451 if v:
452 method = getattr(v, self.method)
453 return apply(method, args, kw)
454 frame = frame.f_back
455 return None
456
457 ConstructionEnvironment = {
458 'BUILDERS' : {},
459 'SCANNERS' : [],
460 'CONFIGUREDIR' : '#/.sconf_temp',
461 'CONFIGURELOG' : '#/config.log',
462 'CPPSUFFIXES' : SCons.Tool.CSuffixes,
463 'DSUFFIXES' : SCons.Tool.DSuffixes,
464 'ENV' : {},
465 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
466
467 '_concat' : _concat,
468 '_defines' : _defines,
469 '_stripixes' : _stripixes,
470 '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
471 '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
472 '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
473 '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
474 'TEMPFILE' : NullCmdGenerator,
475 'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
476 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
477 'File' : Variable_Method_Caller('TARGET', 'File'),
478 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
479 }
480
481
482
483
484
485
486