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 subsysem 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__"
48 def __init__(self, name):
51 def __call__(self, env, *args, **kw):
52 env.Append(TOOLS = [ self.name ])
53 apply(self.generate, ( env, ) + args, kw)
58 def Tool(name, toolpath=[]):
59 "Select a canned Tool specification, optionally searching in toolpath."
62 file, path, desc = imp.find_module(name, toolpath)
64 module = imp.load_module(name, file, path, desc)
66 spec.generate = module.generate
67 spec.exists = module.exists
72 except ImportError, e:
75 full_name = 'SCons.Tool.' + name
76 if not sys.modules.has_key(full_name):
78 file, path, desc = imp.find_module(name,
79 sys.modules['SCons.Tool'].__path__)
80 mod = imp.load_module(full_name, file, path, desc)
81 setattr(SCons.Tool, name, mod)
82 except ImportError, e:
83 raise SCons.Errors.UserError, "No tool named '%s': %s" % (name, e)
87 spec.generate = sys.modules[full_name].generate
88 spec.exists = sys.modules[full_name].exists
91 def createProgBuilder(env):
92 """This is a utility function that creates the Program
93 Builder in an Environment if it is not there already.
95 If it is already there, we return the existing one.
99 program = env['BUILDERS']['Program']
101 program = SCons.Builder.Builder(action = '$LINKCOM',
102 emitter = '$PROGEMITTER',
103 prefix = '$PROGPREFIX',
104 suffix = '$PROGSUFFIX',
105 src_suffix = '$OBJSUFFIX',
106 src_builder = 'Object',
107 scanner = SCons.Defaults.ProgScan)
108 env['BUILDERS']['Program'] = program
112 def createStaticLibBuilder(env):
113 """This is a utility function that creates the StaticLibrary
114 Builder in an Environment if it is not there already.
116 If it is already there, we return the existing one.
120 static_lib = env['BUILDERS']['StaticLibrary']
122 static_lib = SCons.Builder.Builder(action = "$ARCOM",
123 emitter = '$LIBEMITTER',
124 prefix = '$LIBPREFIX',
125 suffix = '$LIBSUFFIX',
126 src_suffix = '$OBJSUFFIX',
127 src_builder = 'StaticObject')
128 env['BUILDERS']['StaticLibrary'] = static_lib
129 env['BUILDERS']['Library'] = static_lib
133 def createSharedLibBuilder(env):
134 """This is a utility function that creates the SharedLibrary
135 Builder in an Environment if it is not there already.
137 If it is already there, we return the existing one.
141 shared_lib = env['BUILDERS']['SharedLibrary']
143 action_list = [ SCons.Defaults.SharedCheck, "$SHLINKCOM" ]
144 shared_lib = SCons.Builder.Builder(action = action_list,
145 emitter = "$SHLIBEMITTER",
146 prefix = '$SHLIBPREFIX',
147 suffix = '$SHLIBSUFFIX',
148 scanner = SCons.Defaults.ProgScan,
149 src_suffix = '$SHOBJSUFFIX',
150 src_builder = 'SharedObject')
151 env['BUILDERS']['SharedLibrary'] = shared_lib
155 def createObjBuilders(env):
156 """This is a utility function that creates the StaticObject
157 and SharedObject Builders in an Environment if they
158 are not there already.
160 If they are there already, we return the existing ones.
162 This is a separate function because soooo many Tools
163 use this functionality.
165 The return is a 2-tuple of (StaticObject, SharedObject)
169 static_obj = env['BUILDERS']['StaticObject']
171 static_obj = SCons.Builder.Builder(action = {},
172 emitter = "$OBJEMITTER",
173 prefix = '$OBJPREFIX',
174 suffix = '$OBJSUFFIX',
175 src_builder = ['CFile', 'CXXFile'])
176 env['BUILDERS']['StaticObject'] = static_obj
177 env['BUILDERS']['Object'] = static_obj
178 env['OBJEMITTER'] = SCons.Defaults.StaticObjectEmitter
181 shared_obj = env['BUILDERS']['SharedObject']
183 shared_obj = SCons.Builder.Builder(action = {},
184 emitter = "$SHOBJEMITTER",
185 prefix = '$SHOBJPREFIX',
186 suffix = '$SHOBJSUFFIX',
187 src_builder = ['CFile', 'CXXFile'])
188 env['BUILDERS']['SharedObject'] = shared_obj
189 env['SHOBJEMITTER'] = SCons.Defaults.SharedObjectEmitter
191 return (static_obj, shared_obj)
193 def createCFileBuilders(env):
194 """This is a utility function that creates the CFile/CXXFile
195 Builders in an Environment if they
196 are not there already.
198 If they are there already, we return the existing ones.
200 This is a separate function because soooo many Tools
201 use this functionality.
203 The return is a 2-tuple of (CFile, CXXFile)
207 c_file = env['BUILDERS']['CFile']
209 c_file = SCons.Builder.Builder(action = {},
211 suffix = {None:'$CFILESUFFIX'})
212 env['BUILDERS']['CFile'] = c_file
213 env['CFILESUFFIX'] = '.c'
216 cxx_file = env['BUILDERS']['CXXFile']
218 cxx_file = SCons.Builder.Builder(action = {},
220 suffix = {None:'$CXXFILESUFFIX'})
221 env['BUILDERS']['CXXFile'] = cxx_file
222 env['CXXFILESUFFIX'] = '.cc'
224 return (c_file, cxx_file)
226 def FindTool(tools, env):
233 def FindAllTools(tools, env):
234 def ToolExists(tool, env=env):
235 return Tool(tool).exists(env)
236 return filter (ToolExists, tools)
238 def tool_list(platform, env):
240 # XXX this logic about what tool to prefer on which platform
241 # should be moved into either the platform files or
242 # the tool files themselves.
243 # The search orders here are described in the man page. If you
244 # change these search orders, update the man page as well.
245 if str(platform) == 'win32':
246 "prefer Microsoft tools on Windows"
247 linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
248 c_compilers = ['msvc', 'mingw', 'gcc', 'icl', 'icc', 'cc', 'bcc32' ]
249 cxx_compilers = ['msvc', 'icc', 'g++', 'c++', 'bcc32' ]
250 assemblers = ['masm', 'nasm', 'gas', '386asm' ]
251 fortran_compilers = ['g77', 'ifl']
252 ars = ['mslib', 'ar', 'tlib']
253 elif str(platform) == 'os2':
254 "prefer IBM tools on OS/2"
255 linkers = ['ilink', 'gnulink', 'mslink']
256 c_compilers = ['icc', 'gcc', 'msvc', 'cc']
257 cxx_compilers = ['icc', 'g++', 'msvc', 'c++']
258 assemblers = ['nasm', 'masm', 'gas']
259 fortran_compilers = ['ifl', 'g77']
260 ars = ['ar', 'mslib']
261 elif str(platform) == 'irix':
262 "prefer MIPSPro on IRIX"
263 linkers = ['sgilink', 'gnulink']
264 c_compilers = ['sgicc', 'gcc', 'cc']
265 cxx_compilers = ['sgic++', 'g++', 'c++']
266 assemblers = ['as', 'gas']
267 fortran_compilers = ['f77', 'g77']
269 elif str(platform) == 'sunos':
270 "prefer Forte tools on SunOS"
271 linkers = ['sunlink', 'gnulink']
272 c_compilers = ['suncc', 'gcc', 'cc']
273 cxx_compilers = ['sunc++', 'g++', 'c++']
274 assemblers = ['as', 'gas']
275 fortran_compilers = ['f77', 'g77']
277 elif str(platform) == 'hpux':
278 "prefer aCC tools on HP-UX"
279 linkers = ['hplink', 'gnulink']
280 c_compilers = ['hpcc', 'gcc', 'cc']
281 cxx_compilers = ['hpc++', 'g++', 'c++']
282 assemblers = ['as', 'gas']
283 fortran_compilers = ['f77', 'g77']
285 elif str(platform) == 'aix':
286 "prefer AIX Visual Age tools on AIX"
287 linkers = ['aixlink', 'gnulink']
288 c_compilers = ['aixcc', 'gcc', 'cc']
289 cxx_compilers = ['aixc++', 'g++', 'c++']
290 assemblers = ['as', 'gas']
291 fortran_compilers = ['aixf77', 'g77']
294 "prefer GNU tools on all other platforms"
295 linkers = ['gnulink', 'mslink', 'ilink']
296 c_compilers = ['gcc', 'msvc', 'icc', 'cc']
297 cxx_compilers = ['g++', 'msvc', 'icc', 'c++']
298 assemblers = ['gas', 'nasm', 'masm']
299 fortran_compilers = ['g77', 'ifl']
300 ars = ['ar', 'mslib']
302 c_compiler = FindTool(c_compilers, env) or c_compilers[0]
304 # XXX this logic about what tool provides what should somehow be
305 # moved into the tool files themselves.
306 if c_compiler and c_compiler == 'mingw':
307 # MinGW contains a linker, C compiler, C++ compiler,
308 # Fortran compiler, archiver and assembler:
312 fortran_compiler = None
315 # Don't use g++ if the C compiler has built-in C++ support:
316 if c_compiler in ('msvc', 'icc'):
319 cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
320 linker = FindTool(linkers, env) or linkers[0]
321 assembler = FindTool(assemblers, env) or assemblers[0]
322 fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
323 ar = FindTool(ars, env) or ars[0]
325 other_tools = FindAllTools(['BitKeeper', 'CVS',
326 'dvipdf', 'dvips', 'gs',
327 'jar', 'javac', 'javah',
328 'latex', 'lex', 'm4', 'midl', 'msvs',
329 'pdflatex', 'pdftex', 'Perforce',
330 'RCS', 'rmic', 'SCCS',
333 'tar', 'tex', 'yacc', 'zip'],
336 tools = ([linker, c_compiler, cxx_compiler,
337 fortran_compiler, assembler, ar]
340 return filter(lambda x: x, tools)