You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1240 lines
48 KiB

6 years ago
  1. """SCons.Tool
  2. SCons tool selection.
  3. This looks for modules that define a callable object that can modify
  4. a construction environment as appropriate for a given tool (or tool
  5. chain).
  6. Note that because this subsystem just *selects* a callable that can
  7. modify a construction environment, it's possible for people to define
  8. their own "tool specification" in an arbitrary callable function. No
  9. one needs to use or tie in to this subsystem in order to roll their own
  10. tool definition.
  11. """
  12. #
  13. # Copyright (c) 2001 - 2017 The SCons Foundation
  14. #
  15. # Permission is hereby granted, free of charge, to any person obtaining
  16. # a copy of this software and associated documentation files (the
  17. # "Software"), to deal in the Software without restriction, including
  18. # without limitation the rights to use, copy, modify, merge, publish,
  19. # distribute, sublicense, and/or sell copies of the Software, and to
  20. # permit persons to whom the Software is furnished to do so, subject to
  21. # the following conditions:
  22. #
  23. # The above copyright notice and this permission notice shall be included
  24. # in all copies or substantial portions of the Software.
  25. #
  26. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  27. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  28. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. __revision__ = "src/engine/SCons/Tool/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"
  34. import imp
  35. import importlib
  36. import sys
  37. import re
  38. import os
  39. import shutil
  40. import SCons.Builder
  41. import SCons.Errors
  42. import SCons.Node.FS
  43. import SCons.Scanner
  44. import SCons.Scanner.C
  45. import SCons.Scanner.D
  46. import SCons.Scanner.LaTeX
  47. import SCons.Scanner.Prog
  48. import SCons.Scanner.SWIG
  49. import collections
  50. DefaultToolpath=[]
  51. CScanner = SCons.Scanner.C.CScanner()
  52. DScanner = SCons.Scanner.D.DScanner()
  53. LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner()
  54. PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner()
  55. ProgramScanner = SCons.Scanner.Prog.ProgramScanner()
  56. SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner')
  57. SWIGScanner = SCons.Scanner.SWIG.SWIGScanner()
  58. CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
  59. ".h", ".H", ".hxx", ".hpp", ".hh",
  60. ".F", ".fpp", ".FPP",
  61. ".m", ".mm",
  62. ".S", ".spp", ".SPP", ".sx"]
  63. DSuffixes = ['.d']
  64. IDLSuffixes = [".idl", ".IDL"]
  65. LaTeXSuffixes = [".tex", ".ltx", ".latex"]
  66. SWIGSuffixes = ['.i']
  67. for suffix in CSuffixes:
  68. SourceFileScanner.add_scanner(suffix, CScanner)
  69. for suffix in DSuffixes:
  70. SourceFileScanner.add_scanner(suffix, DScanner)
  71. for suffix in SWIGSuffixes:
  72. SourceFileScanner.add_scanner(suffix, SWIGScanner)
  73. # FIXME: what should be done here? Two scanners scan the same extensions,
  74. # but look for different files, e.g., "picture.eps" vs. "picture.pdf".
  75. # The builders for DVI and PDF explicitly reference their scanners
  76. # I think that means this is not needed???
  77. for suffix in LaTeXSuffixes:
  78. SourceFileScanner.add_scanner(suffix, LaTeXScanner)
  79. SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner)
  80. # Tool aliases are needed for those tools whos module names also
  81. # occur in the python standard library. This causes module shadowing and
  82. # can break using python library functions under python3
  83. TOOL_ALIASES = {
  84. 'gettext':'gettext_tool',
  85. 'clang++': 'clangxx',
  86. }
  87. class Tool(object):
  88. def __init__(self, name, toolpath=[], **kw):
  89. # Rename if there's a TOOL_ALIAS for this tool
  90. self.name = TOOL_ALIASES.get(name,name)
  91. self.toolpath = toolpath + DefaultToolpath
  92. # remember these so we can merge them into the call
  93. self.init_kw = kw
  94. module = self._tool_module()
  95. self.generate = module.generate
  96. self.exists = module.exists
  97. if hasattr(module, 'options'):
  98. self.options = module.options
  99. def _load_dotted_module_py2(self, short_name, full_name, searchpaths=None):
  100. splitname = short_name.split('.')
  101. index = 0
  102. srchpths = searchpaths
  103. for item in splitname:
  104. file, path, desc = imp.find_module(item, srchpths)
  105. mod = imp.load_module(full_name, file, path, desc)
  106. srchpths = [path]
  107. return mod, file
  108. def _tool_module(self):
  109. oldpythonpath = sys.path
  110. sys.path = self.toolpath + sys.path
  111. # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path))
  112. if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)):
  113. # Py 2 code
  114. try:
  115. try:
  116. file = None
  117. try:
  118. mod, file = self._load_dotted_module_py2(self.name, self.name, self.toolpath)
  119. return mod
  120. finally:
  121. if file:
  122. file.close()
  123. except ImportError as e:
  124. splitname = self.name.split('.')
  125. if str(e)!="No module named %s"%splitname[0]:
  126. raise SCons.Errors.EnvironmentError(e)
  127. try:
  128. import zipimport
  129. except ImportError:
  130. pass
  131. else:
  132. for aPath in self.toolpath:
  133. try:
  134. importer = zipimport.zipimporter(aPath)
  135. return importer.load_module(self.name)
  136. except ImportError as e:
  137. pass
  138. finally:
  139. sys.path = oldpythonpath
  140. elif sys.version_info[1] > 4:
  141. # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692
  142. # import importlib.util
  143. # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
  144. # foo = importlib.util.module_from_spec(spec)
  145. # spec.loader.exec_module(foo)
  146. # foo.MyClass()
  147. # Py 3 code
  148. # import pdb; pdb.set_trace()
  149. import importlib.util
  150. # sys.stderr.write("toolpath:%s\n" % self.toolpath)
  151. # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__)
  152. debug = False
  153. spec = None
  154. found_name = self.name
  155. add_to_scons_tools_namespace = False
  156. for path in self.toolpath:
  157. sepname = self.name.replace('.', os.path.sep)
  158. file_path = os.path.join(path, "%s.py"%sepname)
  159. file_package = os.path.join(path, sepname)
  160. if debug: sys.stderr.write("Trying:%s %s\n"%(file_path, file_package))
  161. if os.path.isfile(file_path):
  162. spec = importlib.util.spec_from_file_location(self.name, file_path)
  163. if debug: print("file_Path:%s FOUND"%file_path)
  164. break
  165. elif os.path.isdir(file_package):
  166. file_package = os.path.join(file_package, '__init__.py')
  167. spec = importlib.util.spec_from_file_location(self.name, file_package)
  168. if debug: print("PACKAGE:%s Found"%file_package)
  169. break
  170. else:
  171. continue
  172. if spec is None:
  173. if debug: sys.stderr.write("NO SPEC :%s\n"%self.name)
  174. spec = importlib.util.find_spec("."+self.name, package='SCons.Tool')
  175. if spec:
  176. found_name = 'SCons.Tool.'+self.name
  177. add_to_scons_tools_namespace = True
  178. if debug: sys.stderr.write("Spec Found? .%s :%s\n"%(self.name, spec))
  179. if spec is None:
  180. error_string = "No module named %s"%self.name
  181. raise SCons.Errors.EnvironmentError(error_string)
  182. module = importlib.util.module_from_spec(spec)
  183. if module is None:
  184. if debug: print("MODULE IS NONE:%s"%self.name)
  185. error_string = "No module named %s"%self.name
  186. raise SCons.Errors.EnvironmentError(error_string)
  187. # Don't reload a tool we already loaded.
  188. sys_modules_value = sys.modules.get(found_name,False)
  189. if sys_modules_value and sys_modules_value.__file__ == spec.origin:
  190. return sys.modules[found_name]
  191. else:
  192. # Not sure what to do in the case that there already
  193. # exists sys.modules[self.name] but the source file is
  194. # different.. ?
  195. module = spec.loader.load_module(spec.name)
  196. sys.modules[found_name] = module
  197. if add_to_scons_tools_namespace:
  198. # If we found it in SCons.Tool, then add it to the module
  199. setattr(SCons.Tool, self.name, module)
  200. return module
  201. sys.path = oldpythonpath
  202. full_name = 'SCons.Tool.' + self.name
  203. try:
  204. return sys.modules[full_name]
  205. except KeyError:
  206. try:
  207. smpath = sys.modules['SCons.Tool'].__path__
  208. try:
  209. module, file = self._load_dotted_module_py2(self.name, full_name, smpath)
  210. setattr(SCons.Tool, self.name, module)
  211. if file:
  212. file.close()
  213. return module
  214. except ImportError as e:
  215. if str(e)!="No module named %s"%self.name:
  216. raise SCons.Errors.EnvironmentError(e)
  217. try:
  218. import zipimport
  219. importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] )
  220. module = importer.load_module(full_name)
  221. setattr(SCons.Tool, self.name, module)
  222. return module
  223. except ImportError as e:
  224. m = "No tool named '%s': %s" % (self.name, e)
  225. raise SCons.Errors.EnvironmentError(m)
  226. except ImportError as e:
  227. m = "No tool named '%s': %s" % (self.name, e)
  228. raise SCons.Errors.EnvironmentError(m)
  229. def __call__(self, env, *args, **kw):
  230. if self.init_kw is not None:
  231. # Merge call kws into init kws;
  232. # but don't bash self.init_kw.
  233. if kw is not None:
  234. call_kw = kw
  235. kw = self.init_kw.copy()
  236. kw.update(call_kw)
  237. else:
  238. kw = self.init_kw
  239. env.Append(TOOLS = [ self.name ])
  240. if hasattr(self, 'options'):
  241. import SCons.Variables
  242. if 'options' not in env:
  243. from SCons.Script import ARGUMENTS
  244. env['options']=SCons.Variables.Variables(args=ARGUMENTS)
  245. opts=env['options']
  246. self.options(opts)
  247. opts.Update(env)
  248. self.generate(env, *args, **kw)
  249. def __str__(self):
  250. return self.name
  251. ##########################################################################
  252. # Create common executable program / library / object builders
  253. def createProgBuilder(env):
  254. """This is a utility function that creates the Program
  255. Builder in an Environment if it is not there already.
  256. If it is already there, we return the existing one.
  257. """
  258. try:
  259. program = env['BUILDERS']['Program']
  260. except KeyError:
  261. import SCons.Defaults
  262. program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction,
  263. emitter = '$PROGEMITTER',
  264. prefix = '$PROGPREFIX',
  265. suffix = '$PROGSUFFIX',
  266. src_suffix = '$OBJSUFFIX',
  267. src_builder = 'Object',
  268. target_scanner = ProgramScanner)
  269. env['BUILDERS']['Program'] = program
  270. return program
  271. def createStaticLibBuilder(env):
  272. """This is a utility function that creates the StaticLibrary
  273. Builder in an Environment if it is not there already.
  274. If it is already there, we return the existing one.
  275. """
  276. try:
  277. static_lib = env['BUILDERS']['StaticLibrary']
  278. except KeyError:
  279. action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
  280. if env.get('RANLIB',False) or env.Detect('ranlib'):
  281. ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
  282. action_list.append(ranlib_action)
  283. static_lib = SCons.Builder.Builder(action = action_list,
  284. emitter = '$LIBEMITTER',
  285. prefix = '$LIBPREFIX',
  286. suffix = '$LIBSUFFIX',
  287. src_suffix = '$OBJSUFFIX',
  288. src_builder = 'StaticObject')
  289. env['BUILDERS']['StaticLibrary'] = static_lib
  290. env['BUILDERS']['Library'] = static_lib
  291. return static_lib
  292. def _call_linker_cb(env, callback, args, result = None):
  293. """Returns the result of env['LINKCALLBACKS'][callback](*args)
  294. if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback]
  295. is callable. If these conditions are not met, return the value provided as
  296. the *result* argument. This function is mainly used for generating library
  297. info such as versioned suffixes, symlink maps, sonames etc. by delegating
  298. the core job to callbacks configured by current linker tool"""
  299. Verbose = False
  300. if Verbose:
  301. print('_call_linker_cb: args=%r' % args)
  302. print('_call_linker_cb: callback=%r' % callback)
  303. try:
  304. cbfun = env['LINKCALLBACKS'][callback]
  305. except (KeyError, TypeError):
  306. if Verbose:
  307. print('_call_linker_cb: env["LINKCALLBACKS"][%r] not found or can not be used' % callback)
  308. pass
  309. else:
  310. if Verbose:
  311. print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback)
  312. print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun))
  313. if(isinstance(cbfun, collections.Callable)):
  314. if Verbose:
  315. print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback)
  316. result = cbfun(env, *args)
  317. return result
  318. def _call_env_subst(env, string, *args, **kw):
  319. kw2 = {}
  320. for k in ('raw', 'target', 'source', 'conv', 'executor'):
  321. try: kw2[k] = kw[k]
  322. except KeyError: pass
  323. return env.subst(string, *args, **kw2)
  324. class _ShLibInfoSupport(object):
  325. def get_libtype(self):
  326. return 'ShLib'
  327. def get_lib_prefix(self, env, *args, **kw):
  328. return _call_env_subst(env,'$SHLIBPREFIX', *args, **kw)
  329. def get_lib_suffix(self, env, *args, **kw):
  330. return _call_env_subst(env,'$SHLIBSUFFIX', *args, **kw)
  331. def get_lib_version(self, env, *args, **kw):
  332. return _call_env_subst(env,'$SHLIBVERSION', *args, **kw)
  333. def get_lib_noversionsymlinks(self, env, *args, **kw):
  334. return _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw)
  335. class _LdModInfoSupport(object):
  336. def get_libtype(self):
  337. return 'LdMod'
  338. def get_lib_prefix(self, env, *args, **kw):
  339. return _call_env_subst(env,'$LDMODULEPREFIX', *args, **kw)
  340. def get_lib_suffix(self, env, *args, **kw):
  341. return _call_env_subst(env,'$LDMODULESUFFIX', *args, **kw)
  342. def get_lib_version(self, env, *args, **kw):
  343. return _call_env_subst(env,'$LDMODULEVERSION', *args, **kw)
  344. def get_lib_noversionsymlinks(self, env, *args, **kw):
  345. return _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw)
  346. class _ImpLibInfoSupport(object):
  347. def get_libtype(self):
  348. return 'ImpLib'
  349. def get_lib_prefix(self, env, *args, **kw):
  350. return _call_env_subst(env,'$IMPLIBPREFIX', *args, **kw)
  351. def get_lib_suffix(self, env, *args, **kw):
  352. return _call_env_subst(env,'$IMPLIBSUFFIX', *args, **kw)
  353. def get_lib_version(self, env, *args, **kw):
  354. version = _call_env_subst(env,'$IMPLIBVERSION', *args, **kw)
  355. if not version:
  356. try: lt = kw['implib_libtype']
  357. except KeyError: pass
  358. else:
  359. if lt == 'ShLib':
  360. version = _call_env_subst(env,'$SHLIBVERSION', *args, **kw)
  361. elif lt == 'LdMod':
  362. version = _call_env_subst(env,'$LDMODULEVERSION', *args, **kw)
  363. return version
  364. def get_lib_noversionsymlinks(self, env, *args, **kw):
  365. disable = None
  366. try: env['IMPLIBNOVERSIONSYMLINKS']
  367. except KeyError:
  368. try: lt = kw['implib_libtype']
  369. except KeyError: pass
  370. else:
  371. if lt == 'ShLib':
  372. disable = _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw)
  373. elif lt == 'LdMod':
  374. disable = _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw)
  375. else:
  376. disable = _call_env_subst(env,'$IMPLIBNOVERSIONSYMLINKS', *args, **kw)
  377. return disable
  378. class _LibInfoGeneratorBase(object):
  379. """Generator base class for library-related info such as suffixes for
  380. versioned libraries, symlink maps, sonames etc. It handles commonities
  381. of SharedLibrary and LoadableModule
  382. """
  383. _support_classes = { 'ShLib' : _ShLibInfoSupport,
  384. 'LdMod' : _LdModInfoSupport,
  385. 'ImpLib' : _ImpLibInfoSupport }
  386. def __init__(self, libtype, infoname):
  387. self.set_libtype(libtype)
  388. self.set_infoname(infoname)
  389. def set_libtype(self, libtype):
  390. try:
  391. support_class = self._support_classes[libtype]
  392. except KeyError:
  393. raise ValueError('unsupported libtype %r' % libtype)
  394. self._support = support_class()
  395. def get_libtype(self):
  396. return self._support.get_libtype()
  397. def set_infoname(self, infoname):
  398. self.infoname = infoname
  399. def get_infoname(self):
  400. return self.infoname
  401. def get_lib_prefix(self, env, *args, **kw):
  402. return self._support.get_lib_prefix(env,*args,**kw)
  403. def get_lib_suffix(self, env, *args, **kw):
  404. return self._support.get_lib_suffix(env,*args,**kw)
  405. def get_lib_version(self, env, *args, **kw):
  406. return self._support.get_lib_version(env,*args,**kw)
  407. def get_lib_noversionsymlinks(self, env, *args, **kw):
  408. return self._support.get_lib_noversionsymlinks(env,*args,**kw)
  409. # Returns name of generator linker callback that shall be used to generate
  410. # our info for a versioned library. For example, if our libtype is 'ShLib'
  411. # and infoname is 'Prefix', it would return 'VersionedShLibPrefix'.
  412. def get_versioned_lib_info_generator(self, **kw):
  413. try: libtype = kw['generator_libtype']
  414. except KeyError: libtype = self.get_libtype()
  415. infoname = self.get_infoname()
  416. return 'Versioned%s%s' % (libtype, infoname)
  417. def generate_versioned_lib_info(self, env, args, result = None, **kw):
  418. callback = self.get_versioned_lib_info_generator(**kw)
  419. return _call_linker_cb(env, callback, args, result)
  420. class _LibPrefixGenerator(_LibInfoGeneratorBase):
  421. """Library prefix generator, used as target_prefix in SharedLibrary and
  422. LoadableModule builders"""
  423. def __init__(self, libtype):
  424. super(_LibPrefixGenerator, self).__init__(libtype, 'Prefix')
  425. def __call__(self, env, sources = None, **kw):
  426. Verbose = False
  427. if sources and 'source' not in kw:
  428. kw2 = kw.copy()
  429. kw2['source'] = sources
  430. else:
  431. kw2 = kw
  432. prefix = self.get_lib_prefix(env,**kw2)
  433. if Verbose:
  434. print("_LibPrefixGenerator: input prefix=%r" % prefix)
  435. version = self.get_lib_version(env, **kw2)
  436. if Verbose:
  437. print("_LibPrefixGenerator: version=%r" % version)
  438. if version:
  439. prefix = self.generate_versioned_lib_info(env, [prefix, version], prefix, **kw2)
  440. if Verbose:
  441. print("_LibPrefixGenerator: return prefix=%r" % prefix)
  442. return prefix
  443. ShLibPrefixGenerator = _LibPrefixGenerator('ShLib')
  444. LdModPrefixGenerator = _LibPrefixGenerator('LdMod')
  445. ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib')
  446. class _LibSuffixGenerator(_LibInfoGeneratorBase):
  447. """Library suffix generator, used as target_suffix in SharedLibrary and
  448. LoadableModule builders"""
  449. def __init__(self, libtype):
  450. super(_LibSuffixGenerator, self).__init__(libtype, 'Suffix')
  451. def __call__(self, env, sources = None, **kw):
  452. Verbose = False
  453. if sources and 'source' not in kw:
  454. kw2 = kw.copy()
  455. kw2['source'] = sources
  456. else:
  457. kw2 = kw
  458. suffix = self.get_lib_suffix(env, **kw2)
  459. if Verbose:
  460. print("_LibSuffixGenerator: input suffix=%r" % suffix)
  461. version = self.get_lib_version(env, **kw2)
  462. if Verbose:
  463. print("_LibSuffixGenerator: version=%r" % version)
  464. if version:
  465. suffix = self.generate_versioned_lib_info(env, [suffix, version], suffix, **kw2)
  466. if Verbose:
  467. print("_LibSuffixGenerator: return suffix=%r" % suffix)
  468. return suffix
  469. ShLibSuffixGenerator = _LibSuffixGenerator('ShLib')
  470. LdModSuffixGenerator = _LibSuffixGenerator('LdMod')
  471. ImpLibSuffixGenerator = _LibSuffixGenerator('ImpLib')
  472. class _LibSymlinkGenerator(_LibInfoGeneratorBase):
  473. """Library symlink map generator. It generates a list of symlinks that
  474. should be created by SharedLibrary or LoadableModule builders"""
  475. def __init__(self, libtype):
  476. super(_LibSymlinkGenerator, self).__init__(libtype, 'Symlinks')
  477. def __call__(self, env, libnode, **kw):
  478. Verbose = False
  479. if libnode and 'target' not in kw:
  480. kw2 = kw.copy()
  481. kw2['target'] = libnode
  482. else:
  483. kw2 = kw
  484. if Verbose:
  485. print("_LibSymLinkGenerator: libnode=%r" % libnode.get_path())
  486. symlinks = None
  487. version = self.get_lib_version(env, **kw2)
  488. disable = self.get_lib_noversionsymlinks(env, **kw2)
  489. if Verbose:
  490. print('_LibSymlinkGenerator: version=%r' % version)
  491. print('_LibSymlinkGenerator: disable=%r' % disable)
  492. if version and not disable:
  493. prefix = self.get_lib_prefix(env,**kw2)
  494. suffix = self.get_lib_suffix(env,**kw2)
  495. symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)
  496. if Verbose:
  497. print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks))
  498. return symlinks
  499. ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib')
  500. LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod')
  501. ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib')
  502. class _LibNameGenerator(_LibInfoGeneratorBase):
  503. """Generates "unmangled" library name from a library file node.
  504. Generally, it's thought to revert modifications done by prefix/suffix
  505. generators (_LibPrefixGenerator/_LibSuffixGenerator) used by a library
  506. builder. For example, on gnulink the suffix generator used by SharedLibrary
  507. builder appends $SHLIBVERSION to $SHLIBSUFFIX producing node name which
  508. ends with "$SHLIBSUFFIX.$SHLIBVERSION". Correspondingly, the implementation
  509. of _LibNameGenerator replaces "$SHLIBSUFFIX.$SHLIBVERSION" with
  510. "$SHLIBSUFFIX" in the node's basename. So that, if $SHLIBSUFFIX is ".so",
  511. $SHLIBVERSION is "0.1.2" and the node path is "/foo/bar/libfoo.so.0.1.2",
  512. the _LibNameGenerator shall return "libfoo.so". Other link tools may
  513. implement it's own way of library name unmangling.
  514. """
  515. def __init__(self, libtype):
  516. super(_LibNameGenerator, self).__init__(libtype, 'Name')
  517. def __call__(self, env, libnode, **kw):
  518. """Returns "demangled" library name"""
  519. Verbose = False
  520. if libnode and 'target' not in kw:
  521. kw2 = kw.copy()
  522. kw2['target'] = libnode
  523. else:
  524. kw2 = kw
  525. if Verbose:
  526. print("_LibNameGenerator: libnode=%r" % libnode.get_path())
  527. version = self.get_lib_version(env, **kw2)
  528. if Verbose:
  529. print('_LibNameGenerator: version=%r' % version)
  530. name = None
  531. if version:
  532. prefix = self.get_lib_prefix(env,**kw2)
  533. suffix = self.get_lib_suffix(env,**kw2)
  534. name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)
  535. if not name:
  536. name = os.path.basename(libnode.get_path())
  537. if Verbose:
  538. print('_LibNameGenerator: return name=%r' % name)
  539. return name
  540. ShLibNameGenerator = _LibNameGenerator('ShLib')
  541. LdModNameGenerator = _LibNameGenerator('LdMod')
  542. ImpLibNameGenerator = _LibNameGenerator('ImpLib')
  543. class _LibSonameGenerator(_LibInfoGeneratorBase):
  544. """Library soname generator. Returns library soname (e.g. libfoo.so.0) for
  545. a given node (e.g. /foo/bar/libfoo.so.0.1.2)"""
  546. def __init__(self, libtype):
  547. super(_LibSonameGenerator, self).__init__(libtype, 'Soname')
  548. def __call__(self, env, libnode, **kw):
  549. """Returns a SONAME based on a shared library's node path"""
  550. Verbose = False
  551. if libnode and 'target' not in kw:
  552. kw2 = kw.copy()
  553. kw2['target'] = libnode
  554. else:
  555. kw2 = kw
  556. if Verbose:
  557. print("_LibSonameGenerator: libnode=%r" % libnode.get_path())
  558. soname = _call_env_subst(env, '$SONAME', **kw2)
  559. if not soname:
  560. version = self.get_lib_version(env,**kw2)
  561. if Verbose:
  562. print("_LibSonameGenerator: version=%r" % version)
  563. if version:
  564. prefix = self.get_lib_prefix(env,**kw2)
  565. suffix = self.get_lib_suffix(env,**kw2)
  566. soname = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2)
  567. if not soname:
  568. # fallback to library name (as returned by appropriate _LibNameGenerator)
  569. soname = _LibNameGenerator(self.get_libtype())(env, libnode)
  570. if Verbose:
  571. print("_LibSonameGenerator: FALLBACK: soname=%r" % soname)
  572. if Verbose:
  573. print("_LibSonameGenerator: return soname=%r" % soname)
  574. return soname
  575. ShLibSonameGenerator = _LibSonameGenerator('ShLib')
  576. LdModSonameGenerator = _LibSonameGenerator('LdMod')
  577. def StringizeLibSymlinks(symlinks):
  578. """Converts list with pairs of nodes to list with pairs of node paths
  579. (strings). Used mainly for debugging."""
  580. if SCons.Util.is_List(symlinks):
  581. try:
  582. return [ (k.get_path(), v.get_path()) for k,v in symlinks ]
  583. except (TypeError, ValueError):
  584. return symlinks
  585. else:
  586. return symlinks
  587. def EmitLibSymlinks(env, symlinks, libnode, **kw):
  588. """Used by emitters to handle (shared/versioned) library symlinks"""
  589. Verbose = False
  590. # nodes involved in process... all symlinks + library
  591. nodes = list(set([ x for x,y in symlinks ] + [libnode]))
  592. clean_targets = kw.get('clean_targets', [])
  593. if not SCons.Util.is_List(clean_targets):
  594. clean_targets = [ clean_targets ]
  595. for link, linktgt in symlinks:
  596. env.SideEffect(link, linktgt)
  597. if(Verbose):
  598. print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path()))
  599. clean_list = [x for x in nodes if x != linktgt]
  600. env.Clean(list(set([linktgt] + clean_targets)), clean_list)
  601. if(Verbose):
  602. print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list]))
  603. def CreateLibSymlinks(env, symlinks):
  604. """Physically creates symlinks. The symlinks argument must be a list in
  605. form [ (link, linktarget), ... ], where link and linktarget are SCons
  606. nodes.
  607. """
  608. Verbose = False
  609. for link, linktgt in symlinks:
  610. linktgt = link.get_dir().rel_path(linktgt)
  611. link = link.get_path()
  612. if(Verbose):
  613. print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt))
  614. # Delete the (previously created) symlink if exists. Let only symlinks
  615. # to be deleted to prevent accidental deletion of source files...
  616. if env.fs.islink(link):
  617. env.fs.unlink(link)
  618. if(Verbose):
  619. print("CreateLibSymlinks: removed old symlink %r" % link)
  620. # If a file or directory exists with the same name as link, an OSError
  621. # will be thrown, which should be enough, I think.
  622. env.fs.symlink(linktgt, link)
  623. if(Verbose):
  624. print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt))
  625. return 0
  626. def LibSymlinksActionFunction(target, source, env):
  627. for tgt in target:
  628. symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None)
  629. if symlinks:
  630. CreateLibSymlinks(env, symlinks)
  631. return 0
  632. def LibSymlinksStrFun(target, source, env, *args):
  633. cmd = None
  634. for tgt in target:
  635. symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None)
  636. if symlinks:
  637. if cmd is None: cmd = ""
  638. if cmd: cmd += "\n"
  639. cmd += "Create symlinks for: %r" % tgt.get_path()
  640. try:
  641. linkstr = ', '.join([ "%r->%r" %(k,v) for k,v in StringizeLibSymlinks(symlinks)])
  642. except (KeyError, ValueError):
  643. pass
  644. else:
  645. cmd += ": %s" % linkstr
  646. return cmd
  647. LibSymlinksAction = SCons.Action.Action(LibSymlinksActionFunction, LibSymlinksStrFun)
  648. def createSharedLibBuilder(env):
  649. """This is a utility function that creates the SharedLibrary
  650. Builder in an Environment if it is not there already.
  651. If it is already there, we return the existing one.
  652. """
  653. try:
  654. shared_lib = env['BUILDERS']['SharedLibrary']
  655. except KeyError:
  656. import SCons.Defaults
  657. action_list = [ SCons.Defaults.SharedCheck,
  658. SCons.Defaults.ShLinkAction,
  659. LibSymlinksAction ]
  660. shared_lib = SCons.Builder.Builder(action = action_list,
  661. emitter = "$SHLIBEMITTER",
  662. prefix = ShLibPrefixGenerator,
  663. suffix = ShLibSuffixGenerator,
  664. target_scanner = ProgramScanner,
  665. src_suffix = '$SHOBJSUFFIX',
  666. src_builder = 'SharedObject')
  667. env['BUILDERS']['SharedLibrary'] = shared_lib
  668. return shared_lib
  669. def createLoadableModuleBuilder(env):
  670. """This is a utility function that creates the LoadableModule
  671. Builder in an Environment if it is not there already.
  672. If it is already there, we return the existing one.
  673. """
  674. try:
  675. ld_module = env['BUILDERS']['LoadableModule']
  676. except KeyError:
  677. import SCons.Defaults
  678. action_list = [ SCons.Defaults.SharedCheck,
  679. SCons.Defaults.LdModuleLinkAction,
  680. LibSymlinksAction ]
  681. ld_module = SCons.Builder.Builder(action = action_list,
  682. emitter = "$LDMODULEEMITTER",
  683. prefix = LdModPrefixGenerator,
  684. suffix = LdModSuffixGenerator,
  685. target_scanner = ProgramScanner,
  686. src_suffix = '$SHOBJSUFFIX',
  687. src_builder = 'SharedObject')
  688. env['BUILDERS']['LoadableModule'] = ld_module
  689. return ld_module
  690. def createObjBuilders(env):
  691. """This is a utility function that creates the StaticObject
  692. and SharedObject Builders in an Environment if they
  693. are not there already.
  694. If they are there already, we return the existing ones.
  695. This is a separate function because soooo many Tools
  696. use this functionality.
  697. The return is a 2-tuple of (StaticObject, SharedObject)
  698. """
  699. try:
  700. static_obj = env['BUILDERS']['StaticObject']
  701. except KeyError:
  702. static_obj = SCons.Builder.Builder(action = {},
  703. emitter = {},
  704. prefix = '$OBJPREFIX',
  705. suffix = '$OBJSUFFIX',
  706. src_builder = ['CFile', 'CXXFile'],
  707. source_scanner = SourceFileScanner,
  708. single_source = 1)
  709. env['BUILDERS']['StaticObject'] = static_obj
  710. env['BUILDERS']['Object'] = static_obj
  711. try:
  712. shared_obj = env['BUILDERS']['SharedObject']
  713. except KeyError:
  714. shared_obj = SCons.Builder.Builder(action = {},
  715. emitter = {},
  716. prefix = '$SHOBJPREFIX',
  717. suffix = '$SHOBJSUFFIX',
  718. src_builder = ['CFile', 'CXXFile'],
  719. source_scanner = SourceFileScanner,
  720. single_source = 1)
  721. env['BUILDERS']['SharedObject'] = shared_obj
  722. return (static_obj, shared_obj)
  723. def createCFileBuilders(env):
  724. """This is a utility function that creates the CFile/CXXFile
  725. Builders in an Environment if they
  726. are not there already.
  727. If they are there already, we return the existing ones.
  728. This is a separate function because soooo many Tools
  729. use this functionality.
  730. The return is a 2-tuple of (CFile, CXXFile)
  731. """
  732. try:
  733. c_file = env['BUILDERS']['CFile']
  734. except KeyError:
  735. c_file = SCons.Builder.Builder(action = {},
  736. emitter = {},
  737. suffix = {None:'$CFILESUFFIX'})
  738. env['BUILDERS']['CFile'] = c_file
  739. env.SetDefault(CFILESUFFIX = '.c')
  740. try:
  741. cxx_file = env['BUILDERS']['CXXFile']
  742. except KeyError:
  743. cxx_file = SCons.Builder.Builder(action = {},
  744. emitter = {},
  745. suffix = {None:'$CXXFILESUFFIX'})
  746. env['BUILDERS']['CXXFile'] = cxx_file
  747. env.SetDefault(CXXFILESUFFIX = '.cc')
  748. return (c_file, cxx_file)
  749. ##########################################################################
  750. # Create common Java builders
  751. def CreateJarBuilder(env):
  752. try:
  753. java_jar = env['BUILDERS']['Jar']
  754. except KeyError:
  755. fs = SCons.Node.FS.get_default_fs()
  756. jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR')
  757. java_jar = SCons.Builder.Builder(action = jar_com,
  758. suffix = '$JARSUFFIX',
  759. src_suffix = '$JAVACLASSSUFFIX',
  760. src_builder = 'JavaClassFile',
  761. source_factory = fs.Entry)
  762. env['BUILDERS']['Jar'] = java_jar
  763. return java_jar
  764. def CreateJavaHBuilder(env):
  765. try:
  766. java_javah = env['BUILDERS']['JavaH']
  767. except KeyError:
  768. fs = SCons.Node.FS.get_default_fs()
  769. java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR')
  770. java_javah = SCons.Builder.Builder(action = java_javah_com,
  771. src_suffix = '$JAVACLASSSUFFIX',
  772. target_factory = fs.Entry,
  773. source_factory = fs.File,
  774. src_builder = 'JavaClassFile')
  775. env['BUILDERS']['JavaH'] = java_javah
  776. return java_javah
  777. def CreateJavaClassFileBuilder(env):
  778. try:
  779. java_class_file = env['BUILDERS']['JavaClassFile']
  780. except KeyError:
  781. fs = SCons.Node.FS.get_default_fs()
  782. javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
  783. java_class_file = SCons.Builder.Builder(action = javac_com,
  784. emitter = {},
  785. #suffix = '$JAVACLASSSUFFIX',
  786. src_suffix = '$JAVASUFFIX',
  787. src_builder = ['JavaFile'],
  788. target_factory = fs.Entry,
  789. source_factory = fs.File)
  790. env['BUILDERS']['JavaClassFile'] = java_class_file
  791. return java_class_file
  792. def CreateJavaClassDirBuilder(env):
  793. try:
  794. java_class_dir = env['BUILDERS']['JavaClassDir']
  795. except KeyError:
  796. fs = SCons.Node.FS.get_default_fs()
  797. javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
  798. java_class_dir = SCons.Builder.Builder(action = javac_com,
  799. emitter = {},
  800. target_factory = fs.Dir,
  801. source_factory = fs.Dir)
  802. env['BUILDERS']['JavaClassDir'] = java_class_dir
  803. return java_class_dir
  804. def CreateJavaFileBuilder(env):
  805. try:
  806. java_file = env['BUILDERS']['JavaFile']
  807. except KeyError:
  808. java_file = SCons.Builder.Builder(action = {},
  809. emitter = {},
  810. suffix = {None:'$JAVASUFFIX'})
  811. env['BUILDERS']['JavaFile'] = java_file
  812. env['JAVASUFFIX'] = '.java'
  813. return java_file
  814. class ToolInitializerMethod(object):
  815. """
  816. This is added to a construction environment in place of a
  817. method(s) normally called for a Builder (env.Object, env.StaticObject,
  818. etc.). When called, it has its associated ToolInitializer
  819. object search the specified list of tools and apply the first
  820. one that exists to the construction environment. It then calls
  821. whatever builder was (presumably) added to the construction
  822. environment in place of this particular instance.
  823. """
  824. def __init__(self, name, initializer):
  825. """
  826. Note: we store the tool name as __name__ so it can be used by
  827. the class that attaches this to a construction environment.
  828. """
  829. self.__name__ = name
  830. self.initializer = initializer
  831. def get_builder(self, env):
  832. """
  833. Returns the appropriate real Builder for this method name
  834. after having the associated ToolInitializer object apply
  835. the appropriate Tool module.
  836. """
  837. builder = getattr(env, self.__name__)
  838. self.initializer.apply_tools(env)
  839. builder = getattr(env, self.__name__)
  840. if builder is self:
  841. # There was no Builder added, which means no valid Tool
  842. # for this name was found (or possibly there's a mismatch
  843. # between the name we were called by and the Builder name
  844. # added by the Tool module).
  845. return None
  846. self.initializer.remove_methods(env)
  847. return builder
  848. def __call__(self, env, *args, **kw):
  849. """
  850. """
  851. builder = self.get_builder(env)
  852. if builder is None:
  853. return [], []
  854. return builder(*args, **kw)
  855. class ToolInitializer(object):
  856. """
  857. A class for delayed initialization of Tools modules.
  858. Instances of this class associate a list of Tool modules with
  859. a list of Builder method names that will be added by those Tool
  860. modules. As part of instantiating this object for a particular
  861. construction environment, we also add the appropriate
  862. ToolInitializerMethod objects for the various Builder methods
  863. that we want to use to delay Tool searches until necessary.
  864. """
  865. def __init__(self, env, tools, names):
  866. if not SCons.Util.is_List(tools):
  867. tools = [tools]
  868. if not SCons.Util.is_List(names):
  869. names = [names]
  870. self.env = env
  871. self.tools = tools
  872. self.names = names
  873. self.methods = {}
  874. for name in names:
  875. method = ToolInitializerMethod(name, self)
  876. self.methods[name] = method
  877. env.AddMethod(method)
  878. def remove_methods(self, env):
  879. """
  880. Removes the methods that were added by the tool initialization
  881. so we no longer copy and re-bind them when the construction
  882. environment gets cloned.
  883. """
  884. for method in list(self.methods.values()):
  885. env.RemoveMethod(method)
  886. def apply_tools(self, env):
  887. """
  888. Searches the list of associated Tool modules for one that
  889. exists, and applies that to the construction environment.
  890. """
  891. for t in self.tools:
  892. tool = SCons.Tool.Tool(t)
  893. if tool.exists(env):
  894. env.Tool(tool)
  895. return
  896. # If we fall through here, there was no tool module found.
  897. # This is where we can put an informative error message
  898. # about the inability to find the tool. We'll start doing
  899. # this as we cut over more pre-defined Builder+Tools to use
  900. # the ToolInitializer class.
  901. def Initializers(env):
  902. ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs', '_InternalInstallVersionedLib'])
  903. def Install(self, *args, **kw):
  904. return self._InternalInstall(*args, **kw)
  905. def InstallAs(self, *args, **kw):
  906. return self._InternalInstallAs(*args, **kw)
  907. def InstallVersionedLib(self, *args, **kw):
  908. return self._InternalInstallVersionedLib(*args, **kw)
  909. env.AddMethod(Install)
  910. env.AddMethod(InstallAs)
  911. env.AddMethod(InstallVersionedLib)
  912. def FindTool(tools, env):
  913. for tool in tools:
  914. t = Tool(tool)
  915. if t.exists(env):
  916. return tool
  917. return None
  918. def FindAllTools(tools, env):
  919. def ToolExists(tool, env=env):
  920. return Tool(tool).exists(env)
  921. return list(filter (ToolExists, tools))
  922. def tool_list(platform, env):
  923. other_plat_tools=[]
  924. # XXX this logic about what tool to prefer on which platform
  925. # should be moved into either the platform files or
  926. # the tool files themselves.
  927. # The search orders here are described in the man page. If you
  928. # change these search orders, update the man page as well.
  929. if str(platform) == 'win32':
  930. "prefer Microsoft tools on Windows"
  931. linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ]
  932. c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ]
  933. cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32' ]
  934. assemblers = ['masm', 'nasm', 'gas', '386asm' ]
  935. fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
  936. ars = ['mslib', 'ar', 'tlib']
  937. other_plat_tools = ['msvs', 'midl']
  938. elif str(platform) == 'os2':
  939. "prefer IBM tools on OS/2"
  940. linkers = ['ilink', 'gnulink', ]#'mslink']
  941. c_compilers = ['icc', 'gcc',]# 'msvc', 'cc']
  942. cxx_compilers = ['icc', 'g++',]# 'msvc', 'cxx']
  943. assemblers = ['nasm',]# 'masm', 'gas']
  944. fortran_compilers = ['ifl', 'g77']
  945. ars = ['ar',]# 'mslib']
  946. elif str(platform) == 'irix':
  947. "prefer MIPSPro on IRIX"
  948. linkers = ['sgilink', 'gnulink']
  949. c_compilers = ['sgicc', 'gcc', 'cc']
  950. cxx_compilers = ['sgicxx', 'g++', 'cxx']
  951. assemblers = ['as', 'gas']
  952. fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
  953. ars = ['sgiar']
  954. elif str(platform) == 'sunos':
  955. "prefer Forte tools on SunOS"
  956. linkers = ['sunlink', 'gnulink']
  957. c_compilers = ['suncc', 'gcc', 'cc']
  958. cxx_compilers = ['suncxx', 'g++', 'cxx']
  959. assemblers = ['as', 'gas']
  960. fortran_compilers = ['sunf95', 'sunf90', 'sunf77', 'f95', 'f90', 'f77',
  961. 'gfortran', 'g77', 'fortran']
  962. ars = ['sunar']
  963. elif str(platform) == 'hpux':
  964. "prefer aCC tools on HP-UX"
  965. linkers = ['hplink', 'gnulink']
  966. c_compilers = ['hpcc', 'gcc', 'cc']
  967. cxx_compilers = ['hpcxx', 'g++', 'cxx']
  968. assemblers = ['as', 'gas']
  969. fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran']
  970. ars = ['ar']
  971. elif str(platform) == 'aix':
  972. "prefer AIX Visual Age tools on AIX"
  973. linkers = ['aixlink', 'gnulink']
  974. c_compilers = ['aixcc', 'gcc', 'cc']
  975. cxx_compilers = ['aixcxx', 'g++', 'cxx']
  976. assemblers = ['as', 'gas']
  977. fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran']
  978. ars = ['ar']
  979. elif str(platform) == 'darwin':
  980. "prefer GNU tools on Mac OS X, except for some linkers and IBM tools"
  981. linkers = ['applelink', 'gnulink']
  982. c_compilers = ['gcc', 'cc']
  983. cxx_compilers = ['g++', 'cxx']
  984. assemblers = ['as']
  985. fortran_compilers = ['gfortran', 'f95', 'f90', 'g77']
  986. ars = ['ar']
  987. elif str(platform) == 'cygwin':
  988. "prefer GNU tools on Cygwin, except for a platform-specific linker"
  989. linkers = ['cyglink', 'mslink', 'ilink']
  990. c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc']
  991. cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'cxx']
  992. assemblers = ['gas', 'nasm', 'masm']
  993. fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77']
  994. ars = ['ar', 'mslib']
  995. else:
  996. "prefer GNU tools on all other platforms"
  997. linkers = ['gnulink', 'ilink']
  998. c_compilers = ['gcc', 'intelc', 'icc', 'cc']
  999. cxx_compilers = ['g++', 'intelc', 'icc', 'cxx']
  1000. assemblers = ['gas', 'nasm', 'masm']
  1001. fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77']
  1002. ars = ['ar',]
  1003. if not str(platform) == 'win32':
  1004. other_plat_tools += ['m4', 'rpm']
  1005. c_compiler = FindTool(c_compilers, env) or c_compilers[0]
  1006. # XXX this logic about what tool provides what should somehow be
  1007. # moved into the tool files themselves.
  1008. if c_compiler and c_compiler == 'mingw':
  1009. # MinGW contains a linker, C compiler, C++ compiler,
  1010. # Fortran compiler, archiver and assembler:
  1011. cxx_compiler = None
  1012. linker = None
  1013. assembler = None
  1014. fortran_compiler = None
  1015. ar = None
  1016. else:
  1017. # Don't use g++ if the C compiler has built-in C++ support:
  1018. if c_compiler in ('msvc', 'intelc', 'icc'):
  1019. cxx_compiler = None
  1020. else:
  1021. cxx_compiler = FindTool(cxx_compilers, env) or cxx_compilers[0]
  1022. linker = FindTool(linkers, env) or linkers[0]
  1023. assembler = FindTool(assemblers, env) or assemblers[0]
  1024. fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0]
  1025. ar = FindTool(ars, env) or ars[0]
  1026. d_compilers = ['dmd', 'ldc', 'gdc']
  1027. d_compiler = FindTool(d_compilers, env) or d_compilers[0]
  1028. other_tools = FindAllTools(other_plat_tools + [
  1029. #TODO: merge 'install' into 'filesystem' and
  1030. # make 'filesystem' the default
  1031. 'filesystem',
  1032. 'wix', #'midl', 'msvs',
  1033. # Parser generators
  1034. 'lex', 'yacc',
  1035. # Foreign function interface
  1036. 'rpcgen', 'swig',
  1037. # Java
  1038. 'jar', 'javac', 'javah', 'rmic',
  1039. # TeX
  1040. 'dvipdf', 'dvips', 'gs',
  1041. 'tex', 'latex', 'pdflatex', 'pdftex',
  1042. # Archivers
  1043. 'tar', 'zip',
  1044. ], env)
  1045. tools = ([linker, c_compiler, cxx_compiler,
  1046. fortran_compiler, assembler, ar, d_compiler]
  1047. + other_tools)
  1048. return [x for x in tools if x]
  1049. # Local Variables:
  1050. # tab-width:4
  1051. # indent-tabs-mode:nil
  1052. # End:
  1053. # vim: set expandtab tabstop=4 shiftwidth=4: