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