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""" 9This tool allows to use environment variables to define cross-compilation 10variables intended for build variants. 11 12The variables are obtained from the environment in 3 ways: 13 141. By defining CHOST, they can be derived as ${CHOST}-${TOOL} 152. By defining HOST_x 163. By defining ${CHOST//-/_}_x 17 18else one can set ``cfg.env.CHOST`` in ``wscript`` before loading ``cross_gnu``. 19 20Usage: 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 40This 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 83import os 84from waflib import Utils, Configure 85from waflib.Tools import ccroot, gcc 86 87try: 88 from shlex import quote 89except ImportError: 90 from pipes import quote 91 92def 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 105def 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 126def 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 162def 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 192def 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 218def 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() 228