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/07/05 09:42:21 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 DAction = SCons.Action.Action("$DCOM", "$DCOMSTR")
148 ShDAction = SCons.Action.Action("$SHDCOM", "$SHDCOMSTR")
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 '[' + ', '.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
214
216 return 'Delete(%s)' % get_paths_str(dest)
217
218 Delete = ActionFactory(delete_func, delete_strfunc)
219
221 SCons.Node.FS.invalidate_node_memos(dest)
222 if not SCons.Util.is_List(dest):
223 dest = [dest]
224 for entry in dest:
225 try:
226 os.makedirs(str(entry))
227 except os.error, e:
228 p = str(entry)
229 if (e.args[0] == errno.EEXIST or
230 (sys.platform=='win32' and e.args[0]==183)) \
231 and os.path.isdir(str(entry)):
232 pass
233 else:
234 raise
235
236 Mkdir = ActionFactory(mkdir_func,
237 lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
238
243
244 Move = ActionFactory(move_func,
245 lambda dest, src: 'Move("%s", "%s")' % (dest, src),
246 convert=str)
247
249 SCons.Node.FS.invalidate_node_memos(dest)
250 if not SCons.Util.is_List(dest):
251 dest = [dest]
252 for file in dest:
253 file = str(file)
254 mtime = int(time.time())
255 if os.path.exists(file):
256 atime = os.path.getatime(file)
257 else:
258 open(file, 'w')
259 atime = mtime
260 os.utime(file, (atime, mtime))
261
262 Touch = ActionFactory(touch_func,
263 lambda file: 'Touch(%s)' % get_paths_str(file))
264
265
266
267 -def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
268 """
269 Creates a new list from 'list' by first interpolating each element
270 in the list using the 'env' dictionary and then calling f on the
271 list, and finally calling _concat_ixes to concatenate 'prefix' and
272 'suffix' onto each element of the list.
273 """
274 if not list:
275 return list
276
277 l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
278 if l is not None:
279 list = l
280
281 return _concat_ixes(prefix, list, suffix, env)
282
284 """
285 Creates a new list from 'list' by concatenating the 'prefix' and
286 'suffix' arguments onto each element of the list. A trailing space
287 on 'prefix' or leading space on 'suffix' will cause them to be put
288 into separate list elements rather than being concatenated.
289 """
290
291 result = []
292
293
294 prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
295 suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
296
297 for x in list:
298 if isinstance(x, SCons.Node.FS.File):
299 result.append(x)
300 continue
301 x = str(x)
302 if x:
303
304 if prefix:
305 if prefix[-1] == ' ':
306 result.append(prefix[:-1])
307 elif x[:len(prefix)] != prefix:
308 x = prefix + x
309
310 result.append(x)
311
312 if suffix:
313 if suffix[0] == ' ':
314 result.append(suffix[1:])
315 elif x[-len(suffix):] != suffix:
316 result[-1] = result[-1]+suffix
317
318 return result
319
320 -def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None):
321 """
322 This is a wrapper around _concat()/_concat_ixes() that checks for
323 the existence of prefixes or suffixes on list items and strips them
324 where it finds them. This is used by tools (like the GNU linker)
325 that need to turn something like 'libfoo.a' into '-lfoo'.
326 """
327
328 if not itms:
329 return itms
330
331 if not callable(c):
332 env_c = env['_concat']
333 if env_c != _concat and callable(env_c):
334
335
336
337
338 c = env_c
339 else:
340 c = _concat_ixes
341
342 stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes)))
343 stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes)))
344
345 stripped = []
346 for l in SCons.PathList.PathList(itms).subst_path(env, None, None):
347 if isinstance(l, SCons.Node.FS.File):
348 stripped.append(l)
349 continue
350
351 if not SCons.Util.is_String(l):
352 l = str(l)
353
354 for stripprefix in stripprefixes:
355 lsp = len(stripprefix)
356 if l[:lsp] == stripprefix:
357 l = l[lsp:]
358
359 break
360
361 for stripsuffix in stripsuffixes:
362 lss = len(stripsuffix)
363 if l[-lss:] == stripsuffix:
364 l = l[:-lss]
365
366 break
367
368 stripped.append(l)
369
370 return c(prefix, stripped, suffix, env)
371
373 """process defines, resolving strings, lists, dictionaries, into a list of
374 strings
375 """
376 if SCons.Util.is_List(defs):
377 l = []
378 for d in defs:
379 if d is None:
380 continue
381 elif SCons.Util.is_List(d) or isinstance(d, tuple):
382 if len(d) >= 2:
383 l.append(str(d[0]) + '=' + str(d[1]))
384 else:
385 l.append(str(d[0]))
386 elif SCons.Util.is_Dict(d):
387 for macro,value in d.iteritems():
388 if value is not None:
389 l.append(str(macro) + '=' + str(value))
390 else:
391 l.append(str(macro))
392 elif SCons.Util.is_String(d):
393 l.append(str(d))
394 else:
395 raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None."%repr(d))
396 elif SCons.Util.is_Dict(defs):
397
398
399
400
401
402
403 l = []
404 for k,v in sorted(defs.items()):
405 if v is None:
406 l.append(str(k))
407 else:
408 l.append(str(k) + '=' + str(v))
409 else:
410 l = [str(defs)]
411 return l
412
413 -def _defines(prefix, defs, suffix, env, c=_concat_ixes):
414 """A wrapper around _concat_ixes that turns a list or string
415 into a list of C preprocessor command-line definitions.
416 """
417
418 return c(prefix, env.subst_path(processDefines(defs)), suffix, env)
419
421 """This is a callable class that can be used in place of other
422 command generators if you don't want them to do anything.
423
424 The __call__ method for this class simply returns the thing
425 you instantiated it with.
426
427 Example usage:
428 env["DO_NOTHING"] = NullCmdGenerator
429 env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
430 """
431
434
435 - def __call__(self, target, source, env, for_signature=None):
437
439 """A class for finding a construction variable on the stack and
440 calling one of its methods.
441
442 We use this to support "construction variables" in our string
443 eval()s that actually stand in for methods--specifically, use
444 of "RDirs" in call to _concat that should actually execute the
445 "TARGET.RDirs" method. (We used to support this by creating a little
446 "build dictionary" that mapped RDirs to the method, but this got in
447 the way of Memoizing construction environments, because we had to
448 create new environment objects to hold the variables.)
449 """
451 self.variable = variable
452 self.method = method
454 try: 1//0
455 except ZeroDivisionError:
456
457
458 frame = sys.exc_info()[2].tb_frame.f_back
459 variable = self.variable
460 while frame:
461 if variable in frame.f_locals:
462 v = frame.f_locals[variable]
463 if v:
464 method = getattr(v, self.method)
465 return method(*args, **kw)
466 frame = frame.f_back
467 return None
468
469 ConstructionEnvironment = {
470 'BUILDERS' : {},
471 'SCANNERS' : [],
472 'CONFIGUREDIR' : '#/.sconf_temp',
473 'CONFIGURELOG' : '#/config.log',
474 'CPPSUFFIXES' : SCons.Tool.CSuffixes,
475 'DSUFFIXES' : SCons.Tool.DSuffixes,
476 'ENV' : {},
477 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
478
479 '_concat' : _concat,
480 '_defines' : _defines,
481 '_stripixes' : _stripixes,
482 '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
483 '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
484 '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
485 '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
486 'TEMPFILE' : NullCmdGenerator,
487 'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
488 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
489 'File' : Variable_Method_Caller('TARGET', 'File'),
490 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
491 }
492
493
494
495
496
497
498