Toplevel directory cleanup
[senf.git] / tools / scons-1.2.0 / engine / SCons / Tool / __init__.py
1 """SCons.Tool
2
3 SCons tool selection.
4
5 This looks for modules that define a callable object that can modify
6 a construction environment as appropriate for a given tool (or tool
7 chain).
8
9 Note that because this subsystem just *selects* a callable that can
10 modify a construction environment, it's possible for people to define
11 their own "tool specification" in an arbitrary callable function.  No
12 one needs to use or tie in to this subsystem in order to roll their own
13 tool definition.
14 """
15
16 #
17 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
18 #
19 # Permission is hereby granted, free of charge, to any person obtaining
20 # a copy of this software and associated documentation files (the
21 # "Software"), to deal in the Software without restriction, including
22 # without limitation the rights to use, copy, modify, merge, publish,
23 # distribute, sublicense, and/or sell copies of the Software, and to
24 # permit persons to whom the Software is furnished to do so, subject to
25 # the following conditions:
26 #
27 # The above copyright notice and this permission notice shall be included
28 # in all copies or substantial portions of the Software.
29 #
30 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
31 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
32 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #
38
39 __revision__ = "src/engine/SCons/Tool/__init__.py 3842 2008/12/20 22:59:52 scons"
40
41 import imp
42 import sys
43
44 import SCons.Builder
45 import SCons.Errors
46 import SCons.Node.FS
47 import SCons.Scanner
48 import SCons.Scanner.C
49 import SCons.Scanner.D
50 import SCons.Scanner.LaTeX
51 import SCons.Scanner.Prog
52
53 DefaultToolpath=[]
54
55 CScanner = SCons.Scanner.C.CScanner()
56 DScanner = SCons.Scanner.D.DScanner()
57 LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
58 PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner()
59 ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
60 SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner')
61
62 CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
63              ".h", ".H", ".hxx", ".hpp", ".hh",
64              ".F", ".fpp", ".FPP",
65              ".m", ".mm",
66              ".S", ".spp", ".SPP"]
67
68 DSuffixes = ['.d']
69
70 IDLSuffixes = [".idl", ".IDL"]
71
72 LaTeXSuffixes = [".tex", ".ltx", ".latex"]
73
74 for suffix in CSuffixes:
75     SourceFileScanner.add_scanner(suffix, CScanner)
76
77 for suffix in DSuffixes:
78     SourceFileScanner.add_scanner(suffix, DScanner)
79
80 # FIXME: what should be done here? Two scanners scan the same extensions,
81 # but look for different files, e.g., "picture.eps" vs. "picture.pdf".
82 # The builders for DVI and PDF explicitly reference their scanners
83 # I think that means this is not needed???
84 for suffix in LaTeXSuffixes:
85     SourceFileScanner.add_scanner(suffix, LaTeXScanner)
86     SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner)
87
88 class Tool:
89     def __init__(self, name, toolpath=[], **kw):
90         self.name = name
91         self.toolpath = toolpath + DefaultToolpath
92         # remember these so we can merge them into the call
93         self.init_kw = kw
94
95         module = self._tool_module()
96         self.generate = module.generate
97         self.exists = module.exists
98         if hasattr(module, 'options'):
99             self.options = module.options
100
101     def _tool_module(self):
102         # TODO: Interchange zipimport with normal initilization for better error reporting
103         oldpythonpath = sys.path
104         sys.path = self.toolpath + sys.path
105
106         try:
107             try:
108                 file, path, desc = imp.find_module(self.name, self.toolpath)
109                 try:
110                     return imp.load_module(self.name, file, path, desc)
111                 finally:
112                     if file:
113                         file.close()
114             except ImportError, e:
115                 if str(e)!="No module named %s"%self.name:
116                     raise SCons.Errors.EnvironmentError, e
117                 try:
118                     import zipimport
119                 except ImportError:
120                     pass
121                 else:
122                     for aPath in self.toolpath:
123                         try:
124                             importer = zipimport.zipimporter(aPath)
125                             return importer.load_module(self.name)
126                         except ImportError, e:
127                             pass
128         finally:
129             sys.path = oldpythonpath
130
131         full_name = 'SCons.Tool.' + self.name
132         try:
133             return sys.modules[full_name]
134         except KeyError:
135             try:
136                 smpath = sys.modules['SCons.Tool'].__path__
137                 try:
138                     file, path, desc = imp.find_module(self.name, smpath)
139                     module = imp.load_module(full_name, file, path, desc)
140                     setattr(SCons.Tool, self.name, module)
141                     if file:
142                         file.close()
143                     return module
144                 except ImportError, e:
145                     if str(e)!="No module named %s"%self.name:
146                         raise SCons.Errors.EnvironmentError, e
147                     try:
148                         import zipimport
149                         importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] )
150                         module = importer.load_module(full_name)
151                         setattr(SCons.Tool, self.name, module)
152                         return module
153                     except ImportError, e:
154                         m = "No tool named '%s': %s" % (self.name, e)
155                         raise SCons.Errors.EnvironmentError, m
156             except ImportError, e:
157                 m = "No tool named '%s': %s" % (self.name, e)
158                 raise SCons.Errors.EnvironmentError, m
159
160     def __call__(self, env, *args, **kw):
161         if self.init_kw is not None:
162             # Merge call kws into init kws;
163             # but don't bash self.init_kw.
164             if kw is not None:
165                 call_kw = kw
166                 kw = self.init_kw.copy()
167                 kw.update(call_kw)
168             else:
169                 kw = self.init_kw
170         env.Append(TOOLS = [ self.name ])
171         if hasattr(self, 'options'):
172             import SCons.Variables
173             if not env.has_key('options'):
174                 from SCons.Script import ARGUMENTS
175                 env['options']=SCons.Variables.Variables(args=ARGUMENTS)
176             opts=env['options']
177
178             self.options(opts)
179             opts.Update(env)
180
181         apply(self.generate, ( env, ) + args, kw)
182
183     def __str__(self):
184         return self.name
185
186 ##########################################################################
187 #  Create common executable program / library / object builders
188
189 def createProgBuilder(env):
190     """This is a utility function that creates the Program
191     Builder in an Environment if it is not there already.
192
193     If it is already there, we return the existing one.
194     """
195
196     try:
197         program = env['BUILDERS']['Program']
198     except KeyError:
199         import SCons.Defaults
200         program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction,
201                                         emitter = '$PROGEMITTER',
202                                         prefix = '$PROGPREFIX',
203                                         suffix = '$PROGSUFFIX',
204                                         src_suffix = '$OBJSUFFIX',
205                                         src_builder = 'Object',
206                                         target_scanner = ProgramScanner)
207         env['BUILDERS']['Program'] = program
208
209     return program
210
211 def createStaticLibBuilder(env):
212     """This is a utility function that creates the StaticLibrary
213     Builder in an Environment if it is not there already.
214
215     If it is already there, we return the existing one.
216     """
217
218     try:
219         static_lib = env['BUILDERS']['StaticLibrary']
220     except KeyError:
221         action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
222         if env.Detect('ranlib'):
223             ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
224             action_list.append(ranlib_action)
225
226         static_lib = SCons.Builder.Builder(action = action_list,
227                                            emitter = '$LIBEMITTER',
228                                            prefix = '$LIBPREFIX',
229                                            suffix = '$LIBSUFFIX',
230                                            src_suffix = '$OBJSUFFIX',
231                                            src_builder = 'StaticObject')
232         env['BUILDERS']['StaticLibrary'] = static_lib
233         env['BUILDERS']['Library'] = static_lib
234
235     return static_lib
236
237 def createSharedLibBuilder(env):
238     """This is a utility function that creates the SharedLibrary
239     Builder in an Environment if it is not there already.
240
241     If it is already there, we return the existing one.
242     """
243
244     try:
245         shared_lib = env['BUILDERS']['SharedLibrary']
246     except KeyError:
247         import SCons.Defaults
248         action_list = [ SCons.Defaults.SharedCheck,
249                         SCons.Defaults.ShLinkAction ]
250         shared_lib = SCons.Builder.Builder(action = action_list,
251                                            emitter = "$SHLIBEMITTER",
252                                            prefix = '$SHLIBPREFIX',
253                                            suffix = '$SHLIBSUFFIX',
254                                            target_scanner = ProgramScanner,
255                                            src_suffix = '$SHOBJSUFFIX',
256                                            src_builder = 'SharedObject')
257         env['BUILDERS']['SharedLibrary'] = shared_lib
258
259     return shared_lib
260
261 def createLoadableModuleBuilder(env):
262     """This is a utility function that creates the LoadableModule
263     Builder in an Environment if it is not there already.
264
265     If it is already there, we return the existing one.
266     """
267
268     try:
269         ld_module = env['BUILDERS']['LoadableModule']
270     except KeyError:
271         import SCons.Defaults
272         action_list = [ SCons.Defaults.SharedCheck,
273                         SCons.Defaults.LdModuleLinkAction ]
274         ld_module = SCons.Builder.Builder(action = action_list,
275                                           emitter = "$SHLIBEMITTER",
276                                           prefix = '$LDMODULEPREFIX',
277                                           suffix = '$LDMODULESUFFIX',
278                                           target_scanner = ProgramScanner,
279                                           src_suffix = '$SHOBJSUFFIX',
280                                           src_builder = 'SharedObject')
281         env['BUILDERS']['LoadableModule'] = ld_module
282
283     return ld_module
284
285 def createObjBuilders(env):
286     """This is a utility function that creates the StaticObject
287     and SharedObject Builders in an Environment if they
288     are not there already.
289
290     If they are there already, we return the existing ones.
291
292     This is a separate function because soooo many Tools
293     use this functionality.
294
295     The return is a 2-tuple of (StaticObject, SharedObject)
296     """
297
298
299     try:
300         static_obj = env['BUILDERS']['StaticObject']
301     except KeyError:
302         static_obj = SCons.Builder.Builder(action = {},
303                                            emitter = {},
304                                            prefix = '$OBJPREFIX',
305                                            suffix = '$OBJSUFFIX',
306                                            src_builder = ['CFile', 'CXXFile'],
307                                            source_scanner = SourceFileScanner,
308                                            single_source = 1)
309         env['BUILDERS']['StaticObject'] = static_obj
310         env['BUILDERS']['Object'] = static_obj
311
312     try:
313         shared_obj = env['BUILDERS']['SharedObject']
314     except KeyError:
315         shared_obj = SCons.Builder.Builder(action = {},
316                                            emitter = {},
317                                            prefix = '$SHOBJPREFIX',
318                                            suffix = '$SHOBJSUFFIX',
319                                            src_builder = ['CFile', 'CXXFile'],
320                                            source_scanner = SourceFileScanner,
321                                            single_source = 1)
322         env['BUILDERS']['SharedObject'] = shared_obj
323
324     return (static_obj, shared_obj)
325
326 def createCFileBuilders(env):
327     """This is a utility function that creates the CFile/CXXFile
328     Builders in an Environment if they
329     are not there already.
330
331     If they are there already, we return the existing ones.
332
333     This is a separate function because soooo many Tools
334     use this functionality.
335
336     The return is a 2-tuple of (CFile, CXXFile)
337     """
338
339     try:
340         c_file = env['BUILDERS']['CFile']
341     except KeyError:
342         c_file = SCons.Builder.Builder(action = {},
343                                        emitter = {},
344                                        suffix = {None:'$CFILESUFFIX'})
345         env['BUILDERS']['CFile'] = c_file
346
347         env.SetDefault(CFILESUFFIX = '.c')
348
349     try:
350         cxx_file = env['BUILDERS']['CXXFile']
351     except KeyError:
352         cxx_file = SCons.Builder.Builder(action = {},
353                                          emitter = {},
354                                          suffix = {None:'$CXXFILESUFFIX'})
355         env['BUILDERS']['CXXFile'] = cxx_file
356         env.SetDefault(CXXFILESUFFIX = '.cc')
357
358     return (c_file, cxx_file)
359
360 ##########################################################################
361 #  Create common Java builders
362
363 def CreateJarBuilder(env):
364     try:
365         java_jar = env['BUILDERS']['Jar']
366     except KeyError:
367         fs = SCons.Node.FS.get_default_fs()
368         jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR')
369         java_jar = SCons.Builder.Builder(action = jar_com,
370                                          suffix = '$JARSUFFIX',
371                                          src_suffix = '$JAVACLASSSUFIX',
372                                          src_builder = 'JavaClassFile',
373                                          source_factory = fs.Entry)
374         env['BUILDERS']['Jar'] = java_jar
375     return java_jar
376
377 def CreateJavaHBuilder(env):
378     try:
379         java_javah = env['BUILDERS']['JavaH']
380     except KeyError:
381         fs = SCons.Node.FS.get_default_fs()
382         java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR')
383         java_javah = SCons.Builder.Builder(action = java_javah_com,
384                                            src_suffix = '$JAVACLASSSUFFIX',
385                                            target_factory = fs.Entry,
386                                            source_factory = fs.File,
387                                            src_builder = 'JavaClassFile')
388         env['BUILDERS']['JavaH'] = java_javah
389     return java_javah
390
391 def CreateJavaClassFileBuilder(env):
392     try:
393         java_class_file = env['BUILDERS']['JavaClassFile']
394     except KeyError:
395         fs = SCons.Node.FS.get_default_fs()
396         javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
397         java_class_file = SCons.Builder.Builder(action = javac_com,
398                                                 emitter = {},
399                                                 #suffix = '$JAVACLASSSUFFIX',
400                                                 src_suffix = '$JAVASUFFIX',
401                                                 src_builder = ['JavaFile'],
402                                                 target_factory = fs.Entry,
403                                                 source_factory = fs.File)
404         env['BUILDERS']['JavaClassFile'] = java_class_file
405     return java_class_file
406
407 def CreateJavaClassDirBuilder(env):
408     try:
409         java_class_dir = env['BUILDERS']['JavaClassDir']
410     except KeyError:
411         fs = SCons.Node.FS.get_default_fs()
412         javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
413         java_class_dir = SCons.Builder.Builder(action = javac_com,
414                                                emitter = {},
415                                                target_factory = fs.Dir,
416                                                source_factory = fs.Dir)
417         env['BUILDERS']['JavaClassDir'] = java_class_dir
418     return java_class_dir
419
420 def CreateJavaFileBuilder(env):
421     try:
422         java_file = env['BUILDERS']['JavaFile']
423     except KeyError:
424         java_file = SCons.Builder.Builder(action = {},
425                                           emitter = {},
426                                           suffix = {None:'$JAVASUFFIX'})
427         env['BUILDERS']['JavaFile'] = java_file
428         env['JAVASUFFIX'] = '.java'
429     return java_file
430
431 class ToolInitializerMethod:
432     """
433     This is added to a construction environment in place of a
434     method(s) normally called for a Builder (env.Object, env.StaticObject,
435     etc.).  When called, it has its associated ToolInitializer
436     object search the specified list of tools and apply the first
437     one that exists to the construction environment.  It then calls
438     whatever builder was (presumably) added to the construction
439     environment in place of this particular instance.
440     """
441     def __init__(self, name, initializer):
442         """
443         Note:  we store the tool name as __name__ so it can be used by
444         the class that attaches this to a construction environment.
445         """
446         self.__name__ = name
447         self.initializer = initializer
448
449     def get_builder(self, env):
450         """
451         Returns the appropriate real Builder for this method name
452         after having the associated ToolInitializer object apply
453         the appropriate Tool module.
454         """
455         builder = getattr(env, self.__name__)
456
457         self.initializer.apply_tools(env)
458
459         builder = getattr(env, self.__name__)
460         if builder is self:
461             # There was no Builder added, which means no valid Tool
462             # for this name was found (or possibly there's a mismatch
463             # between the name we were called by and the Builder name
464             # added by the Tool module).
465             return None
466
467         self.initializer.remove_methods(env)
468
469         return builder
470
471     def __call__(self, env, *args, **kw):
472         """
473         """
474         builder = self.get_builder(env)
475         if builder is None:
476             return [], []
477         return apply(builder, args, kw)
478
479 class ToolInitializer:
480     """
481     A class for delayed initialization of Tools modules.
482
483     Instances of this class associate a list of Tool modules with
484     a list of Builder method names that will be added by those Tool
485     modules.  As part of instantiating this object for a particular
486     construction environment, we also add the appropriate
487     ToolInitializerMethod objects for the various Builder methods
488     that we want to use to delay Tool searches until necessary.
489     """
490     def __init__(self, env, tools, names):
491         if not SCons.Util.is_List(tools):
492             tools = [tools]
493         if not SCons.Util.is_List(names):
494             names = [names]
495         self.env = env
496         self.tools = tools
497         self.names = names
498         self.methods = {}
499         for name in names:
500             method = ToolInitializerMethod(name, self)
501             self.methods[name] = method
502             env.AddMethod(method)
503
504     def remove_methods(self, env):
505         """
506         Removes the methods that were added by the tool initialization
507         so we no longer copy and re-bind them when the construction
508         environment gets cloned.
509         """
510         for method in self.methods.values():
511             env.RemoveMethod(method)
512
513     def apply_tools(self, env):
514         """
515         Searches the list of associated Tool modules for one that
516         exists, and applies that to the construction environment.
517         """
518         for t in self.tools:
519             tool = SCons.Tool.Tool(t)
520             if tool.exists(env):
521                 env.Tool(tool)
522                 return
523
524         # If we fall through here, there was no tool module found.
525         # This is where we can put an informative error message
526         # about the inability to find the tool.   We'll start doing
527         # this as we cut over more pre-defined Builder+Tools to use
528         # the ToolInitializer class.
529
530 def Initializers(env):
531     ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs'])
532     def Install(self, *args, **kw):
533         return apply(self._InternalInstall, args, kw)
534     def InstallAs(self, *args, **kw):
535         return apply(self._InternalInstallAs, args, kw)
536     env.AddMethod(Install)
537     env.AddMethod(InstallAs)
538
539 def FindTool(tools, env):
540     for tool in tools:
541         t = Tool(tool)
542         if t.exists(env):
543             return tool
544     return None
545
546 def FindAllTools(tools, env):
547     def ToolExists(tool, env=env):
548         return Tool(tool).exists(env)
549     return filter (ToolExists, tools)
550
551 def tool_list(platform, env):
552
553     # XXX this logic about what tool to prefer on which platform
554     #     should be moved into either the platform files or
555     #     the tool files themselves.
556     # The search orders here are described in the man page.  If you
557     # change these search orders, update the man page as well.
558     if str(platform) == 'win32':
559         "prefer Microsoft tools on Windows"
560         linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
561         c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ]
562         cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'c++', 'bcc32' ]
563         assemblers = ['masm', 'nasm', 'gas', '386asm' ]
564         fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
565         ars = ['mslib', 'ar', 'tlib']
566     elif str(platform) == 'os2':
567         "prefer IBM tools on OS/2"
568         linkers = ['ilink', 'gnulink', 'mslink']
569         c_compilers = ['icc', 'gcc', 'msvc', 'cc']
570         cxx_compilers = ['icc', 'g++', 'msvc', 'c++']
571         assemblers = ['nasm', 'masm', 'gas']
572         fortran_compilers = ['ifl', 'g77']
573         ars = ['ar', 'mslib']
574     elif str(platform) == 'irix':
575         "prefer MIPSPro on IRIX"
576         linkers = ['sgilink', 'gnulink']
577         c_compilers = ['sgicc', 'gcc', 'cc']
578         cxx_compilers = ['sgic++', 'g++', 'c++']
579         assemblers = ['as', 'gas']
580         fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
581         ars = ['sgiar']
582     elif str(platform) == 'sunos':
583         "prefer Forte tools on SunOS"
584         linkers = ['sunlink', 'gnulink']
585         c_compilers = ['suncc', 'gcc', 'cc']
586         cxx_compilers = ['sunc++', 'g++', 'c++']
587         assemblers = ['as', 'gas']
588         fortran_compilers = ['sunf95', 'sunf90', 'sunf77', 'f95', 'f90', 'f77',
589                              'gfortran', 'g77', 'fortran']
590         ars = ['sunar']
591     elif str(platform) == 'hpux':
592         "prefer aCC tools on HP-UX"
593         linkers = ['hplink', 'gnulink']
594         c_compilers = ['hpcc', 'gcc', 'cc']
595         cxx_compilers = ['hpc++', 'g++', 'c++']
596         assemblers = ['as', 'gas']
597         fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
598         ars = ['ar']
599     elif str(platform) == 'aix':
600         "prefer AIX Visual Age tools on AIX"
601         linkers = ['aixlink', 'gnulink']
602         c_compilers = ['aixcc', 'gcc', 'cc']
603         cxx_compilers = ['aixc++', 'g++', 'c++']
604         assemblers = ['as', 'gas']
605         fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran']
606         ars = ['ar']
607     elif str(platform) == 'darwin':
608         "prefer GNU tools on Mac OS X, except for some linkers and IBM tools"
609         linkers = ['applelink', 'gnulink']
610         c_compilers = ['gcc', 'cc']
611         cxx_compilers = ['g++', 'c++']
612         assemblers = ['as']
613         fortran_compilers = ['gfortran', 'f95', 'f90', 'g77']
614         ars = ['ar']
615     else:
616         "prefer GNU tools on all other platforms"
617         linkers = ['gnulink', 'mslink', 'ilink']
618         c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
619         cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++']
620         assemblers = ['gas', 'nasm', 'masm']
621         fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77']
622         ars = ['ar', 'mslib']
623
624     c_compiler = FindTool(c_compilers, env) or c_compilers[0]
625
626     # XXX this logic about what tool provides what should somehow be
627     #     moved into the tool files themselves.
628     if c_compiler and c_compiler == 'mingw':
629         # MinGW contains a linker, C compiler, C++ compiler,
630         # Fortran compiler, archiver and assembler:
631         cxx_compiler = None
632         linker = None
633         assembler = None
634         fortran_compiler = None
635         ar = None
636     else:
637         # Don't use g++ if the C compiler has built-in C++ support:
638         if c_compiler in ('msvc', 'intelc', 'icc'):
639             cxx_compiler = None
640         else:
641             cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
642         linker = FindTool(linkers, env) or linkers[0]
643         assembler = FindTool(assemblers, env) or assemblers[0]
644         fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
645         ar = FindTool(ars, env) or ars[0]
646
647     other_tools = FindAllTools(['BitKeeper', 'CVS',
648                                 'dmd',
649                                 'filesystem',
650                                 'dvipdf', 'dvips', 'gs',
651                                 'jar', 'javac', 'javah',
652                                 'latex', 'lex',
653                                 'm4', 'midl', 'msvs',
654                                 'pdflatex', 'pdftex', 'Perforce',
655                                 'RCS', 'rmic', 'rpcgen',
656                                 'SCCS',
657                                 # 'Subversion',
658                                 'swig',
659                                 'tar', 'tex',
660                                 'yacc', 'zip', 'rpm', 'wix'],
661                                env)
662
663     tools = ([linker, c_compiler, cxx_compiler,
664               fortran_compiler, assembler, ar]
665              + other_tools)
666
667     return filter(lambda x: x, tools)