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