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 3a41ed6b288cee8d085373ad7fa02894e1903864 2019-01-23 17:30:35 bdeegan"
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 shutil.copy2(src, dest)
265 return 0
266 else:
267 shutil.copytree(src, dest, symlinks)
268
269
270 return 0
271
272 Copy = ActionFactory(
273 copy_func,
274 lambda dest, src, symlinks=True: 'Copy("%s", "%s")' % (dest, src)
275 )
276
292
294 return 'Delete(%s)' % get_paths_str(dest)
295
296 Delete = ActionFactory(delete_func, delete_strfunc)
297
299 SCons.Node.FS.invalidate_node_memos(dest)
300 if not SCons.Util.is_List(dest):
301 dest = [dest]
302 for entry in dest:
303 try:
304 os.makedirs(str(entry))
305 except os.error as e:
306 p = str(entry)
307 if (e.args[0] == errno.EEXIST or
308 (sys.platform=='win32' and e.args[0]==183)) \
309 and os.path.isdir(str(entry)):
310 pass
311 else:
312 raise
313
314 Mkdir = ActionFactory(mkdir_func,
315 lambda dir: 'Mkdir(%s)' % get_paths_str(dir))
316
321
322 Move = ActionFactory(move_func,
323 lambda dest, src: 'Move("%s", "%s")' % (dest, src),
324 convert=str)
325
339
340 Touch = ActionFactory(touch_func,
341 lambda file: 'Touch(%s)' % get_paths_str(file))
342
343
344
345
346 -def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None):
347 """
348 Creates a new list from 'list' by first interpolating each element
349 in the list using the 'env' dictionary and then calling f on the
350 list, and finally calling _concat_ixes to concatenate 'prefix' and
351 'suffix' onto each element of the list.
352 """
353 if not list:
354 return list
355
356 l = f(SCons.PathList.PathList(list).subst_path(env, target, source))
357 if l is not None:
358 list = l
359
360 return _concat_ixes(prefix, list, suffix, env)
361
362
364 """
365 Creates a new list from 'list' by concatenating the 'prefix' and
366 'suffix' arguments onto each element of the list. A trailing space
367 on 'prefix' or leading space on 'suffix' will cause them to be put
368 into separate list elements rather than being concatenated.
369 """
370
371 result = []
372
373
374 prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW))
375 suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW))
376
377 for x in list:
378 if isinstance(x, SCons.Node.FS.File):
379 result.append(x)
380 continue
381 x = str(x)
382 if x:
383
384 if prefix:
385 if prefix[-1] == ' ':
386 result.append(prefix[:-1])
387 elif x[:len(prefix)] != prefix:
388 x = prefix + x
389
390 result.append(x)
391
392 if suffix:
393 if suffix[0] == ' ':
394 result.append(suffix[1:])
395 elif x[-len(suffix):] != suffix:
396 result[-1] = result[-1]+suffix
397
398 return result
399
400
401 -def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None):
402 """
403 This is a wrapper around _concat()/_concat_ixes() that checks for
404 the existence of prefixes or suffixes on list items and strips them
405 where it finds them. This is used by tools (like the GNU linker)
406 that need to turn something like 'libfoo.a' into '-lfoo'.
407 """
408
409 if not itms:
410 return itms
411
412 if not callable(c):
413 env_c = env['_concat']
414 if env_c != _concat and callable(env_c):
415
416
417
418
419 c = env_c
420 else:
421 c = _concat_ixes
422
423 stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes)))
424 stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes)))
425
426 stripped = []
427 for l in SCons.PathList.PathList(itms).subst_path(env, None, None):
428 if isinstance(l, SCons.Node.FS.File):
429 stripped.append(l)
430 continue
431
432 if not SCons.Util.is_String(l):
433 l = str(l)
434
435 for stripprefix in stripprefixes:
436 lsp = len(stripprefix)
437 if l[:lsp] == stripprefix:
438 l = l[lsp:]
439
440 break
441
442 for stripsuffix in stripsuffixes:
443 lss = len(stripsuffix)
444 if l[-lss:] == stripsuffix:
445 l = l[:-lss]
446
447 break
448
449 stripped.append(l)
450
451 return c(prefix, stripped, suffix, env)
452
454 """process defines, resolving strings, lists, dictionaries, into a list of
455 strings
456 """
457 if SCons.Util.is_List(defs):
458 l = []
459 for d in defs:
460 if d is None:
461 continue
462 elif SCons.Util.is_List(d) or isinstance(d, tuple):
463 if len(d) >= 2:
464 l.append(str(d[0]) + '=' + str(d[1]))
465 else:
466 l.append(str(d[0]))
467 elif SCons.Util.is_Dict(d):
468 for macro,value in d.items():
469 if value is not None:
470 l.append(str(macro) + '=' + str(value))
471 else:
472 l.append(str(macro))
473 elif SCons.Util.is_String(d):
474 l.append(str(d))
475 else:
476 raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None."%repr(d))
477 elif SCons.Util.is_Dict(defs):
478
479
480
481
482
483
484 l = []
485 for k,v in sorted(defs.items()):
486 if v is None:
487 l.append(str(k))
488 else:
489 l.append(str(k) + '=' + str(v))
490 else:
491 l = [str(defs)]
492 return l
493
494
495 -def _defines(prefix, defs, suffix, env, c=_concat_ixes):
496 """A wrapper around _concat_ixes that turns a list or string
497 into a list of C preprocessor command-line definitions.
498 """
499
500 return c(prefix, env.subst_path(processDefines(defs)), suffix, env)
501
502
504 """This is a callable class that can be used in place of other
505 command generators if you don't want them to do anything.
506
507 The __call__ method for this class simply returns the thing
508 you instantiated it with.
509
510 Example usage:
511 env["DO_NOTHING"] = NullCmdGenerator
512 env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}"
513 """
514
517
518 - def __call__(self, target, source, env, for_signature=None):
520
521
523 """A class for finding a construction variable on the stack and
524 calling one of its methods.
525
526 We use this to support "construction variables" in our string
527 eval()s that actually stand in for methods--specifically, use
528 of "RDirs" in call to _concat that should actually execute the
529 "TARGET.RDirs" method. (We used to support this by creating a little
530 "build dictionary" that mapped RDirs to the method, but this got in
531 the way of Memoizing construction environments, because we had to
532 create new environment objects to hold the variables.)
533 """
535 self.variable = variable
536 self.method = method
538 try: 1//0
539 except ZeroDivisionError:
540
541
542 frame = sys.exc_info()[2].tb_frame.f_back
543 variable = self.variable
544 while frame:
545 if variable in frame.f_locals:
546 v = frame.f_locals[variable]
547 if v:
548 method = getattr(v, self.method)
549 return method(*args, **kw)
550 frame = frame.f_back
551 return None
552
553
555 try:
556 if env.subst('$'+version_var):
557 return env[flags_var]
558 except KeyError:
559 pass
560 return None
561
562 ConstructionEnvironment = {
563 'BUILDERS' : {},
564 'SCANNERS' : [ SCons.Tool.SourceFileScanner ],
565 'CONFIGUREDIR' : '#/.sconf_temp',
566 'CONFIGURELOG' : '#/config.log',
567 'CPPSUFFIXES' : SCons.Tool.CSuffixes,
568 'DSUFFIXES' : SCons.Tool.DSuffixes,
569 'ENV' : {},
570 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes,
571 '_concat' : _concat,
572 '_defines' : _defines,
573 '_stripixes' : _stripixes,
574 '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
575 '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
576 '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)',
577 '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
578
579 '__libversionflags' : __libversionflags,
580 '__SHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}',
581 '__LDMODULEVERSIONFLAGS' : '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}',
582 '__DSHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}',
583
584 'TEMPFILE' : NullCmdGenerator,
585 'Dir' : Variable_Method_Caller('TARGET', 'Dir'),
586 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'),
587 'File' : Variable_Method_Caller('TARGET', 'File'),
588 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'),
589 }
590
591
592
593
594
595
596