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