cross_gnu.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 vi:ts=4:noexpandtab
  3. # Tool to provide dedicated variables for cross-compilation
  4. __author__ = __maintainer__ = "Jérôme Carretero <cJ-waf@zougloub.eu>"
  5. __copyright__ = "Jérôme Carretero, 2014"
  6. """
  7. This tool allows to use environment variables to define cross-compilation
  8. variables intended for build variants.
  9. The variables are obtained from the environment in 3 ways:
  10. 1. By defining CHOST, they can be derived as ${CHOST}-${TOOL}
  11. 2. By defining HOST_x
  12. 3. By defining ${CHOST//-/_}_x
  13. else one can set ``cfg.env.CHOST`` in ``wscript`` before loading ``cross_gnu``.
  14. Usage:
  15. - In your build script::
  16. def configure(cfg):
  17. ...
  18. for variant in x_variants:
  19. setenv(variant)
  20. conf.load('cross_gnu')
  21. conf.xcheck_host_var('POUET')
  22. ...
  23. - Then::
  24. CHOST=arm-hardfloat-linux-gnueabi waf configure
  25. env arm-hardfloat-linux-gnueabi-CC="clang -..." waf configure
  26. CFLAGS=... CHOST=arm-hardfloat-linux-gnueabi HOST_CFLAGS=-g waf configure
  27. HOST_CC="clang -..." waf configure
  28. This example ``wscript`` compiles to Microchip PIC (xc16-gcc-xyz must be in PATH):
  29. .. code:: python
  30. from waflib import Configure
  31. #from https://gist.github.com/rpuntaie/2bddfb5d7b77db26415ee14371289971
  32. import waf_variants
  33. variants='pc fw/variant1 fw/variant2'.split()
  34. top = "."
  35. out = "../build"
  36. PIC = '33FJ128GP804' #dsPICxxx
  37. @Configure.conf
  38. def gcc_modifier_xc16(cfg):
  39. v = cfg.env
  40. v.cprogram_PATTERN = '%s.elf'
  41. v.LINKFLAGS_cprogram = ','.join(['-Wl','','','--defsym=__MPLAB_BUILD=0','','--script=p'+PIC+'.gld',
  42. '--stack=16','--check-sections','--data-init','--pack-data','--handles','--isr','--no-gc-sections',
  43. '--fill-upper=0','--stackguard=16','--no-force-link','--smart-io']) #,'--report-mem'])
  44. v.CFLAGS_cprogram=['-mcpu='+PIC,'-omf=elf','-mlarge-code','-msmart-io=1',
  45. '-msfr-warn=off','-mno-override-inline','-finline','-Winline']
  46. def configure(cfg):
  47. if 'fw' in cfg.variant: #firmware
  48. cfg.env.DEST_OS = 'xc16' #cfg.env.CHOST = 'xc16' #works too
  49. cfg.load('c cross_gnu') #cfg.env.CHOST becomes ['xc16']
  50. ...
  51. else: #configure for pc SW
  52. ...
  53. def build(bld):
  54. if 'fw' in bld.variant: #firmware
  55. bld.program(source='maintst.c', target='maintst');
  56. bld(source='maintst.elf', target='maintst.hex', rule="xc16-bin2hex ${SRC} -a -omf=elf")
  57. else: #build for pc SW
  58. ...
  59. """
  60. import os
  61. from waflib import Utils, Configure
  62. from waflib.Tools import ccroot, gcc
  63. try:
  64. from shlex import quote
  65. except ImportError:
  66. from pipes import quote
  67. def get_chost_stuff(conf):
  68. """
  69. Get the CHOST environment variable contents
  70. """
  71. chost = None
  72. chost_envar = None
  73. if conf.env.CHOST:
  74. chost = conf.env.CHOST[0]
  75. chost_envar = chost.replace('-', '_')
  76. return chost, chost_envar
  77. @Configure.conf
  78. def xcheck_var(conf, name, wafname=None, cross=False):
  79. wafname = wafname or name
  80. if wafname in conf.env:
  81. value = conf.env[wafname]
  82. if isinstance(value, str):
  83. value = [value]
  84. else:
  85. envar = os.environ.get(name)
  86. if not envar:
  87. return
  88. value = Utils.to_list(envar) if envar != '' else [envar]
  89. conf.env[wafname] = value
  90. if cross:
  91. pretty = 'cross-compilation %s' % wafname
  92. else:
  93. pretty = wafname
  94. conf.msg('Will use %s' % pretty, " ".join(quote(x) for x in value))
  95. @Configure.conf
  96. def xcheck_host_prog(conf, name, tool, wafname=None):
  97. wafname = wafname or name
  98. chost, chost_envar = get_chost_stuff(conf)
  99. specific = None
  100. if chost:
  101. specific = os.environ.get('%s_%s' % (chost_envar, name))
  102. if specific:
  103. value = Utils.to_list(specific)
  104. conf.env[wafname] += value
  105. conf.msg('Will use cross-compilation %s from %s_%s' % (name, chost_envar, name),
  106. " ".join(quote(x) for x in value))
  107. return
  108. else:
  109. envar = os.environ.get('HOST_%s' % name)
  110. if envar is not None:
  111. value = Utils.to_list(envar)
  112. conf.env[wafname] = value
  113. conf.msg('Will use cross-compilation %s from HOST_%s' % (name, name),
  114. " ".join(quote(x) for x in value))
  115. return
  116. if conf.env[wafname]:
  117. return
  118. value = None
  119. if chost:
  120. value = '%s-%s' % (chost, tool)
  121. if value:
  122. conf.env[wafname] = value
  123. conf.msg('Will use cross-compilation %s from CHOST' % wafname, value)
  124. @Configure.conf
  125. def xcheck_host_envar(conf, name, wafname=None):
  126. wafname = wafname or name
  127. chost, chost_envar = get_chost_stuff(conf)
  128. specific = None
  129. if chost:
  130. specific = os.environ.get('%s_%s' % (chost_envar, name))
  131. if specific:
  132. value = Utils.to_list(specific)
  133. conf.env[wafname] += value
  134. conf.msg('Will use cross-compilation %s from %s_%s' \
  135. % (name, chost_envar, name),
  136. " ".join(quote(x) for x in value))
  137. return
  138. envar = os.environ.get('HOST_%s' % name)
  139. if envar is None:
  140. return
  141. value = Utils.to_list(envar) if envar != '' else [envar]
  142. conf.env[wafname] = value
  143. conf.msg('Will use cross-compilation %s from HOST_%s' % (name, name),
  144. " ".join(quote(x) for x in value))
  145. @Configure.conf
  146. def xcheck_host(conf):
  147. conf.xcheck_var('CHOST', cross=True)
  148. conf.env.CHOST = conf.env.CHOST or [conf.env.DEST_OS]
  149. conf.env.DEST_OS = conf.env.CHOST[0].replace('-','_')
  150. conf.xcheck_host_prog('CC', 'gcc')
  151. conf.xcheck_host_prog('CXX', 'g++')
  152. conf.xcheck_host_prog('LINK_CC', 'gcc')
  153. conf.xcheck_host_prog('LINK_CXX', 'g++')
  154. conf.xcheck_host_prog('AR', 'ar')
  155. conf.xcheck_host_prog('AS', 'as')
  156. conf.xcheck_host_prog('LD', 'ld')
  157. conf.xcheck_host_envar('CFLAGS')
  158. conf.xcheck_host_envar('CXXFLAGS')
  159. conf.xcheck_host_envar('LDFLAGS', 'LINKFLAGS')
  160. conf.xcheck_host_envar('LIB')
  161. conf.xcheck_host_envar('PKG_CONFIG_LIBDIR')
  162. conf.xcheck_host_envar('PKG_CONFIG_PATH')
  163. if not conf.env.env:
  164. conf.env.env = {}
  165. conf.env.env.update(os.environ)
  166. if conf.env.PKG_CONFIG_LIBDIR:
  167. conf.env.env['PKG_CONFIG_LIBDIR'] = conf.env.PKG_CONFIG_LIBDIR[0]
  168. if conf.env.PKG_CONFIG_PATH:
  169. conf.env.env['PKG_CONFIG_PATH'] = conf.env.PKG_CONFIG_PATH[0]
  170. def configure(conf):
  171. """
  172. Configuration example for gcc, it will not work for g++/clang/clang++
  173. """
  174. conf.xcheck_host()
  175. conf.gcc_common_flags()
  176. conf.gcc_modifier_platform()
  177. conf.cc_load_tools()
  178. conf.cc_add_flags()
  179. conf.link_add_flags()