c9a6108e0232186660d3d865a80492a9776f3ba8
[scons.git] / src / engine / SCons / Script / SConscript.py
1 """SCons.Script.SConscript
2
3 This module defines the Python API provided to SConscript and SConstruct
4 files.
5
6 """
7
8 #
9 # __COPYRIGHT__
10 #
11 # Permission is hereby granted, free of charge, to any person obtaining
12 # a copy of this software and associated documentation files (the
13 # "Software"), to deal in the Software without restriction, including
14 # without limitation the rights to use, copy, modify, merge, publish,
15 # distribute, sublicense, and/or sell copies of the Software, and to
16 # permit persons to whom the Software is furnished to do so, subject to
17 # the following conditions:
18 #
19 # The above copyright notice and this permission notice shall be included
20 # in all copies or substantial portions of the Software.
21 #
22 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
23 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #
30
31 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
32
33 import SCons
34 import SCons.Action
35 import SCons.Builder
36 import SCons.Defaults
37 import SCons.Environment
38 import SCons.Errors
39 import SCons.Node
40 import SCons.Node.Alias
41 import SCons.Node.FS
42 import SCons.Options
43 import SCons.Platform
44 import SCons.SConf
45 import SCons.Script
46 import SCons.Tool
47 import SCons.Util
48
49 import os
50 import os.path
51 import re
52 import string
53 import sys
54 import traceback
55 import types
56 import UserList
57
58 launch_dir = os.path.abspath(os.curdir)
59
60 help_text = None
61
62 def HelpFunction(text):
63     global help_text
64     if help_text is None:
65         help_text = text
66     else:
67         help_text = help_text + text
68
69 Arguments = {}
70 ArgList = []
71 CommandLineTargets = []
72 DefaultCalled = None
73 DefaultTargets = []
74 GlobalDict = {}
75
76 class TargetList(UserList.UserList):
77     def _do_nothing(self, *args, **kw):
78         pass
79     def _add_Default(self, list):
80         self.extend(list)
81     def _clear(self):
82         del self[:]
83 BuildTargets = TargetList()
84
85 # global exports set by Export():
86 global_exports = {}
87
88 # chdir flag
89 sconscript_chdir = 1
90
91 # will be set to 1, if we are reading a SConscript
92 sconscript_reading = 0
93
94 def _scons_add_args(alist):
95     for arg in alist:
96         a, b = string.split(arg, '=', 1)
97         Arguments[a] = b
98         ArgList.append((a, b))
99
100 def _scons_add_targets(tlist):
101     if tlist:
102         CommandLineTargets.extend(tlist)
103         BuildTargets.extend(tlist)
104         BuildTargets._add_Default = BuildTargets._do_nothing
105         BuildTargets._clear = BuildTargets._do_nothing
106
107 def get_calling_namespaces():
108     """Return the locals and globals for the function that called
109     into this module in the current callstack."""
110     try: 1/0
111     except ZeroDivisionError: frame = sys.exc_info()[2].tb_frame
112
113     while frame.f_globals.get("__name__") == __name__: frame = frame.f_back
114
115     return frame.f_locals, frame.f_globals
116
117
118 def compute_exports(exports):
119     """Compute a dictionary of exports given one of the parameters
120     to the Export() function or the exports argument to SConscript()."""
121
122     loc, glob = get_calling_namespaces()
123
124     retval = {}
125     try:
126         for export in exports:
127             if SCons.Util.is_Dict(export):
128                 retval.update(export)
129             else:
130                 try:
131                     retval[export] = loc[export]
132                 except KeyError:
133                     retval[export] = glob[export]
134     except KeyError, x:
135         raise SCons.Errors.UserError, "Export of non-existent variable '%s'"%x
136
137     return retval
138
139
140 class Frame:
141     """A frame on the SConstruct/SConscript call stack"""
142     def __init__(self, exports, sconscript):
143         self.globals = BuildDefaultGlobals()
144         self.retval = None
145         self.prev_dir = SCons.Node.FS.default_fs.getcwd()
146         self.exports = compute_exports(exports)  # exports from the calling SConscript
147         # make sure the sconscript attr is a Node.
148         if isinstance(sconscript, SCons.Node.Node):
149             self.sconscript = sconscript
150         else:
151             self.sconscript = SCons.Node.FS.default_fs.File(str(sconscript))
152
153 # the SConstruct/SConscript call stack:
154 stack = []
155
156 # For documentation on the methods in this file, see the scons man-page
157
158 def Return(*vars):
159     retval = []
160     try:
161         for var in vars:
162             for v in string.split(var):
163                 retval.append(stack[-1].globals[v])
164     except KeyError, x:
165         raise SCons.Errors.UserError, "Return of non-existent variable '%s'"%x
166
167     if len(retval) == 1:
168         stack[-1].retval = retval[0]
169     else:
170         stack[-1].retval = tuple(retval)
171
172 def _SConscript(fs, *files, **kw):
173     top = fs.Top
174     sd = fs.SConstruct_dir.rdir()
175     exports = kw.get('exports', [])
176
177     # evaluate each SConscript file
178     results = []
179     for fn in files:
180         stack.append(Frame(exports,fn))
181         old_sys_path = sys.path
182         try:
183             global sconscript_reading
184             sconscript_reading = 1
185             if fn == "-":
186                 exec sys.stdin in stack[-1].globals
187             else:
188                 if isinstance(fn, SCons.Node.Node):
189                     f = fn
190                 else:
191                     f = fs.File(str(fn))
192                 _file_ = None
193
194                 # Change directory to the top of the source
195                 # tree to make sure the os's cwd and the cwd of
196                 # fs match so we can open the SConscript.
197                 fs.chdir(top, change_os_dir=1)
198                 if f.rexists():
199                     _file_ = open(f.rstr(), "r")
200                 elif f.has_src_builder():
201                     # The SConscript file apparently exists in a source
202                     # code management system.  Build it, but then clear
203                     # the builder so that it doesn't get built *again*
204                     # during the actual build phase.
205                     f.build()
206                     f.builder_set(None)
207                     s = str(f)
208                     if os.path.exists(s):
209                         _file_ = open(s, "r")
210                 if _file_:
211                     # Chdir to the SConscript directory.  Use a path
212                     # name relative to the SConstruct file so that if
213                     # we're using the -f option, we're essentially
214                     # creating a parallel SConscript directory structure
215                     # in our local directory tree.
216                     #
217                     # XXX This is broken for multiple-repository cases
218                     # where the SConstruct and SConscript files might be
219                     # in different Repositories.  For now, cross that
220                     # bridge when someone comes to it.
221                     ldir = fs.Dir(f.dir.get_path(sd))
222                     try:
223                         fs.chdir(ldir, change_os_dir=sconscript_chdir)
224                     except OSError:
225                         # There was no local directory, so we should be
226                         # able to chdir to the Repository directory.
227                         # Note that we do this directly, not through
228                         # fs.chdir(), because we still need to
229                         # interpret the stuff within the SConscript file
230                         # relative to where we are logically.
231                         fs.chdir(ldir, change_os_dir=0)
232                         os.chdir(f.rfile().dir.get_abspath())
233
234                     # Append the SConscript directory to the beginning
235                     # of sys.path so Python modules in the SConscript
236                     # directory can be easily imported.
237                     sys.path = [ f.dir.get_abspath() ] + sys.path
238
239                     # This is the magic line that actually reads up and
240                     # executes the stuff in the SConscript file.  We
241                     # look for the "exec _file_ " from the beginning
242                     # of this line to find the right stack frame (the
243                     # next one) describing the SConscript file and line
244                     # number that creates a node.
245                     exec _file_ in stack[-1].globals
246                 else:
247                     SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning,
248                              "Ignoring missing SConscript '%s'" % f.path)
249
250         finally:
251             sconscript_reading = 0
252             sys.path = old_sys_path
253             frame = stack.pop()
254             try:
255                 fs.chdir(frame.prev_dir, change_os_dir=sconscript_chdir)
256             except OSError:
257                 # There was no local directory, so chdir to the
258                 # Repository directory.  Like above, we do this
259                 # directly.
260                 fs.chdir(frame.prev_dir, change_os_dir=0)
261                 os.chdir(frame.prev_dir.rdir().get_abspath())
262
263             results.append(frame.retval)
264
265     # if we only have one script, don't return a tuple
266     if len(results) == 1:
267         return results[0]
268     else:
269         return tuple(results)
270
271 def is_our_exec_statement(line):
272     return not line is None and line[:12] == "exec _file_ "
273
274 def SConscript_exception(file=sys.stderr):
275     """Print an exception stack trace just for the SConscript file(s).
276     This will show users who have Python errors where the problem is,
277     without cluttering the output with all of the internal calls leading
278     up to where we exec the SConscript."""
279     exc_type, exc_value, exc_tb = sys.exc_info()
280     stack = traceback.extract_tb(exc_tb)
281     last_text = ""
282     found = 0
283     i = 0
284     for frame in stack:
285         if is_our_exec_statement(last_text):
286             found = 1
287             break
288         i = i + 1
289         last_text = frame[3]
290     if not found:
291         # We did not find our exec statement, so this was actually a bug
292         # in SCons itself.  Show the whole stack.
293         i = 0
294     type = str(exc_type)
295     if type[:11] == "exceptions.":
296         type = type[11:]
297     file.write('%s: %s:\n' % (type, exc_value))
298     for fname, line, func, text in stack[i:]:
299         file.write('  File "%s", line %d:\n' % (fname, line))
300         file.write('    %s\n' % text)
301
302 def annotate(node):
303     """Annotate a node with the stack frame describing the
304     SConscript file and line number that created it."""
305     stack = traceback.extract_stack()
306     last_text = ""
307     for frame in stack:
308         # If the script text of the previous frame begins with the
309         # magic "exec _file_ " string, then this frame describes the
310         # SConscript file and line number that caused this node to be
311         # created.  Record the tuple and carry on.
312         if is_our_exec_statement(last_text):
313             node.creator = frame
314             return
315         last_text = frame[3]
316
317 # The following line would cause each Node to be annotated using the
318 # above function.  Unfortunately, this is a *huge* performance hit, so
319 # leave this disabled until we find a more efficient mechanism.
320 #SCons.Node.Annotate = annotate
321
322 class SConsEnvironment(SCons.Environment.Base):
323     """An Environment subclass that contains all of the methods that
324     are particular to the wrapper SCons interface and which aren't
325     (or shouldn't be) part of the build engine itself.
326
327     Note that not all of the methods of this class have corresponding
328     global functions, there are some private methods.
329     """
330
331     #
332     # Private methods of an SConsEnvironment.
333     #
334     def _exceeds_version(self, major, minor, v_major, v_minor):
335         """Return 1 if 'major' and 'minor' are greater than the version
336         in 'v_major' and 'v_minor', and 0 otherwise."""
337         return (major > v_major or (major == v_major and minor > v_minor))
338
339     def _get_major_minor(self, version_string):
340         """Split a version string into major and minor parts.  This
341         is complicated by the fact that a version string can be something
342         like 3.2b1."""
343         version = string.split(string.split(version_string, ' ')[0], '.')
344         v_major = int(version[0])
345         v_minor = int(re.match('\d+', version[1]).group())
346         return v_major, v_minor
347
348     def _get_SConscript_filenames(self, ls, kw):
349         """
350         Convert the parameters passed to # SConscript() calls into a list
351         of files and export variables.  If the parameters are invalid,
352         throws SCons.Errors.UserError. Returns a tuple (l, e) where l
353         is a list of SConscript filenames and e is a list of exports.
354         """
355         exports = []
356
357         if len(ls) == 0:
358             try:
359                 dirs = kw["dirs"]
360             except KeyError:
361                 raise SCons.Errors.UserError, \
362                       "Invalid SConscript usage - no parameters"
363
364             if not SCons.Util.is_List(dirs):
365                 dirs = [ dirs ]
366             dirs = map(str, dirs)
367
368             name = kw.get('name', 'SConscript')
369
370             files = map(lambda n, name = name: os.path.join(n, name), dirs)
371
372         elif len(ls) == 1:
373
374             files = ls[0]
375
376         elif len(ls) == 2:
377
378             files   = ls[0]
379             exports = self.Split(ls[1])
380
381         else:
382
383             raise SCons.Errors.UserError, \
384                   "Invalid SConscript() usage - too many arguments"
385
386         if not SCons.Util.is_List(files):
387             files = [ files ]
388
389         if kw.get('exports'):
390             exports.extend(self.Split(kw['exports']))
391
392         build_dir = kw.get('build_dir')
393         if build_dir:
394             if len(files) != 1:
395                 raise SCons.Errors.UserError, \
396                     "Invalid SConscript() usage - can only specify one SConscript with a build_dir"
397             duplicate = kw.get('duplicate', 1)
398             src_dir = kw.get('src_dir')
399             if not src_dir:
400                 src_dir, fname = os.path.split(str(files[0]))
401             else:
402                 if not isinstance(src_dir, SCons.Node.Node):
403                     src_dir = self.fs.Dir(src_dir)
404                 fn = files[0]
405                 if not isinstance(fn, SCons.Node.Node):
406                     fn = self.fs.File(fn)
407                 if fn.is_under(src_dir):
408                     # Get path relative to the source directory.
409                     fname = fn.get_path(src_dir)
410                 else:
411                     # Fast way to only get the terminal path component of a Node.
412                     fname = fn.get_path(fn.dir)
413             self.fs.BuildDir(build_dir, src_dir, duplicate)
414             files = [os.path.join(str(build_dir), fname)]
415
416         return (files, exports)
417
418     #
419     # Public methods of an SConsEnvironment.  These get
420     # entry points in the global name space so they can be called
421     # as global functions.
422     #
423
424     def Default(self, *targets):
425         global DefaultCalled
426         global DefaultTargets
427         DefaultCalled = 1
428         for t in targets:
429             if t is None:
430                 # Delete the elements from the list in-place, don't
431                 # reassign an empty list to DefaultTargets, so that the
432                 # DEFAULT_TARGETS variable will still point to the
433                 # same object we point to.
434                 del DefaultTargets[:]
435                 BuildTargets._clear()
436             elif isinstance(t, SCons.Node.Node):
437                 DefaultTargets.append(t)
438                 BuildTargets._add_Default([t])
439             else:
440                 nodes = self.arg2nodes(t, self.fs.Entry)
441                 DefaultTargets.extend(nodes)
442                 BuildTargets._add_Default(nodes)
443
444     def EnsureSConsVersion(self, major, minor):
445         """Exit abnormally if the SCons version is not late enough."""
446         v_major, v_minor = self._get_major_minor(SCons.__version__)
447         if self._exceeds_version(major, minor, v_major, v_minor):
448             print "SCons %d.%d or greater required, but you have SCons %s" %(major,minor,SCons.__version__)
449             sys.exit(2)
450
451     def EnsurePythonVersion(self, major, minor):
452         """Exit abnormally if the Python version is not late enough."""
453         try:
454             v_major, v_minor, v_micro, release, serial = sys.version_info
455         except AttributeError:
456             v_major, v_minor = self._get_major_minor(sys.version)
457         if self._exceeds_version(major, minor, v_major, v_minor):
458             v = string.split(sys.version, " ", 1)[0]
459             print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v)
460             sys.exit(2)
461
462     def Exit(self, value=0):
463         sys.exit(value)
464
465     def Export(self, *vars):
466         for var in vars:
467             global_exports.update(compute_exports(self.Split(var)))
468
469     def GetLaunchDir(self):
470         global launch_dir
471         return launch_dir
472
473     def GetOption(self, name):
474         name = self.subst(name)
475         return SCons.Script.ssoptions.get(name)
476
477     def Help(self, text):
478         text = self.subst(text, raw=1)
479         HelpFunction(text)
480
481     def Import(self, *vars):
482         try:
483             for var in vars:
484                 var = self.Split(var)
485                 for v in var:
486                     if v == '*':
487                         stack[-1].globals.update(global_exports)
488                         stack[-1].globals.update(stack[-1].exports)
489                     else:
490                         if stack[-1].exports.has_key(v):
491                             stack[-1].globals[v] = stack[-1].exports[v]
492                         else:
493                             stack[-1].globals[v] = global_exports[v]
494         except KeyError,x:
495             raise SCons.Errors.UserError, "Import of non-existent variable '%s'"%x
496
497     def SConscript(self, *ls, **kw):
498         ls = map(lambda l, self=self: self.subst(l), ls)
499         subst_kw = {}
500         for key, val in kw.items():
501             if SCons.Util.is_String(val):
502                 val = self.subst(val)
503             elif SCons.Util.is_List(val):
504                 result = []
505                 for v in val:
506                     if SCons.Util.is_String(v):
507                         v = self.subst(v)
508                     result.append(v)
509                 val = result
510             subst_kw[key] = val
511
512         files, exports = self._get_SConscript_filenames(ls, subst_kw)
513
514         return apply(_SConscript, [self.fs,] + files, {'exports' : exports})
515
516     def SConscriptChdir(self, flag):
517         global sconscript_chdir
518         sconscript_chdir = flag
519
520     def SetOption(self, name, value):
521         name = self.subst(name)
522         SCons.Script.ssoptions.set(name, value)
523
524 #
525 #
526 #
527 SCons.Environment.Environment = SConsEnvironment
528
529 def Options(files=None, args=Arguments):
530     return SCons.Options.Options(files, args)
531
532 def SetBuildSignatureType(type):
533     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
534                         "The SetBuildSignatureType() function has been deprecated;\n" +\
535                         "\tuse the TargetSignatures() function instead.")
536     SCons.Defaults.DefaultEnvironment().TargetSignatures(type)
537
538 def SetContentSignatureType(type):
539     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
540                         "The SetContentSignatureType() function has been deprecated;\n" +\
541                         "\tuse the SourceSignatures() function instead.")
542     SCons.Defaults.DefaultEnvironment().SourceSignatures(type)
543
544 def GetJobs():
545     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
546                         "The GetJobs() function has been deprecated;\n" +\
547                         "\tuse GetOption('num_jobs') instead.")
548
549     return GetOption('num_jobs')
550
551 def SetJobs(num):
552     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
553                         "The SetJobs() function has been deprecated;\n" +\
554                         "\tuse SetOption('num_jobs', num) instead.")
555     SetOption('num_jobs', num)
556
557 def ParseConfig(env, command, function=None):
558     SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
559                         "The ParseConfig() function has been deprecated;\n" +\
560                         "\tuse the env.ParseConfig() method instead.")
561     return env.ParseConfig(command, function)
562
563 #
564 _DefaultEnvironmentProxy = None
565
566 def get_DefaultEnvironmentProxy():
567     global _DefaultEnvironmentProxy
568     if not _DefaultEnvironmentProxy:
569         default_env = SCons.Defaults.DefaultEnvironment()
570         _DefaultEnvironmentProxy = SCons.Environment.NoSubstitutionProxy(default_env)
571     return _DefaultEnvironmentProxy
572
573 class DefaultEnvironmentCall:
574     """A class that implements "global function" calls of
575     Environment methods by fetching the specified method from the
576     DefaultEnvironment's class.  Note that this uses an intermediate
577     proxy class instead of calling the DefaultEnvironment method
578     directly so that the proxy can override the subst() method and
579     thereby prevent expansion of construction variables (since from
580     the user's point of view this was called as a global function,
581     with no associated construction environment)."""
582     def __init__(self, method_name):
583         self.method_name = method_name
584     def __call__(self, *args, **kw):
585         proxy = get_DefaultEnvironmentProxy()
586         method = getattr(proxy, self.method_name)
587         return apply(method, args, kw)
588
589 # The list of global functions to add to the SConscript name space
590 # that end up calling corresponding methods or Builders in the
591 # DefaultEnvironment().
592 GlobalDefaultEnvironmentFunctions = [
593     # Methods from the SConsEnvironment class, above.
594     'Default',
595     'EnsurePythonVersion',
596     'EnsureSConsVersion',
597     'Exit',
598     'Export',
599     'GetLaunchDir',
600     'GetOption',
601     'Help',
602     'Import',
603     'SConscript',
604     'SConscriptChdir',
605     'SetOption',
606
607     # Methods from the Environment.Base class.
608     'AddPostAction',
609     'AddPreAction',
610     'Alias',
611     'AlwaysBuild',
612     'BuildDir',
613     'CacheDir',
614     'Clean',
615     'Command',
616     'Depends',
617     'Dir',
618     'Execute',
619     'File',
620     'FindFile',
621     'Flatten',
622     'GetBuildPath',
623     'Ignore',
624     'Install',
625     'InstallAs',
626     'Literal',
627     'Local',
628     'Precious',
629     'Repository',
630     'SConsignFile',
631     'SideEffect',
632     'SourceCode',
633     'SourceSignatures',
634     'Split',
635     'TargetSignatures',
636     'Value',
637 ]
638
639 GlobalDefaultBuilders = [
640     # Supported builders.
641     'CFile',
642     'CXXFile',
643     'DVI',
644     'Jar',
645     'Java',
646     'JavaH',
647     'Library',
648     'M4',
649     'MSVSProject',
650     'Object',
651     'PCH',
652     'PDF',
653     'PostScript',
654     'Program',
655     'RES',
656     'RMIC',
657     'SharedLibrary',
658     'SharedObject',
659     'StaticLibrary',
660     'StaticObject',
661     'Tar',
662     'TypeLibrary',
663     'Zip',
664 ]
665
666 for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:
667     GlobalDict[name] = DefaultEnvironmentCall(name)
668
669 def BuildDefaultGlobals():
670     """
671     Create a dictionary containing all the default globals for
672     SConstruct and SConscript files.
673     """
674
675     globals = {
676         # Global functions that don't get executed through the
677         # default Environment.
678         'Action'                : SCons.Action.Action,
679         'BoolOption'            : SCons.Options.BoolOption,
680         'Builder'               : SCons.Builder.Builder,
681         'Configure'             : SCons.SConf.SConf,
682         'EnumOption'            : SCons.Options.EnumOption,
683         'Environment'           : SCons.Environment.Environment,
684         'ListOption'            : SCons.Options.ListOption,
685         'Options'               : Options,
686         'PackageOption'         : SCons.Options.PackageOption,
687         'PathOption'            : SCons.Options.PathOption,
688         'Platform'              : SCons.Platform.Platform,
689         'Return'                : Return,
690         'Scanner'               : SCons.Scanner.Base,
691         'Tool'                  : SCons.Tool.Tool,
692         'WhereIs'               : SCons.Util.WhereIs,
693
694         # Action factories.
695         'Chmod'                 : SCons.Defaults.Chmod,
696         'Copy'                  : SCons.Defaults.Copy,
697         'Delete'                : SCons.Defaults.Delete,
698         'Mkdir'                 : SCons.Defaults.Mkdir,
699         'Move'                  : SCons.Defaults.Move,
700         'Touch'                 : SCons.Defaults.Touch,
701
702         # Other variables we provide.
703         'ARGUMENTS'             : Arguments,
704         'ARGLIST'               : ArgList,
705         'BUILD_TARGETS'         : BuildTargets,
706         'COMMAND_LINE_TARGETS'  : CommandLineTargets,
707         'DEFAULT_TARGETS'       : DefaultTargets,
708     }
709
710     # Functions we might still convert to Environment methods.
711     globals['CScan']             = SCons.Defaults.CScan
712     globals['DefaultEnvironment'] = SCons.Defaults.DefaultEnvironment
713
714     # Deprecated functions, leave these here for now.
715     globals['GetJobs']           = GetJobs
716     globals['ParseConfig']       = ParseConfig
717     globals['SetBuildSignatureType'] = SetBuildSignatureType
718     globals['SetContentSignatureType'] = SetContentSignatureType
719     globals['SetJobs']           = SetJobs
720
721     globals.update(GlobalDict)
722
723     return globals