waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

cross_gnu.py (6109B)


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