PageRenderTime 32ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/Miranda IM - CK Release/Miranda/boost/tools/build/v2/tools/gcc.py

http://miranda-dev.googlecode.com/
Python | 800 lines | 614 code | 48 blank | 138 comment | 29 complexity | cd627c2dbc34a8d2da43ffd7cbc36d42 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, BSD-3-Clause, LGPL-2.1
  1. # Status: being ported by Steven Watanabe
  2. # Base revision: 47077
  3. # TODO: common.jam needs to be ported
  4. # TODO: generators.jam needs to have register_c_compiler.
  5. #
  6. # Copyright 2001 David Abrahams.
  7. # Copyright 2002-2006 Rene Rivera.
  8. # Copyright 2002-2003 Vladimir Prus.
  9. # Copyright (c) 2005 Reece H. Dunn.
  10. # Copyright 2006 Ilya Sokolov.
  11. # Copyright 2007 Roland Schwarz
  12. # Copyright 2007 Boris Gubenko.
  13. # Copyright 2008 Steven Watanabe
  14. #
  15. # Distributed under the Boost Software License, Version 1.0.
  16. # (See accompanying file LICENSE_1_0.txt or copy at
  17. # http://www.boost.org/LICENSE_1_0.txt)
  18. import os
  19. import subprocess
  20. import re
  21. import bjam
  22. from b2.tools import unix, common, rc, pch, builtin
  23. from b2.build import feature, type, toolset, generators, property_set
  24. from b2.build.property import Property
  25. from b2.util.utility import os_name, on_windows
  26. from b2.manager import get_manager
  27. from b2.build.generators import Generator
  28. from b2.build.toolset import flags
  29. from b2.util.utility import to_seq
  30. __debug = None
  31. def debug():
  32. global __debug
  33. if __debug is None:
  34. __debug = "--debug-configuration" in bjam.variable("ARGV")
  35. return __debug
  36. feature.extend('toolset', ['gcc'])
  37. toolset.inherit_generators('gcc', [], 'unix', ['unix.link', 'unix.link.dll'])
  38. toolset.inherit_flags('gcc', 'unix')
  39. toolset.inherit_rules('gcc', 'unix')
  40. generators.override('gcc.prebuilt', 'builtin.prebuilt')
  41. generators.override('gcc.searched-lib-generator', 'searched-lib-generator')
  42. # Target naming is determined by types/lib.jam and the settings below this
  43. # comment.
  44. #
  45. # On *nix:
  46. # libxxx.a static library
  47. # libxxx.so shared library
  48. #
  49. # On windows (mingw):
  50. # libxxx.lib static library
  51. # xxx.dll DLL
  52. # xxx.lib import library
  53. #
  54. # On windows (cygwin) i.e. <target-os>cygwin
  55. # libxxx.a static library
  56. # xxx.dll DLL
  57. # libxxx.dll.a import library
  58. #
  59. # Note: user can always override by using the <tag>@rule
  60. # This settings have been choosen, so that mingw
  61. # is in line with msvc naming conventions. For
  62. # cygwin the cygwin naming convention has been choosen.
  63. # Make the "o" suffix used for gcc toolset on all
  64. # platforms
  65. type.set_generated_target_suffix('OBJ', ['<toolset>gcc'], 'o')
  66. type.set_generated_target_suffix('STATIC_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'a')
  67. type.set_generated_target_suffix('IMPORT_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'dll.a')
  68. type.set_generated_target_prefix('IMPORT_LIB', ['<toolset>gcc', '<target-os>cygwin'], 'lib')
  69. __machine_match = re.compile('^([^ ]+)')
  70. __version_match = re.compile('^([0-9.]+)')
  71. def init(version = None, command = None, options = None):
  72. """
  73. Initializes the gcc toolset for the given version. If necessary, command may
  74. be used to specify where the compiler is located. The parameter 'options' is a
  75. space-delimited list of options, each one specified as
  76. <option-name>option-value. Valid option names are: cxxflags, linkflags and
  77. linker-type. Accepted linker-type values are gnu, darwin, osf, hpux or sun
  78. and the default value will be selected based on the current OS.
  79. Example:
  80. using gcc : 3.4 : : <cxxflags>foo <linkflags>bar <linker-type>sun ;
  81. """
  82. options = to_seq(options)
  83. command = to_seq(command)
  84. # Information about the gcc command...
  85. # The command.
  86. command = to_seq(common.get_invocation_command('gcc', 'g++', command))
  87. # The root directory of the tool install.
  88. root = feature.get_values('<root>', options) ;
  89. # The bin directory where to find the command to execute.
  90. bin = None
  91. # The flavor of compiler.
  92. flavor = feature.get_values('<flavor>', options)
  93. # Autodetect the root and bin dir if not given.
  94. if command:
  95. if not bin:
  96. bin = common.get_absolute_tool_path(command[-1])
  97. if not root:
  98. root = os.path.dirname(bin)
  99. # Autodetect the version and flavor if not given.
  100. if command:
  101. machine_info = subprocess.Popen(command + ['-dumpmachine'], stdout=subprocess.PIPE).communicate()[0]
  102. machine = __machine_match.search(machine_info).group(1)
  103. version_info = subprocess.Popen(command + ['-dumpversion'], stdout=subprocess.PIPE).communicate()[0]
  104. version = __version_match.search(version_info).group(1)
  105. if not flavor and machine.find('mingw') != -1:
  106. flavor = 'mingw'
  107. condition = None
  108. if flavor:
  109. condition = common.check_init_parameters('gcc', None,
  110. ('version', version),
  111. ('flavor', flavor))
  112. else:
  113. condition = common.check_init_parameters('gcc', None,
  114. ('version', version))
  115. if command:
  116. command = command[0]
  117. common.handle_options('gcc', condition, command, options)
  118. linker = feature.get_values('<linker-type>', options)
  119. if not linker:
  120. if os_name() == 'OSF':
  121. linker = 'osf'
  122. elif os_name() == 'HPUX':
  123. linker = 'hpux' ;
  124. else:
  125. linker = 'gnu'
  126. init_link_flags('gcc', linker, condition)
  127. # If gcc is installed in non-standard location, we'd need to add
  128. # LD_LIBRARY_PATH when running programs created with it (for unit-test/run
  129. # rules).
  130. if command:
  131. # On multilib 64-bit boxes, there are both 32-bit and 64-bit libraries
  132. # and all must be added to LD_LIBRARY_PATH. The linker will pick the
  133. # right onces. Note that we don't provide a clean way to build 32-bit
  134. # binary with 64-bit compiler, but user can always pass -m32 manually.
  135. lib_path = [os.path.join(root, 'bin'),
  136. os.path.join(root, 'lib'),
  137. os.path.join(root, 'lib32'),
  138. os.path.join(root, 'lib64')]
  139. if debug():
  140. print 'notice: using gcc libraries ::', condition, '::', lib_path
  141. toolset.flags('gcc.link', 'RUN_PATH', condition, lib_path)
  142. # If it's not a system gcc install we should adjust the various programs as
  143. # needed to prefer using the install specific versions. This is essential
  144. # for correct use of MinGW and for cross-compiling.
  145. # - The archive builder.
  146. archiver = common.get_invocation_command('gcc',
  147. 'ar', feature.get_values('<archiver>', options), [bin], path_last=True)
  148. toolset.flags('gcc.archive', '.AR', condition, [archiver])
  149. if debug():
  150. print 'notice: using gcc archiver ::', condition, '::', archiver
  151. # - The resource compiler.
  152. rc_command = common.get_invocation_command_nodefault('gcc',
  153. 'windres', feature.get_values('<rc>', options), [bin], path_last=True)
  154. rc_type = feature.get_values('<rc-type>', options)
  155. if not rc_type:
  156. rc_type = 'windres'
  157. if not rc_command:
  158. # If we can't find an RC compiler we fallback to a null RC compiler that
  159. # creates empty object files. This allows the same Jamfiles to work
  160. # across the board. The null RC uses the assembler to create the empty
  161. # objects, so configure that.
  162. rc_command = common.get_invocation_command('gcc', 'as', [], [bin], path_last=True)
  163. rc_type = 'null'
  164. rc.configure(rc_command, condition, '<rc-type>' + rc_type)
  165. ###if [ os.name ] = NT
  166. ###{
  167. ### # This causes single-line command invocation to not go through .bat files,
  168. ### # thus avoiding command-line length limitations.
  169. ### JAMSHELL = % ;
  170. ###}
  171. #FIXME: when register_c_compiler is moved to
  172. # generators, these should be updated
  173. builtin.register_c_compiler('gcc.compile.c++', ['CPP'], ['OBJ'], ['<toolset>gcc'])
  174. builtin.register_c_compiler('gcc.compile.c', ['C'], ['OBJ'], ['<toolset>gcc'])
  175. builtin.register_c_compiler('gcc.compile.asm', ['ASM'], ['OBJ'], ['<toolset>gcc'])
  176. # pch support
  177. # The compiler looks for a precompiled header in each directory just before it
  178. # looks for the include file in that directory. The name searched for is the
  179. # name specified in the #include directive with ".gch" suffix appended. The
  180. # logic in gcc-pch-generator will make sure that BASE_PCH suffix is appended to
  181. # full name of the header.
  182. type.set_generated_target_suffix('PCH', ['<toolset>gcc'], 'gch')
  183. # GCC-specific pch generator.
  184. class GccPchGenerator(pch.PchGenerator):
  185. # Inherit the __init__ method
  186. def run_pch(self, project, name, prop_set, sources):
  187. # Find the header in sources. Ignore any CPP sources.
  188. header = None
  189. for s in sources:
  190. if type.is_derived(s.type(), 'H'):
  191. header = s
  192. # Error handling: Base header file name should be the same as the base
  193. # precompiled header name.
  194. header_name = header.name()
  195. header_basename = os.path.basename(header_name).rsplit('.', 1)[0]
  196. if header_basename != name:
  197. location = project.project_module
  198. ###FIXME:
  199. raise Exception()
  200. ### errors.user-error "in" $(location)": pch target name `"$(name)"' should be the same as the base name of header file `"$(header-name)"'" ;
  201. pch_file = Generator.run(self, project, name, prop_set, [header])
  202. # return result of base class and pch-file property as usage-requirements
  203. # FIXME: what about multiple results from generator.run?
  204. return (property_set.create([Property('pch-file', pch_file[0]),
  205. Property('cflags', '-Winvalid-pch')]),
  206. pch_file)
  207. # Calls the base version specifying source's name as the name of the created
  208. # target. As result, the PCH will be named whatever.hpp.gch, and not
  209. # whatever.gch.
  210. def generated_targets(self, sources, prop_set, project, name = None):
  211. name = sources[0].name()
  212. return Generator.generated_targets(self, sources,
  213. prop_set, project, name)
  214. # Note: the 'H' source type will catch both '.h' header and '.hpp' header. The
  215. # latter have HPP type, but HPP type is derived from H. The type of compilation
  216. # is determined entirely by the destination type.
  217. generators.register(GccPchGenerator('gcc.compile.c.pch', False, ['H'], ['C_PCH'], ['<pch>on', '<toolset>gcc' ]))
  218. generators.register(GccPchGenerator('gcc.compile.c++.pch', False, ['H'], ['CPP_PCH'], ['<pch>on', '<toolset>gcc' ]))
  219. # Override default do-nothing generators.
  220. generators.override('gcc.compile.c.pch', 'pch.default-c-pch-generator')
  221. generators.override('gcc.compile.c++.pch', 'pch.default-cpp-pch-generator')
  222. flags('gcc.compile', 'PCH_FILE', ['<pch>on'], ['<pch-file>'])
  223. # Declare flags and action for compilation
  224. flags('gcc.compile', 'OPTIONS', ['<optimization>off'], ['-O0'])
  225. flags('gcc.compile', 'OPTIONS', ['<optimization>speed'], ['-O3'])
  226. flags('gcc.compile', 'OPTIONS', ['<optimization>space'], ['-Os'])
  227. flags('gcc.compile', 'OPTIONS', ['<inlining>off'], ['-fno-inline'])
  228. flags('gcc.compile', 'OPTIONS', ['<inlining>on'], ['-Wno-inline'])
  229. flags('gcc.compile', 'OPTIONS', ['<inlining>full'], ['-finline-functions', '-Wno-inline'])
  230. flags('gcc.compile', 'OPTIONS', ['<warnings>off'], ['-w'])
  231. flags('gcc.compile', 'OPTIONS', ['<warnings>on'], ['-Wall'])
  232. flags('gcc.compile', 'OPTIONS', ['<warnings>all'], ['-Wall', '-pedantic'])
  233. flags('gcc.compile', 'OPTIONS', ['<warnings-as-errors>on'], ['-Werror'])
  234. flags('gcc.compile', 'OPTIONS', ['<debug-symbols>on'], ['-g'])
  235. flags('gcc.compile', 'OPTIONS', ['<profiling>on'], ['-pg'])
  236. flags('gcc.compile', 'OPTIONS', ['<rtti>off'], ['-fno-rtti'])
  237. # On cygwin and mingw, gcc generates position independent code by default, and
  238. # warns if -fPIC is specified. This might not be the right way of checking if
  239. # we're using cygwin. For example, it's possible to run cygwin gcc from NT
  240. # shell, or using crosscompiling. But we'll solve that problem when it's time.
  241. # In that case we'll just add another parameter to 'init' and move this login
  242. # inside 'init'.
  243. if not os_name () in ['CYGWIN', 'NT']:
  244. # This logic will add -fPIC for all compilations:
  245. #
  246. # lib a : a.cpp b ;
  247. # obj b : b.cpp ;
  248. # exe c : c.cpp a d ;
  249. # obj d : d.cpp ;
  250. #
  251. # This all is fine, except that 'd' will be compiled with -fPIC even though
  252. # it's not needed, as 'd' is used only in exe. However, it's hard to detect
  253. # where a target is going to be used. Alternative, we can set -fPIC only
  254. # when main target type is LIB but than 'b' will be compiled without -fPIC.
  255. # In x86-64 that will lead to link errors. So, compile everything with
  256. # -fPIC.
  257. #
  258. # Yet another alternative would be to create propagated <sharedable>
  259. # feature, and set it when building shared libraries, but that's hard to
  260. # implement and will increase target path length even more.
  261. flags('gcc.compile', 'OPTIONS', ['<link>shared'], ['-fPIC'])
  262. if os_name() != 'NT' and os_name() != 'OSF' and os_name() != 'HPUX':
  263. # OSF does have an option called -soname but it doesn't seem to work as
  264. # expected, therefore it has been disabled.
  265. HAVE_SONAME = ''
  266. SONAME_OPTION = '-h'
  267. flags('gcc.compile', 'USER_OPTIONS', [], ['<cflags>'])
  268. flags('gcc.compile.c++', 'USER_OPTIONS',[], ['<cxxflags>'])
  269. flags('gcc.compile', 'DEFINES', [], ['<define>'])
  270. flags('gcc.compile', 'INCLUDES', [], ['<include>'])
  271. engine = get_manager().engine()
  272. engine.register_action('gcc.compile.c++.pch',
  273. '"$(CONFIG_COMMAND)" -x c++-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"')
  274. engine.register_action('gcc.compile.c.pch',
  275. '"$(CONFIG_COMMAND)" -x c-header $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"')
  276. def gcc_compile_cpp(targets, sources, properties):
  277. # Some extensions are compiled as C++ by default. For others, we need to
  278. # pass -x c++. We could always pass -x c++ but distcc does not work with it.
  279. extension = os.path.splitext (sources [0]) [1]
  280. lang = ''
  281. if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']:
  282. lang = '-x c++'
  283. get_manager().engine().set_target_variable (targets, 'LANG', lang)
  284. engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
  285. def gcc_compile_c(targets, sources, properties):
  286. engine = get_manager().engine()
  287. # If we use the name g++ then default file suffix -> language mapping does
  288. # not work. So have to pass -x option. Maybe, we can work around this by
  289. # allowing the user to specify both C and C++ compiler names.
  290. #if $(>:S) != .c
  291. #{
  292. engine.set_target_variable (targets, 'LANG', '-x c')
  293. #}
  294. engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
  295. engine.register_action(
  296. 'gcc.compile.c++',
  297. '"$(CONFIG_COMMAND)" $(LANG) -ftemplate-depth-128 $(OPTIONS) ' +
  298. '$(USER_OPTIONS) -D$(DEFINES) -I"$(PCH_FILE:D)" -I"$(INCLUDES)" ' +
  299. '-c -o "$(<:W)" "$(>:W)"',
  300. function=gcc_compile_cpp,
  301. bound_list=['PCH_FILE'])
  302. engine.register_action(
  303. 'gcc.compile.c',
  304. '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) ' +
  305. '-I"$(PCH_FILE:D)" -I"$(INCLUDES)" -c -o "$(<)" "$(>)"',
  306. function=gcc_compile_c,
  307. bound_list=['PCH_FILE'])
  308. def gcc_compile_asm(targets, sources, properties):
  309. get_manager().engine().set_target_variable(targets, 'LANG', '-x assembler-with-cpp')
  310. engine.register_action(
  311. 'gcc.compile.asm',
  312. '"$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)"',
  313. function=gcc_compile_asm)
  314. class GccLinkingGenerator(unix.UnixLinkingGenerator):
  315. """
  316. The class which check that we don't try to use the <runtime-link>static
  317. property while creating or using shared library, since it's not supported by
  318. gcc/libc.
  319. """
  320. def run(self, project, name, ps, sources):
  321. # TODO: Replace this with the use of a target-os property.
  322. no_static_link = False
  323. if bjam.variable('UNIX'):
  324. no_static_link = True;
  325. ##FIXME: what does this mean?
  326. ## {
  327. ## switch [ modules.peek : JAMUNAME ]
  328. ## {
  329. ## case * : no-static-link = true ;
  330. ## }
  331. ## }
  332. reason = None
  333. if no_static_link and ps.get('runtime-link') == 'static':
  334. if ps.get('link') == 'shared':
  335. reason = "On gcc, DLL can't be build with '<runtime-link>static'."
  336. elif type.is_derived(self.target_types[0], 'EXE'):
  337. for s in sources:
  338. source_type = s.type()
  339. if source_type and type.is_derived(source_type, 'SHARED_LIB'):
  340. reason = "On gcc, using DLLS together with the " +\
  341. "<runtime-link>static options is not possible "
  342. if reason:
  343. print 'warning:', reason
  344. print 'warning:',\
  345. "It is suggested to use '<runtime-link>static' together",\
  346. "with '<link>static'." ;
  347. return
  348. else:
  349. generated_targets = unix.UnixLinkingGenerator.run(self, project,
  350. name, ps, sources)
  351. return generated_targets
  352. if on_windows():
  353. flags('gcc.link.dll', '.IMPLIB-COMMAND', [], ['-Wl,--out-implib,'])
  354. generators.register(
  355. GccLinkingGenerator('gcc.link', True,
  356. ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'],
  357. [ 'EXE' ],
  358. [ '<toolset>gcc' ]))
  359. generators.register(
  360. GccLinkingGenerator('gcc.link.dll', True,
  361. ['OBJ', 'SEARCHED_LIB', 'STATIC_LIB', 'IMPORT_LIB'],
  362. ['IMPORT_LIB', 'SHARED_LIB'],
  363. ['<toolset>gcc']))
  364. else:
  365. generators.register(
  366. GccLinkingGenerator('gcc.link', True,
  367. ['LIB', 'OBJ'],
  368. ['EXE'],
  369. ['<toolset>gcc']))
  370. generators.register(
  371. GccLinkingGenerator('gcc.link.dll', True,
  372. ['LIB', 'OBJ'],
  373. ['SHARED_LIB'],
  374. ['<toolset>gcc']))
  375. # Declare flags for linking.
  376. # First, the common flags.
  377. flags('gcc.link', 'OPTIONS', ['<debug-symbols>on'], ['-g'])
  378. flags('gcc.link', 'OPTIONS', ['<profiling>on'], ['-pg'])
  379. flags('gcc.link', 'USER_OPTIONS', [], ['<linkflags>'])
  380. flags('gcc.link', 'LINKPATH', [], ['<library-path>'])
  381. flags('gcc.link', 'FINDLIBS-ST', [], ['<find-static-library>'])
  382. flags('gcc.link', 'FINDLIBS-SA', [], ['<find-shared-library>'])
  383. flags('gcc.link', 'LIBRARIES', [], ['<library-file>'])
  384. # For <runtime-link>static we made sure there are no dynamic libraries in the
  385. # link. On HP-UX not all system libraries exist as archived libraries (for
  386. # example, there is no libunwind.a), so, on this platform, the -static option
  387. # cannot be specified.
  388. if os_name() != 'HPUX':
  389. flags('gcc.link', 'OPTIONS', ['<runtime-link>static'], ['-static'])
  390. # Now, the vendor specific flags.
  391. # The parameter linker can be either gnu, darwin, osf, hpux or sun.
  392. def init_link_flags(toolset, linker, condition):
  393. """
  394. Now, the vendor specific flags.
  395. The parameter linker can be either gnu, darwin, osf, hpux or sun.
  396. """
  397. toolset_link = toolset + '.link'
  398. if linker == 'gnu':
  399. # Strip the binary when no debugging is needed. We use --strip-all flag
  400. # as opposed to -s since icc (intel's compiler) is generally
  401. # option-compatible with and inherits from the gcc toolset, but does not
  402. # support -s.
  403. # FIXME: what does unchecked translate to?
  404. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,--strip-all']) # : unchecked ;
  405. flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
  406. flags(toolset_link, 'RPATH_LINK', condition, ['<xdll-path>']) # : unchecked ;
  407. flags(toolset_link, 'START-GROUP', condition, ['-Wl,--start-group'])# : unchecked ;
  408. flags(toolset_link, 'END-GROUP', condition, ['-Wl,--end-group']) # : unchecked ;
  409. # gnu ld has the ability to change the search behaviour for libraries
  410. # referenced by -l switch. These modifiers are -Bstatic and -Bdynamic
  411. # and change search for -l switches that follow them. The following list
  412. # shows the tried variants.
  413. # The search stops at the first variant that has a match.
  414. # *nix: -Bstatic -lxxx
  415. # libxxx.a
  416. #
  417. # *nix: -Bdynamic -lxxx
  418. # libxxx.so
  419. # libxxx.a
  420. #
  421. # windows (mingw,cygwin) -Bstatic -lxxx
  422. # libxxx.a
  423. # xxx.lib
  424. #
  425. # windows (mingw,cygwin) -Bdynamic -lxxx
  426. # libxxx.dll.a
  427. # xxx.dll.a
  428. # libxxx.a
  429. # xxx.lib
  430. # cygxxx.dll (*)
  431. # libxxx.dll
  432. # xxx.dll
  433. # libxxx.a
  434. #
  435. # (*) This is for cygwin
  436. # Please note that -Bstatic and -Bdynamic are not a guarantee that a
  437. # static or dynamic lib indeed gets linked in. The switches only change
  438. # search patterns!
  439. # On *nix mixing shared libs with static runtime is not a good idea.
  440. flags(toolset_link, 'FINDLIBS-ST-PFX',
  441. map(lambda x: x + '/<runtime-link>shared', condition),
  442. ['-Wl,-Bstatic']) # : unchecked ;
  443. flags(toolset_link, 'FINDLIBS-SA-PFX',
  444. map(lambda x: x + '/<runtime-link>shared', condition),
  445. ['-Wl,-Bdynamic']) # : unchecked ;
  446. # On windows allow mixing of static and dynamic libs with static
  447. # runtime.
  448. flags(toolset_link, 'FINDLIBS-ST-PFX',
  449. map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
  450. ['-Wl,-Bstatic']) # : unchecked ;
  451. flags(toolset_link, 'FINDLIBS-SA-PFX',
  452. map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
  453. ['-Wl,-Bdynamic']) # : unchecked ;
  454. flags(toolset_link, 'OPTIONS',
  455. map(lambda x: x + '/<runtime-link>static/<target-os>windows', condition),
  456. ['-Wl,-Bstatic']) # : unchecked ;
  457. elif linker == 'darwin':
  458. # On Darwin, the -s option to ld does not work unless we pass -static,
  459. # and passing -static unconditionally is a bad idea. So, don't pass -s.
  460. # at all, darwin.jam will use separate 'strip' invocation.
  461. flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
  462. flags(toolset_link, 'RPATH_LINK', condition, ['<xdll-path>']) # : unchecked ;
  463. elif linker == 'osf':
  464. # No --strip-all, just -s.
  465. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,-s'])
  466. # : unchecked ;
  467. flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
  468. # This does not supports -R.
  469. flags(toolset_link, 'RPATH_OPTION', condition, ['-rpath']) # : unchecked ;
  470. # -rpath-link is not supported at all.
  471. elif linker == 'sun':
  472. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition), ['-Wl,-s'])
  473. # : unchecked ;
  474. flags(toolset_link, 'RPATH', condition, ['<dll-path>']) # : unchecked ;
  475. # Solaris linker does not have a separate -rpath-link, but allows to use
  476. # -L for the same purpose.
  477. flags(toolset_link, 'LINKPATH', condition, ['<xdll-path>']) # : unchecked ;
  478. # This permits shared libraries with non-PIC code on Solaris.
  479. # VP, 2004/09/07: Now that we have -fPIC hardcode in link.dll, the
  480. # following is not needed. Whether -fPIC should be hardcoded, is a
  481. # separate question.
  482. # AH, 2004/10/16: it is still necessary because some tests link against
  483. # static libraries that were compiled without PIC.
  484. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<link>shared', condition), ['-mimpure-text'])
  485. # : unchecked ;
  486. elif linker == 'hpux':
  487. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<debug-symbols>off', condition),
  488. ['-Wl,-s']) # : unchecked ;
  489. flags(toolset_link, 'OPTIONS', map(lambda x: x + '/<link>shared', condition),
  490. ['-fPIC']) # : unchecked ;
  491. else:
  492. # FIXME:
  493. errors.user_error(
  494. "$(toolset) initialization: invalid linker '$(linker)' " +
  495. "The value '$(linker)' specified for <linker> is not recognized. " +
  496. "Possible values are 'gnu', 'darwin', 'osf', 'hpux' or 'sun'")
  497. # Declare actions for linking.
  498. def gcc_link(targets, sources, properties):
  499. engine = get_manager().engine()
  500. engine.set_target_variable(targets, 'SPACE', ' ')
  501. # Serialize execution of the 'link' action, since running N links in
  502. # parallel is just slower. For now, serialize only gcc links, it might be a
  503. # good idea to serialize all links.
  504. engine.set_target_variable(targets, 'JAM_SEMAPHORE', '<s>gcc-link-semaphore')
  505. engine.register_action(
  506. 'gcc.link',
  507. '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' +
  508. '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' +
  509. '-Wl,-rpath-link$(SPACE)-Wl,"$(RPATH_LINK)" -o "$(<)" ' +
  510. '$(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' +
  511. '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' +
  512. '$(OPTIONS) $(USER_OPTIONS)',
  513. function=gcc_link,
  514. bound_list=['LIBRARIES'])
  515. # Default value. Mostly for the sake of intel-linux that inherits from gcc, but
  516. # does not have the same logic to set the .AR variable. We can put the same
  517. # logic in intel-linux, but that's hardly worth the trouble as on Linux, 'ar' is
  518. # always available.
  519. __AR = 'ar'
  520. flags('gcc.archive', 'AROPTIONS', [], ['<archiveflags>'])
  521. def gcc_archive(targets, sources, properties):
  522. # Always remove archive and start again. Here's rationale from
  523. #
  524. # Andre Hentz:
  525. #
  526. # I had a file, say a1.c, that was included into liba.a. I moved a1.c to
  527. # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd
  528. # errors. After some debugging I traced it back to the fact that a1.o was
  529. # *still* in liba.a
  530. #
  531. # Rene Rivera:
  532. #
  533. # Originally removing the archive was done by splicing an RM onto the
  534. # archive action. That makes archives fail to build on NT when they have
  535. # many files because it will no longer execute the action directly and blow
  536. # the line length limit. Instead we remove the file in a different action,
  537. # just before building the archive.
  538. clean = targets[0] + '(clean)'
  539. bjam.call('TEMPORARY', clean)
  540. bjam.call('NOCARE', clean)
  541. engine = get_manager().engine()
  542. engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE'))
  543. engine.add_dependency(clean, sources)
  544. engine.add_dependency(targets, clean)
  545. engine.set_update_action('common.RmTemps', clean, targets)
  546. # Declare action for creating static libraries.
  547. # The letter 'r' means to add files to the archive with replacement. Since we
  548. # remove archive, we don't care about replacement, but there's no option "add
  549. # without replacement".
  550. # The letter 'c' suppresses the warning in case the archive does not exists yet.
  551. # That warning is produced only on some platforms, for whatever reasons.
  552. engine.register_action('gcc.archive',
  553. '"$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"',
  554. function=gcc_archive,
  555. flags=['piecemeal'])
  556. def gcc_link_dll(targets, sources, properties):
  557. engine = get_manager().engine()
  558. engine.set_target_variable(targets, 'SPACE', ' ')
  559. engine.set_target_variable(targets, 'JAM_SEMAPHORE', '<s>gcc-link-semaphore')
  560. engine.set_target_variable(targets, "HAVE_SONAME", HAVE_SONAME)
  561. engine.set_target_variable(targets, "SONAME_OPTION", SONAME_OPTION)
  562. engine.register_action(
  563. 'gcc.link.dll',
  564. # Differ from 'link' above only by -shared.
  565. '"$(CONFIG_COMMAND)" -L"$(LINKPATH)" ' +
  566. '-Wl,$(RPATH_OPTION:E=-R)$(SPACE)-Wl,"$(RPATH)" ' +
  567. '"$(.IMPLIB-COMMAND)$(<[1])" -o "$(<[-1])" ' +
  568. '$(HAVE_SONAME)-Wl,$(SONAME_OPTION)$(SPACE)-Wl,$(<[-1]:D=) ' +
  569. '-shared $(START-GROUP) "$(>)" "$(LIBRARIES)" $(FINDLIBS-ST-PFX) ' +
  570. '-l$(FINDLIBS-ST) $(FINDLIBS-SA-PFX) -l$(FINDLIBS-SA) $(END-GROUP) ' +
  571. '$(OPTIONS) $(USER_OPTIONS)',
  572. function = gcc_link_dll,
  573. bound_list=['LIBRARIES'])
  574. # Set up threading support. It's somewhat contrived, so perform it at the end,
  575. # to avoid cluttering other code.
  576. if on_windows():
  577. flags('gcc', 'OPTIONS', ['<threading>multi'], ['-mthreads'])
  578. elif bjam.variable('UNIX'):
  579. jamuname = bjam.variable('JAMUNAME')
  580. host_os_name = jamuname[0]
  581. if host_os_name.startswith('SunOS'):
  582. flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthreads'])
  583. flags('gcc', 'FINDLIBS-SA', [], ['rt'])
  584. elif host_os_name == 'BeOS':
  585. # BeOS has no threading options, don't set anything here.
  586. pass
  587. elif host_os_name.endswith('BSD'):
  588. flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
  589. # there is no -lrt on BSD
  590. elif host_os_name == 'DragonFly':
  591. flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
  592. # there is no -lrt on BSD - DragonFly is a FreeBSD variant,
  593. # which anoyingly doesn't say it's a *BSD.
  594. elif host_os_name == 'IRIX':
  595. # gcc on IRIX does not support multi-threading, don't set anything here.
  596. pass
  597. elif host_os_name == 'Darwin':
  598. # Darwin has no threading options, don't set anything here.
  599. pass
  600. else:
  601. flags('gcc', 'OPTIONS', ['<threading>multi'], ['-pthread'])
  602. flags('gcc', 'FINDLIBS-SA', [], ['rt'])
  603. def cpu_flags(toolset, variable, architecture, instruction_set, values, default=None):
  604. #FIXME: for some reason this fails. Probably out of date feature code
  605. ## if default:
  606. ## flags(toolset, variable,
  607. ## ['<architecture>' + architecture + '/<instruction-set>'],
  608. ## values)
  609. flags(toolset, variable,
  610. #FIXME: same as above
  611. [##'<architecture>/<instruction-set>' + instruction_set,
  612. '<architecture>' + architecture + '/<instruction-set>' + instruction_set],
  613. values)
  614. # Set architecture/instruction-set options.
  615. #
  616. # x86 and compatible
  617. flags('gcc', 'OPTIONS', ['<architecture>x86/<address-model>32'], ['-m32'])
  618. flags('gcc', 'OPTIONS', ['<architecture>x86/<address-model>64'], ['-m64'])
  619. cpu_flags('gcc', 'OPTIONS', 'x86', 'i386', ['-march=i386'], default=True)
  620. cpu_flags('gcc', 'OPTIONS', 'x86', 'i486', ['-march=i486'])
  621. cpu_flags('gcc', 'OPTIONS', 'x86', 'i586', ['-march=i586'])
  622. cpu_flags('gcc', 'OPTIONS', 'x86', 'i686', ['-march=i686'])
  623. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium', ['-march=pentium'])
  624. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium-mmx', ['-march=pentium-mmx'])
  625. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentiumpro', ['-march=pentiumpro'])
  626. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium2', ['-march=pentium2'])
  627. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium3', ['-march=pentium3'])
  628. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium3m', ['-march=pentium3m'])
  629. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium-m', ['-march=pentium-m'])
  630. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium4', ['-march=pentium4'])
  631. cpu_flags('gcc', 'OPTIONS', 'x86', 'pentium4m', ['-march=pentium4m'])
  632. cpu_flags('gcc', 'OPTIONS', 'x86', 'prescott', ['-march=prescott'])
  633. cpu_flags('gcc', 'OPTIONS', 'x86', 'nocona', ['-march=nocona'])
  634. cpu_flags('gcc', 'OPTIONS', 'x86', 'k6', ['-march=k6'])
  635. cpu_flags('gcc', 'OPTIONS', 'x86', 'k6-2', ['-march=k6-2'])
  636. cpu_flags('gcc', 'OPTIONS', 'x86', 'k6-3', ['-march=k6-3'])
  637. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon', ['-march=athlon'])
  638. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-tbird', ['-march=athlon-tbird'])
  639. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-4', ['-march=athlon-4'])
  640. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-xp', ['-march=athlon-xp'])
  641. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-mp', ['-march=athlon-mp'])
  642. ##
  643. cpu_flags('gcc', 'OPTIONS', 'x86', 'k8', ['-march=k8'])
  644. cpu_flags('gcc', 'OPTIONS', 'x86', 'opteron', ['-march=opteron'])
  645. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon64', ['-march=athlon64'])
  646. cpu_flags('gcc', 'OPTIONS', 'x86', 'athlon-fx', ['-march=athlon-fx'])
  647. cpu_flags('gcc', 'OPTIONS', 'x86', 'winchip-c6', ['-march=winchip-c6'])
  648. cpu_flags('gcc', 'OPTIONS', 'x86', 'winchip2', ['-march=winchip2'])
  649. cpu_flags('gcc', 'OPTIONS', 'x86', 'c3', ['-march=c3'])
  650. cpu_flags('gcc', 'OPTIONS', 'x86', 'c3-2', ['-march=c3-2'])
  651. # Sparc
  652. flags('gcc', 'OPTIONS', ['<architecture>sparc/<address-model>32'], ['-m32'])
  653. flags('gcc', 'OPTIONS', ['<architecture>sparc/<address-model>64'], ['-m64'])
  654. cpu_flags('gcc', 'OPTIONS', 'sparc', 'c3', ['-mcpu=c3'], default=True)
  655. cpu_flags('gcc', 'OPTIONS', 'sparc', 'v7', ['-mcpu=v7'])
  656. cpu_flags('gcc', 'OPTIONS', 'sparc', 'cypress', ['-mcpu=cypress'])
  657. cpu_flags('gcc', 'OPTIONS', 'sparc', 'v8', ['-mcpu=v8'])
  658. cpu_flags('gcc', 'OPTIONS', 'sparc', 'supersparc', ['-mcpu=supersparc'])
  659. cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclite', ['-mcpu=sparclite'])
  660. cpu_flags('gcc', 'OPTIONS', 'sparc', 'hypersparc', ['-mcpu=hypersparc'])
  661. cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclite86x', ['-mcpu=sparclite86x'])
  662. cpu_flags('gcc', 'OPTIONS', 'sparc', 'f930', ['-mcpu=f930'])
  663. cpu_flags('gcc', 'OPTIONS', 'sparc', 'f934', ['-mcpu=f934'])
  664. cpu_flags('gcc', 'OPTIONS', 'sparc', 'sparclet', ['-mcpu=sparclet'])
  665. cpu_flags('gcc', 'OPTIONS', 'sparc', 'tsc701', ['-mcpu=tsc701'])
  666. cpu_flags('gcc', 'OPTIONS', 'sparc', 'v9', ['-mcpu=v9'])
  667. cpu_flags('gcc', 'OPTIONS', 'sparc', 'ultrasparc', ['-mcpu=ultrasparc'])
  668. cpu_flags('gcc', 'OPTIONS', 'sparc', 'ultrasparc3', ['-mcpu=ultrasparc3'])
  669. # RS/6000 & PowerPC
  670. flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>32'], ['-m32'])
  671. flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>64'], ['-m64'])
  672. cpu_flags('gcc', 'OPTIONS', 'power', '403', ['-mcpu=403'])
  673. cpu_flags('gcc', 'OPTIONS', 'power', '505', ['-mcpu=505'])
  674. cpu_flags('gcc', 'OPTIONS', 'power', '601', ['-mcpu=601'])
  675. cpu_flags('gcc', 'OPTIONS', 'power', '602', ['-mcpu=602'])
  676. cpu_flags('gcc', 'OPTIONS', 'power', '603', ['-mcpu=603'])
  677. cpu_flags('gcc', 'OPTIONS', 'power', '603e', ['-mcpu=603e'])
  678. cpu_flags('gcc', 'OPTIONS', 'power', '604', ['-mcpu=604'])
  679. cpu_flags('gcc', 'OPTIONS', 'power', '604e', ['-mcpu=604e'])
  680. cpu_flags('gcc', 'OPTIONS', 'power', '620', ['-mcpu=620'])
  681. cpu_flags('gcc', 'OPTIONS', 'power', '630', ['-mcpu=630'])
  682. cpu_flags('gcc', 'OPTIONS', 'power', '740', ['-mcpu=740'])
  683. cpu_flags('gcc', 'OPTIONS', 'power', '7400', ['-mcpu=7400'])
  684. cpu_flags('gcc', 'OPTIONS', 'power', '7450', ['-mcpu=7450'])
  685. cpu_flags('gcc', 'OPTIONS', 'power', '750', ['-mcpu=750'])
  686. cpu_flags('gcc', 'OPTIONS', 'power', '801', ['-mcpu=801'])
  687. cpu_flags('gcc', 'OPTIONS', 'power', '821', ['-mcpu=821'])
  688. cpu_flags('gcc', 'OPTIONS', 'power', '823', ['-mcpu=823'])
  689. cpu_flags('gcc', 'OPTIONS', 'power', '860', ['-mcpu=860'])
  690. cpu_flags('gcc', 'OPTIONS', 'power', '970', ['-mcpu=970'])
  691. cpu_flags('gcc', 'OPTIONS', 'power', '8540', ['-mcpu=8540'])
  692. cpu_flags('gcc', 'OPTIONS', 'power', 'power', ['-mcpu=power'])
  693. cpu_flags('gcc', 'OPTIONS', 'power', 'power2', ['-mcpu=power2'])
  694. cpu_flags('gcc', 'OPTIONS', 'power', 'power3', ['-mcpu=power3'])
  695. cpu_flags('gcc', 'OPTIONS', 'power', 'power4', ['-mcpu=power4'])
  696. cpu_flags('gcc', 'OPTIONS', 'power', 'power5', ['-mcpu=power5'])
  697. cpu_flags('gcc', 'OPTIONS', 'power', 'powerpc', ['-mcpu=powerpc'])
  698. cpu_flags('gcc', 'OPTIONS', 'power', 'powerpc64', ['-mcpu=powerpc64'])
  699. cpu_flags('gcc', 'OPTIONS', 'power', 'rios', ['-mcpu=rios'])
  700. cpu_flags('gcc', 'OPTIONS', 'power', 'rios1', ['-mcpu=rios1'])
  701. cpu_flags('gcc', 'OPTIONS', 'power', 'rios2', ['-mcpu=rios2'])
  702. cpu_flags('gcc', 'OPTIONS', 'power', 'rsc', ['-mcpu=rsc'])
  703. cpu_flags('gcc', 'OPTIONS', 'power', 'rs64a', ['-mcpu=rs64'])
  704. # AIX variant of RS/6000 & PowerPC
  705. flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>32/<target-os>aix'], ['-maix32'])
  706. flags('gcc', 'OPTIONS', ['<architecture>power/<address-model>64/<target-os>aix'], ['-maix64'])
  707. flags('gcc', 'AROPTIONS', ['<architecture>power/<address-model>64/<target-os>aix'], ['-X 64'])