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 rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog"
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
172 permission_dic = {
173 'u':{
174 'r':stat.S_IRUSR,
175 'w':stat.S_IWUSR,
176 'x':stat.S_IXUSR
177 },
178 'g':{
179 'r':stat.S_IRGRP,
180 'w':stat.S_IWGRP,
181 'x':stat.S_IXGRP
182 },
183 'o':{
184 'r':stat.S_IROTH,
185 'w':stat.S_IWOTH,
186 'x':stat.S_IXOTH
187 }
188 }
189
191 import SCons.Util
192 from string import digits
193 SCons.Node.FS.invalidate_node_memos(dest)
194 if not SCons.Util.is_List(dest):
195 dest = [dest]
196 if SCons.Util.is_String(mode) and not 0 in [i in digits for i in mode]:
197 mode = int(mode, 8)
198 if not SCons.Util.is_String(mode):
199 for element in dest:
200 os.chmod(str(element), mode)
201 else:
202 mode = str(mode)
203 for operation in mode.split(","):
204 if "=" in operation:
205 operator = "="
206 elif "+" in operation:
207 operator = "+"
208 elif "-" in operation:
209 operator = "-"
210 else:
211 raise SyntaxError("Could not find +, - or =")
212 operation_list = operation.split(operator)
213 if len(operation_list) is not 2:
214 raise SyntaxError("More than one operator found")
215 user = operation_list[0].strip().replace("a", "ugo")
216 permission = operation_list[1].strip()
217 new_perm = 0
218 for u in user:
219 for p in permission:
220 try:
221 new_perm = new_perm | permission_dic[u][p]
222 except KeyError:
223 raise SyntaxError("Unrecognized user or permission format")
224 for element in dest:
225 curr_perm = os.stat(str(element)).st_mode
226 if operator == "=":
227 os.chmod(str(element), new_perm)
228 elif operator == "+":
229 os.chmod(str(element), curr_perm | new_perm)
230 elif operator == "-":
231 os.chmod(str(element), curr_perm & ~new_perm)
232
234 import SCons.Util
235 if not SCons.Util.is_String(mode):
236 return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode)
237 else:
238 return 'Chmod(%s, "%s")' % (get_paths_str(dest), str(mode))
239
240 Chmod = ActionFactory(chmod_func, chmod_strfunc)
241
243 """
244 If symlinks (is true), then a symbolic link will be
245 shallow copied and recreated as a symbolic link; otherwise, copying
246 a symbolic link will be equivalent to copying the symbolic link's
247 final target regardless of symbolic link depth.
248 """
249
250 dest = str(dest)
251 src = str(src)
252
253 SCons.Node.FS.invalidate_node_memos(dest)
254 if SCons.Util.is_List(src) and os.path.isdir(dest):
255 for file in src:
256 shutil.copy2(file, dest)
257 return 0
258 elif os.path.islink(src):
259 if symlinks:
260 return os.symlink(os.readlink(src), dest)
261 else:
262 return copy_func(dest, os.path.realpath(src))
263 elif os.path.isfile(src):
264 return shutil.copy2(src, dest)
265 else:
266 return shutil.copytree(src, dest, symlinks)
267
268 Copy = ActionFactory(
269 copy_func,
270 lambda dest, src, symlinks=True: 'Copy("%s", "%s")' % (dest, src)
271 )
272
288
290 return 'Delete(%s)' % get_paths_str(dest)
291
292 Delete = ActionFactory(delete_func, delete_strfunc)
293
295 SCons.Node.FS.invalidate_node_memos(dest)
296 if not SCons.Util.is_List(dest):
297 dest = [dest]
298 for entry in dest:
299 try:
300 os.makedirs(str(entry))
301 except os.error, e:
302 p = str(entry)
303 if (e.args[0] == errno.EEXIST or
304 (sys.platform=='win32' and e.args[0]==183)) \
305 and os.path.isdir(str(entry)):
306 pass
307 else:
308 raise
309
310 Mkdir = ActionFactory(mkdir_func,
311 lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
312
317
318 Move = ActionFactory(move_func,
319 lambda dest, src: 'Move("%s", "%s")' % (dest, src),
320 convert=str)
321
323 SCons.Node.FS.invalidate_node_memos(dest)
324 if not SCons.Util.is_List(dest):
325 dest = [dest]
326 for file in dest:
327 file = str(file)
328 mtime = int(time.time())
329 if os.path.exists(file):
330 atime = os.path.getatime(file)
331 else:
332 open(file, 'w')
333 atime = mtime
334 os.utime(file, (atime, mtime))
335
336 Touch = ActionFactory(touch_func,
337 lambda file: 'Touch(%s)' % get_paths_str(file))
338
339
340
341 -def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
342 """
343 Creates a new list from 'list' by first interpolating each element
344 in the list using the 'env' dictionary and then calling f on the
345 list, and finally calling _concat_ixes to concatenate 'prefix' and
346 'suffix' onto each element of the list.
347 """
348 if not list:
349 return list
350
351 l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
352 if l is not None:
353 list = l
354
355 return _concat_ixes(prefix, list, suffix, env)
356
358 """
359 Creates a new list from 'list' by concatenating the 'prefix' and
360 'suffix' arguments onto each element of the list. A trailing space
361 on 'prefix' or leading space on 'suffix' will cause them to be put
362 into separate list elements rather than being concatenated.
363 """
364
365 result = []
366
367
368 prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
369 suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
370
371 for x in list:
372 if isinstance(x, SCons.Node.FS.File):
373 result.append(x)
374 continue
375 x = str(x)
376 if x:
377
378 if prefix:
379 if prefix[-1] == ' ':
380 result.append(prefix[:-1])
381 elif x[:len(prefix)] != prefix:
382 x = prefix + x
383
384 result.append(x)
385
386 if suffix:
387 if suffix[0] == ' ':
388 result.append(suffix[1:])
389 elif x[-len(suffix):] != suffix:
390 result[-1] = result[-1]+suffix
391
392 return result
393
394 -def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None):
395 """
396 This is a wrapper around _concat()/_concat_ixes() that checks for
397 the existence of prefixes or suffixes on list items and strips them
398 where it finds them. This is used by tools (like the GNU linker)
399 that need to turn something like 'libfoo.a' into '-lfoo'.
400 """
401
402 if not itms:
403 return itms
404
405 if not callable(c):
406 env_c = env['_concat']
407 if env_c != _concat and callable(env_c):
408
409
410
411
412 c = env_c
413 else:
414 c = _concat_ixes
415
416 stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes)))
417 stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes)))
418
419 stripped = []
420 for l in SCons.PathList.PathList(itms).subst_path(env, None, None):
421 if isinstance(l, SCons.Node.FS.File):
422 stripped.append(l)
423 continue
424
425 if not SCons.Util.is_String(l):
426 l = str(l)
427
428 for stripprefix in stripprefixes:
429 lsp = len(stripprefix)
430 if l[:lsp] == stripprefix:
431 l = l[lsp:]
432
433 break
434
435 for stripsuffix in stripsuffixes:
436 lss = len(stripsuffix)
437 if l[-lss:] == stripsuffix:
438 l = l[:-lss]
439
440 break
441
442 stripped.append(l)
443
444 return c(prefix, stripped, suffix, env)
445
447 """process defines, resolving strings, lists, dictionaries, into a list of
448 strings
449 """
450 if SCons.Util.is_List(defs):
451 l = []
452 for d in defs:
453 if d is None:
454 continue
455 elif SCons.Util.is_List(d) or isinstance(d, tuple):
456 if len(d) >= 2:
457 l.append(str(d[0]) + '=' + str(d[1]))
458 else:
459 l.append(str(d[0]))
460 elif SCons.Util.is_Dict(d):
461 for macro,value in d.iteritems():
462 if value is not None:
463 l.append(str(macro) + '=' + str(value))
464 else:
465 l.append(str(macro))
466 elif SCons.Util.is_String(d):
467 l.append(str(d))
468 else:
469 raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None."%repr(d))
470 elif SCons.Util.is_Dict(defs):
471
472
473
474
475
476
477 l = []
478 for k,v in sorted(defs.items()):
479 if v is None:
480 l.append(str(k))
481 else:
482 l.append(str(k) + '=' + str(v))
483 else:
484 l = [str(defs)]
485 return l
486
487 -def _defines(prefix, defs, suffix, env, c=_concat_ixes):
488 """A wrapper around _concat_ixes that turns a list or string
489 into a list of C preprocessor command-line definitions.
490 """
491
492 return c(prefix, env.subst_path(processDefines(defs)), suffix, env)
493
495 """This is a callable class that can be used in place of other
496 command generators if you don't want them to do anything.
497
498 The __call__ method for this class simply returns the thing
499 you instantiated it with.
500
501 Example usage:
502 env["DO_NOTHING"] = NullCmdGenerator
503 env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
504 """
505
508
509 - def __call__(self, target, source, env, for_signature=None):
511
513 """A class for finding a construction variable on the stack and
514 calling one of its methods.
515
516 We use this to support "construction variables" in our string
517 eval()s that actually stand in for methods--specifically, use
518 of "RDirs" in call to _concat that should actually execute the
519 "TARGET.RDirs" method. (We used to support this by creating a little
520 "build dictionary" that mapped RDirs to the method, but this got in
521 the way of Memoizing construction environments, because we had to
522 create new environment objects to hold the variables.)
523 """
525 self.variable = variable
526 self.method = method
528 try: 1//0
529 except ZeroDivisionError:
530
531
532 frame = sys.exc_info()[2].tb_frame.f_back
533 variable = self.variable
534 while frame:
535 if variable in frame.f_locals:
536 v = frame.f_locals[variable]
537 if v:
538 method = getattr(v, self.method)
539 return method(*args, **kw)
540 frame = frame.f_back
541 return None
542
543
545 try:
546 if env[version_var]:
547 return env[flags_var]
548 except KeyError:
549 pass
550 return None
551
552 ConstructionEnvironment = {
553 'BUILDERS' : {},
554 'SCANNERS' : [ SCons.Tool.SourceFileScanner ],
555 'CONFIGUREDIR' : '#/.sconf_temp',
556 'CONFIGURELOG' : '#/config.log',
557 'CPPSUFFIXES' : SCons.Tool.CSuffixes,
558 'DSUFFIXES' : SCons.Tool.DSuffixes,
559 'ENV' : {},
560 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
561
562 '_concat' : _concat,
563 '_defines' : _defines,
564 '_stripixes' : _stripixes,
565 '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
566 '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
567 '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
568 '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
569
570 '__libversionflags' : __libversionflags,
571 '__SHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}',
572 '__LDMODULEVERSIONFLAGS' : '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}',
573 '__DSHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}',
574
575 'TEMPFILE' : NullCmdGenerator,
576 'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
577 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
578 'File' : Variable_Method_Caller('TARGET', 'File'),
579 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
580 }
581
582
583
584
585
586
587