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