third_party/waf: upgrade to waf 2.0.8
[samba.git] / third_party / waf / waflib / extras / cross_gnu.py
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()