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
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
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:
27 # The above copyright notice and this permission notice shall be included
28 # in all copies or substantial portions of the Software.
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.
39 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
46 import SCons.Scanner.C
47 import SCons.Scanner.D
48 import SCons.Scanner.LaTeX
49 import SCons.Scanner.Prog
51 CScanner = SCons.Scanner.C.CScanner()
52 DScanner = SCons.Scanner.D.DScanner()
53 LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
54 ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
55 SourceFileScanner = SCons.Scanner.Scanner({}, name='SourceFileScanner')
57 CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
58 ".h", ".H", ".hxx", ".hpp", ".hh",
65 IDLSuffixes = [".idl", ".IDL"]
67 LaTeXSuffixes = [".tex", ".ltx", ".latex"]
69 for suffix in CSuffixes:
70 SourceFileScanner.add_scanner(suffix, CScanner)
72 for suffix in DSuffixes:
73 SourceFileScanner.add_scanner(suffix, DScanner)
75 for suffix in LaTeXSuffixes:
76 SourceFileScanner.add_scanner(suffix, LaTeXScanner)
79 def __init__(self, name, toolpath=[], **kw):
81 self.toolpath = toolpath
82 # remember these so we can merge them into the call
85 module = self._tool_module()
86 self.generate = module.generate
87 self.exists = module.exists
89 def _tool_module(self):
90 oldpythonpath = sys.path
91 sys.path = self.toolpath + sys.path
95 file, path, desc = imp.find_module(self.name, self.toolpath)
97 return imp.load_module(self.name, file, path, desc)
101 except ImportError, e:
107 for aPath in self.toolpath:
109 importer = zipimport.zipimporter(aPath)
110 return importer.load_module(self.name)
111 except ImportError, e:
114 sys.path = oldpythonpath
116 full_name = 'SCons.Tool.' + self.name
118 return sys.modules[full_name]
121 smpath = sys.modules['SCons.Tool'].__path__
123 file, path, desc = imp.find_module(self.name, smpath)
124 module = imp.load_module(full_name, file, path, desc)
125 setattr(SCons.Tool, self.name, module)
129 except ImportError, e:
132 importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] )
133 module = importer.load_module(full_name)
134 setattr(SCons.Tool, self.name, module)
136 except ImportError, e:
137 m = "No tool named '%s': %s" % (self.name, e)
138 raise SCons.Errors.UserError, m
139 except ImportError, e:
140 m = "No tool named '%s': %s" % (self.name, e)
141 raise SCons.Errors.UserError, m
143 def __call__(self, env, *args, **kw):
144 if self.init_kw is not None:
145 # Merge call kws into init kws;
146 # but don't bash self.init_kw.
149 kw = self.init_kw.copy()
153 env.Append(TOOLS = [ self.name ])
154 apply(self.generate, ( env, ) + args, kw)
159 def createProgBuilder(env):
160 """This is a utility function that creates the Program
161 Builder in an Environment if it is not there already.
163 If it is already there, we return the existing one.
167 program = env['BUILDERS']['Program']
169 import SCons.Defaults
170 program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction,
171 emitter = '$PROGEMITTER',
172 prefix = '$PROGPREFIX',
173 suffix = '$PROGSUFFIX',
174 src_suffix = '$OBJSUFFIX',
175 src_builder = 'Object',
176 target_scanner = ProgramScanner)
177 env['BUILDERS']['Program'] = program
181 def createStaticLibBuilder(env):
182 """This is a utility function that creates the StaticLibrary
183 Builder in an Environment if it is not there already.
185 If it is already there, we return the existing one.
189 static_lib = env['BUILDERS']['StaticLibrary']
191 action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
192 if env.Detect('ranlib'):
193 ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
194 action_list.append(ranlib_action)
196 static_lib = SCons.Builder.Builder(action = action_list,
197 emitter = '$LIBEMITTER',
198 prefix = '$LIBPREFIX',
199 suffix = '$LIBSUFFIX',
200 src_suffix = '$OBJSUFFIX',
201 src_builder = 'StaticObject')
202 env['BUILDERS']['StaticLibrary'] = static_lib
203 env['BUILDERS']['Library'] = static_lib
207 def createSharedLibBuilder(env):
208 """This is a utility function that creates the SharedLibrary
209 Builder in an Environment if it is not there already.
211 If it is already there, we return the existing one.
215 shared_lib = env['BUILDERS']['SharedLibrary']
217 import SCons.Defaults
218 action_list = [ SCons.Defaults.SharedCheck,
219 SCons.Defaults.ShLinkAction ]
220 shared_lib = SCons.Builder.Builder(action = action_list,
221 emitter = "$SHLIBEMITTER",
222 prefix = '$SHLIBPREFIX',
223 suffix = '$SHLIBSUFFIX',
224 target_scanner = ProgramScanner,
225 src_suffix = '$SHOBJSUFFIX',
226 src_builder = 'SharedObject')
227 env['BUILDERS']['SharedLibrary'] = shared_lib
231 def createLoadableModuleBuilder(env):
232 """This is a utility function that creates the LoadableModule
233 Builder in an Environment if it is not there already.
235 If it is already there, we return the existing one.
239 ld_module = env['BUILDERS']['LoadableModule']
241 import SCons.Defaults
242 action_list = [ SCons.Defaults.SharedCheck,
243 SCons.Defaults.LdModuleLinkAction ]
244 ld_module = SCons.Builder.Builder(action = action_list,
245 emitter = "$SHLIBEMITTER",
246 prefix = '$LDMODULEPREFIX',
247 suffix = '$LDMODULESUFFIX',
248 target_scanner = ProgramScanner,
249 src_suffix = '$SHOBJSUFFIX',
250 src_builder = 'SharedObject')
251 env['BUILDERS']['LoadableModule'] = ld_module
255 def createObjBuilders(env):
256 """This is a utility function that creates the StaticObject
257 and SharedObject Builders in an Environment if they
258 are not there already.
260 If they are there already, we return the existing ones.
262 This is a separate function because soooo many Tools
263 use this functionality.
265 The return is a 2-tuple of (StaticObject, SharedObject)
270 static_obj = env['BUILDERS']['StaticObject']
272 static_obj = SCons.Builder.Builder(action = {},
274 prefix = '$OBJPREFIX',
275 suffix = '$OBJSUFFIX',
276 src_builder = ['CFile', 'CXXFile'],
277 source_scanner = SourceFileScanner,
279 env['BUILDERS']['StaticObject'] = static_obj
280 env['BUILDERS']['Object'] = static_obj
283 shared_obj = env['BUILDERS']['SharedObject']
285 shared_obj = SCons.Builder.Builder(action = {},
287 prefix = '$SHOBJPREFIX',
288 suffix = '$SHOBJSUFFIX',
289 src_builder = ['CFile', 'CXXFile'],
290 source_scanner = SourceFileScanner,
292 env['BUILDERS']['SharedObject'] = shared_obj
294 return (static_obj, shared_obj)
296 def createCFileBuilders(env):
297 """This is a utility function that creates the CFile/CXXFile
298 Builders in an Environment if they
299 are not there already.
301 If they are there already, we return the existing ones.
303 This is a separate function because soooo many Tools
304 use this functionality.
306 The return is a 2-tuple of (CFile, CXXFile)
310 c_file = env['BUILDERS']['CFile']
312 c_file = SCons.Builder.Builder(action = {},
314 suffix = {None:'$CFILESUFFIX'})
315 env['BUILDERS']['CFile'] = c_file
316 env['CFILESUFFIX'] = '.c'
319 cxx_file = env['BUILDERS']['CXXFile']
321 cxx_file = SCons.Builder.Builder(action = {},
323 suffix = {None:'$CXXFILESUFFIX'})
324 env['BUILDERS']['CXXFile'] = cxx_file
325 env['CXXFILESUFFIX'] = '.cc'
327 return (c_file, cxx_file)
329 def FindTool(tools, env):
336 def FindAllTools(tools, env):
337 def ToolExists(tool, env=env):
338 return Tool(tool).exists(env)
339 return filter (ToolExists, tools)
341 def tool_list(platform, env):
343 # XXX this logic about what tool to prefer on which platform
344 # should be moved into either the platform files or
345 # the tool files themselves.
346 # The search orders here are described in the man page. If you
347 # change these search orders, update the man page as well.
348 if str(platform) == 'win32':
349 "prefer Microsoft tools on Windows"
350 linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
351 c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ]
352 cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'c++', 'bcc32' ]
353 assemblers = ['masm', 'nasm', 'gas', '386asm' ]
354 fortran_compilers = ['g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
355 ars = ['mslib', 'ar', 'tlib']
356 elif str(platform) == 'os2':
357 "prefer IBM tools on OS/2"
358 linkers = ['ilink', 'gnulink', 'mslink']
359 c_compilers = ['icc', 'gcc', 'msvc', 'cc']
360 cxx_compilers = ['icc', 'g++', 'msvc', 'c++']
361 assemblers = ['nasm', 'masm', 'gas']
362 fortran_compilers = ['ifl', 'g77']
363 ars = ['ar', 'mslib']
364 elif str(platform) == 'irix':
365 "prefer MIPSPro on IRIX"
366 linkers = ['sgilink', 'gnulink']
367 c_compilers = ['sgicc', 'gcc', 'cc']
368 cxx_compilers = ['sgic++', 'g++', 'c++']
369 assemblers = ['as', 'gas']
370 fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
372 elif str(platform) == 'sunos':
373 "prefer Forte tools on SunOS"
374 linkers = ['sunlink', 'gnulink']
375 c_compilers = ['suncc', 'gcc', 'cc']
376 cxx_compilers = ['sunc++', 'g++', 'c++']
377 assemblers = ['as', 'gas']
378 fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
380 elif str(platform) == 'hpux':
381 "prefer aCC tools on HP-UX"
382 linkers = ['hplink', 'gnulink']
383 c_compilers = ['hpcc', 'gcc', 'cc']
384 cxx_compilers = ['hpc++', 'g++', 'c++']
385 assemblers = ['as', 'gas']
386 fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
388 elif str(platform) == 'aix':
389 "prefer AIX Visual Age tools on AIX"
390 linkers = ['aixlink', 'gnulink']
391 c_compilers = ['aixcc', 'gcc', 'cc']
392 cxx_compilers = ['aixc++', 'g++', 'c++']
393 assemblers = ['as', 'gas']
394 fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran']
396 elif str(platform) == 'darwin':
397 "prefer GNU tools on Mac OS X, except for some linkers and IBM tools"
398 linkers = ['applelink', 'gnulink']
399 c_compilers = ['gcc', 'cc']
400 cxx_compilers = ['g++', 'c++']
402 fortran_compilers = ['f95', 'f90', 'g77']
405 "prefer GNU tools on all other platforms"
406 linkers = ['gnulink', 'mslink', 'ilink']
407 c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
408 cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++']
409 assemblers = ['gas', 'nasm', 'masm']
410 fortran_compilers = ['f95', 'f90', 'g77', 'ifort', 'ifl', 'fortran']
411 ars = ['ar', 'mslib']
413 c_compiler = FindTool(c_compilers, env) or c_compilers[0]
415 # XXX this logic about what tool provides what should somehow be
416 # moved into the tool files themselves.
417 if c_compiler and c_compiler == 'mingw':
418 # MinGW contains a linker, C compiler, C++ compiler,
419 # Fortran compiler, archiver and assembler:
423 fortran_compiler = None
426 # Don't use g++ if the C compiler has built-in C++ support:
427 if c_compiler in ('msvc', 'intelc', 'icc'):
430 cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
431 linker = FindTool(linkers, env) or linkers[0]
432 assembler = FindTool(assemblers, env) or assemblers[0]
433 fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
434 ar = FindTool(ars, env) or ars[0]
436 other_tools = FindAllTools(['BitKeeper', 'CVS',
438 'dvipdf', 'dvips', 'gs',
439 'jar', 'javac', 'javah',
441 'm4', 'midl', 'msvs',
442 'pdflatex', 'pdftex', 'Perforce',
443 'RCS', 'rmic', 'rpcgen',
451 tools = ([linker, c_compiler, cxx_compiler,
452 fortran_compiler, assembler, ar]
455 return filter(lambda x: x, tools)