3
# Thomas Nagy, 2005-2010 (ita)
6
C/C++/D configuration helpers
9
import os, imp, sys, re, shlex, shutil
10
from waflib import Build, Utils, Configure, Task, Options, Logs, TaskGen, Errors, ConfigSet, Runner
11
from waflib.TaskGen import before_method, after_method, feature
12
from waflib.Configure import conf
14
WAF_CONFIG_H = 'config.h'
15
"""default name for the config.h file"""
17
DEFKEYS = 'define_key'
18
INCKEYS = 'include_key'
21
'atleast-version': '>=',
22
'exact-version': '==',
33
"""Code template for checking for functions"""
37
if ((%(type_name)s *) 0) return 0;
38
if (sizeof (%(type_name)s)) return 0;
41
"""Code template for checking for types"""
49
SNIP_EMPTY_PROGRAM = '''
58
off = (char*) &((%(type_name)s*)0)->%(field_name)s;
59
return (size_t) off < sizeof(%(type_name)s);
64
'__linux__' : 'linux',
65
'__GNU__' : 'gnu', # hurd
66
'__FreeBSD__' : 'freebsd',
67
'__NetBSD__' : 'netbsd',
68
'__OpenBSD__' : 'openbsd',
73
'__CYGWIN__' : 'cygwin',
78
# Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file.
79
'__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin',
80
'__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone
82
'__native_client__' : 'nacl' # google native client platform
86
'__x86_64__' : 'x86_64',
90
'__sparc__' : 'sparc',
91
'__alpha__' : 'alpha',
94
'__powerpc__' : 'powerpc',
98
def parse_flags(self, line, uselib, env=None, force_static=False):
100
Parse the flags from the input lines, and add them to the relevant use variables::
103
conf.parse_flags('-O3', uselib_store='FOO')
104
# conf.env.CXXFLAGS_FOO = ['-O3']
105
# conf.env.CFLAGS_FOO = ['-O3']
109
:param uselib: where to add the flags
111
:param env: config set or conf.env by default
112
:type env: :py:class:`waflib.ConfigSet.ConfigSet`
115
assert(isinstance(line, str))
117
env = env or self.env
119
# append_unique is not always possible
120
# for example, apple flags may require both -arch i386 and -arch ppc
122
app = env.append_value
123
appu = env.append_unique
124
#lst = shlex.split(line)
126
lex = shlex.shlex(line, posix=False)
127
lex.whitespace_split = True
136
if st == '-I' or st == '/I':
137
if not ot: ot = lst.pop(0)
138
appu('INCLUDES_' + uselib, [ot])
139
elif st == '-include':
140
tmp = [x, lst.pop(0)]
143
elif st == '-D' or (self.env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but..
144
if not ot: ot = lst.pop(0)
145
app('DEFINES_' + uselib, [ot])
147
if not ot: ot = lst.pop(0)
148
prefix = force_static and 'STLIB_' or 'LIB_'
149
appu(prefix + uselib, [ot])
151
if not ot: ot = lst.pop(0)
152
appu('LIBPATH_' + uselib, [ot])
153
elif x == '-pthread' or x.startswith('+') or x.startswith('-std'):
154
app('CFLAGS_' + uselib, [x])
155
app('CXXFLAGS_' + uselib, [x])
156
app('LINKFLAGS_' + uselib, [x])
157
elif x == '-framework':
158
appu('FRAMEWORK_' + uselib, [lst.pop(0)])
159
elif x.startswith('-F'):
160
appu('FRAMEWORKPATH_' + uselib, [x[2:]])
161
elif x.startswith('-Wl'):
162
app('LINKFLAGS_' + uselib, [x])
163
elif x.startswith('-m') or x.startswith('-f') or x.startswith('-dynamic'):
164
app('CFLAGS_' + uselib, [x])
165
app('CXXFLAGS_' + uselib, [x])
166
elif x.startswith('-bundle'):
167
app('LINKFLAGS_' + uselib, [x])
168
elif x.startswith('-undefined'):
170
app('LINKFLAGS_' + uselib, [x, arg])
171
elif x.startswith('-arch') or x.startswith('-isysroot'):
172
tmp = [x, lst.pop(0)]
173
app('CFLAGS_' + uselib, tmp)
174
app('CXXFLAGS_' + uselib, tmp)
175
app('LINKFLAGS_' + uselib, tmp)
176
elif x.endswith('.a') or x.endswith('.so') or x.endswith('.dylib'):
177
appu('LINKFLAGS_' + uselib, [x]) # not cool, #762
180
def ret_msg(self, f, kw):
181
if isinstance(f, str):
186
def validate_cfg(self, kw):
188
Search for the program *pkg-config* if missing, and validate the parameters to pass to
189
:py:func:`waflib.Tools.c_config.exec_cfg`.
191
:param path: the **-config program to use** (default is *pkg-config*)
192
:type path: list of string
193
:param msg: message to display to describe the test executed
195
:param okmsg: message to display when the test is successful
197
:param errmsg: message to display in case of error
201
if not self.env.PKGCONFIG:
202
self.find_program('pkg-config', var='PKGCONFIG')
203
kw['path'] = self.env.PKGCONFIG
206
if 'atleast_pkgconfig_version' in kw:
208
kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version']
211
if not 'okmsg' in kw:
213
if not 'errmsg' in kw:
214
kw['errmsg'] = 'not found'
216
if 'modversion' in kw:
218
kw['msg'] = 'Checking for %r version' % kw['modversion']
221
# checking for the version of a module, for the moment, one thing at a time
222
for x in cfg_ver.keys():
223
y = x.replace('-', '_')
225
if not 'package' in kw:
226
raise ValueError('%s requires a package' % x)
229
kw['msg'] = 'Checking for %r %s %s' % (kw['package'], cfg_ver[x], kw[y])
233
kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path'])
236
def exec_cfg(self, kw):
238
Execute the program *pkg-config*:
240
* if atleast_pkgconfig_version is given, check that pkg-config has the version n and return
241
* if modversion is given, then return the module version
242
* else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable
244
:param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests)
245
:type atleast_pkgconfig_version: string
246
:param package: package name, for example *gtk+-2.0*
247
:type package: string
248
:param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables.
249
:type uselib_store: string
250
:param modversion: if provided, return the version of the given module and define *name*\_VERSION
251
:type modversion: string
252
:param args: arguments to give to *package* when retrieving flags
253
:type args: list of string
254
:param variables: return the values of particular variables
255
:type variables: list of string
256
:param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES)
257
:type define_variable: dict(string: string)
261
if 'atleast_pkgconfig_version' in kw:
262
cmd = [kw['path'], '--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']]
263
self.cmd_and_log(cmd)
264
if not 'okmsg' in kw:
268
# checking for the version of a module
270
y = x.replace('-', '_')
272
self.cmd_and_log([kw['path'], '--%s=%s' % (x, kw[y]), kw['package']])
273
if not 'okmsg' in kw:
275
self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0)
278
# retrieving the version of a module
279
if 'modversion' in kw:
280
version = self.cmd_and_log([kw['path'], '--modversion', kw['modversion']]).strip()
281
self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version)
286
defi = kw.get('define_variable', None)
288
defi = self.env.PKG_CONFIG_DEFINES or {}
289
for key, val in defi.items():
290
lst.append('--define-variable=%s=%s' % (key, val))
293
lst.extend(Utils.to_list(kw['package']))
295
# retrieving variables of a module
296
if 'variables' in kw:
297
env = kw.get('env', self.env)
298
uselib = kw.get('uselib_store', kw['package'].upper())
299
vars = Utils.to_list(kw['variables'])
301
val = self.cmd_and_log(lst + ['--variable=' + v]).strip()
302
var = '%s_%s' % (uselib, v)
304
if not 'okmsg' in kw:
310
args = Utils.to_list(kw['args'])
311
if '--static' in args or '--static-libs' in args:
314
# so we assume the command-line will output flags to be parsed afterwards
315
ret = self.cmd_and_log(lst)
316
if not 'okmsg' in kw:
319
self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0)
320
self.parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env), force_static=static)
324
def check_cfg(self, *k, **kw):
326
Check for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc).
327
Encapsulate the calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg`
332
conf.load('compiler_c')
333
conf.check_cfg(package='glib-2.0', args='--libs --cflags')
334
conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0',
335
args='--cflags --libs')
336
conf.check_cfg(package='pango')
337
conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs'])
338
conf.check_cfg(package='pango',
339
args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'],
340
msg="Checking for 'pango 0.1.0'")
341
conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL')
342
conf.check_cfg(path='mpicc', args='--showme:compile --showme:link',
343
package='', uselib_store='OPEN_MPI', mandatory=False)
348
kw['package'] = lst[0]
349
kw['args'] = ' '.join(lst[1:])
351
self.validate_cfg(kw)
353
self.start_msg(kw['msg'])
356
ret = self.exec_cfg(kw)
357
except self.errors.WafError as e:
359
self.end_msg(kw['errmsg'], 'YELLOW')
363
self.fatal('The configuration failed')
367
self.end_msg(self.ret_msg(kw['okmsg'], kw))
372
def validate_c(self, kw):
374
pre-check the parameters that will be given to run_c_code
376
:param env: an optional environment (modified -> provide a copy)
377
:type env: :py:class:`waflib.ConfigSet.ConfigSet`
378
:param compiler: c or cxx (tries to guess what is best)
379
:type compiler: string
380
:param type: cprogram, cshlib, cstlib - not required if *features are given directly*
381
:type type: binary to create
382
:param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib``
383
:type feature: list of string
384
:param fragment: provide a piece of code for the test (default is to let the system create one)
385
:type fragment: string
386
:param uselib_store: define variables after the test is executed (IMPORTANT!)
387
:type uselib_store: string
388
:param use: parameters to use for building (just like the normal *use* keyword)
389
:type use: list of string
390
:param define_name: define to set when the check is over
391
:type define_name: string
392
:param execute: execute the resulting binary
394
:param define_ret: if execute is set to True, use the execution output in both the define and the return value
395
:type define_ret: bool
396
:param header_name: check for a particular header
397
:type header_name: string
398
:param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers
399
:type auto_add_header_name: bool
403
kw['env'] = self.env.derive()
406
if not 'compiler' in kw and not 'features' in kw:
408
if env['CXX_NAME'] and Task.classes.get('cxx', None):
409
kw['compiler'] = 'cxx'
410
if not self.env['CXX']:
411
self.fatal('a c++ compiler is required')
413
if not self.env['CC']:
414
self.fatal('a c compiler is required')
416
if not 'compile_mode' in kw:
417
kw['compile_mode'] = 'c'
418
if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx':
419
kw['compile_mode'] = 'cxx'
422
kw['type'] = 'cprogram'
424
if not 'features' in kw:
425
kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram c"
427
kw['features'] = Utils.to_list(kw['features'])
429
if not 'compile_filename' in kw:
430
kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '')
434
if 'header_name' in dct:
435
dct = Utils.to_list(dct['header_name'])
436
return ''.join(['#include <%s>\n' % x for x in dct])
440
if 'framework_name' in kw:
441
fwkname = kw['framework_name']
442
if not 'uselib_store' in kw:
443
kw['uselib_store'] = fwkname.upper()
445
if not kw.get('no_header', False):
446
if not 'header_name' in kw:
447
kw['header_name'] = []
448
fwk = '%s/%s.h' % (fwkname, fwkname)
449
if kw.get('remove_dot_h', None):
451
kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk]
453
kw['msg'] = 'Checking for framework %s' % fwkname
454
kw['framework'] = fwkname
455
#kw['frameworkpath'] = set it yourself
457
if 'function_name' in kw:
458
fu = kw['function_name']
460
kw['msg'] = 'Checking for function %s' % fu
461
kw['code'] = to_header(kw) + SNIP_FUNCTION % fu
462
if not 'uselib_store' in kw:
463
kw['uselib_store'] = fu.upper()
464
if not 'define_name' in kw:
465
kw['define_name'] = self.have_define(fu)
467
elif 'type_name' in kw:
469
if not 'header_name' in kw:
470
kw['header_name'] = 'stdint.h'
471
if 'field_name' in kw:
472
field = kw['field_name']
473
kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field}
475
kw['msg'] = 'Checking for field %s in %s' % (field, tu)
476
if not 'define_name' in kw:
477
kw['define_name'] = self.have_define((tu + '_' + field).upper())
479
kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu}
481
kw['msg'] = 'Checking for type %s' % tu
482
if not 'define_name' in kw:
483
kw['define_name'] = self.have_define(tu.upper())
485
elif 'header_name' in kw:
487
kw['msg'] = 'Checking for header %s' % kw['header_name']
489
l = Utils.to_list(kw['header_name'])
490
assert len(l)>0, 'list of headers in header_name is empty'
492
kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM
494
if not 'uselib_store' in kw:
495
kw['uselib_store'] = l[0].upper()
497
if not 'define_name' in kw:
498
kw['define_name'] = self.have_define(l[0])
502
kw['msg'] = 'Checking for library %s' % kw['lib']
503
if not 'uselib_store' in kw:
504
kw['uselib_store'] = kw['lib'].upper()
508
kw['msg'] = 'Checking for static library %s' % kw['stlib']
509
if not 'uselib_store' in kw:
510
kw['uselib_store'] = kw['stlib'].upper()
513
# an additional code fragment may be provided to replace the predefined code
515
kw['code'] = kw['fragment']
517
kw['msg'] = 'Checking for code snippet'
518
if not 'errmsg' in kw:
521
for (flagsname,flagstype) in [('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')]:
524
kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname])
525
if not 'errmsg' in kw:
528
if not 'execute' in kw:
529
kw['execute'] = False
531
kw['features'].append('test_exec')
533
if not 'errmsg' in kw:
534
kw['errmsg'] = 'not found'
536
if not 'okmsg' in kw:
540
kw['code'] = SNIP_EMPTY_PROGRAM
542
# if there are headers to append automatically to the next tests
543
if self.env[INCKEYS]:
544
kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code']
546
if not kw.get('success'): kw['success'] = None
548
if 'define_name' in kw:
549
self.undefine(kw['define_name'])
551
assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c'
554
def post_check(self, *k, **kw):
555
"Set the variables after a test executed in :py:func:`waflib.Tools.c_config.check` was run successfully"
559
if kw['success'] is not None:
560
if kw.get('define_ret', False):
561
is_success = kw['success']
563
is_success = (kw['success'] == 0)
565
is_success = (kw['success'] == 0)
567
if 'define_name' in kw:
569
if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw:
570
nm = kw['define_name']
571
if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str):
572
self.define(kw['define_name'], is_success, quote=kw.get('quote', 1))
574
self.define_cond(kw['define_name'], is_success)
576
self.define_cond(kw['define_name'], is_success)
578
if 'header_name' in kw:
579
if kw.get('auto_add_header_name', False):
580
self.env.append_value(INCKEYS, Utils.to_list(kw['header_name']))
582
if is_success and 'uselib_store' in kw:
583
from waflib.Tools import ccroot
585
# TODO see get_uselib_vars from ccroot.py
587
for x in kw['features']:
588
if x in ccroot.USELIB_VARS:
589
_vars |= ccroot.USELIB_VARS[x]
593
if k == 'INCLUDES': lk = 'includes'
594
if k == 'DEFINES': lk = 'defines'
597
# remove trailing slash
598
if isinstance(val, str):
599
val = val.rstrip(os.path.sep)
600
self.env.append_unique(k + '_' + kw['uselib_store'], val)
604
def check(self, *k, **kw):
606
Perform a configuration test by calling :py:func:`waflib.Tools.c_config.run_c_code`.
607
For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`.
608
To force a specific compiler, prefer the methods :py:func:`waflib.Tools.c_config.check_cxx` or :py:func:`waflib.Tools.c_config.check_cc`
611
self.start_msg(kw['msg'])
614
ret = self.run_c_code(*k, **kw)
615
except self.errors.ConfigurationError as e:
616
self.end_msg(kw['errmsg'], 'YELLOW')
620
self.fatal('The configuration failed')
623
self.end_msg(self.ret_msg(kw['okmsg'], kw))
625
ret = self.post_check(*k, **kw)
627
self.fatal('The configuration failed %r' % ret)
630
class test_exec(Task.Task):
632
A task for executing a programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`.
636
if getattr(self.generator, 'rpath', None):
637
if getattr(self.generator, 'define_ret', False):
638
self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()])
640
self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()])
642
env = self.env.env or {}
643
env.update(dict(os.environ))
644
for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'):
645
env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '')
646
if getattr(self.generator, 'define_ret', False):
647
self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env)
649
self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env)
651
@feature('test_exec')
652
@after_method('apply_link')
653
def test_exec_fun(self):
655
The feature **test_exec** is used to create a task that will to execute the binary
656
created (link task output) during the build. The exit status will be set
657
on the build context, so only one program may have the feature *test_exec*.
658
This is used by configuration tests::
661
conf.check(execute=True)
663
self.create_task('test_exec', self.link_task.outputs[0])
669
def run_c_code(self, *k, **kw):
671
Create a temporary build context to execute a build. A reference to that build
672
context is kept on self.test_bld for debugging purposes, and you should not rely
673
on it too much (read the note on the cache below).
674
The parameters given in the arguments to this function are passed as arguments for
675
a single task generator created in the build. Only three parameters are obligatory:
677
:param features: features to pass to a task generator created in the build
678
:type features: list of string
679
:param compile_filename: file to create for the compilation (default: *test.c*)
680
:type compile_filename: string
681
:param code: code to write in the filename to compile
684
Though this function returns *0* by default, the build may set an attribute named *retval* on the
685
build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example.
687
This function also provides a limited cache. To use it, provide the following option::
690
opt.add_option('--confcache', dest='confcache', default=0,
691
action='count', help='Use a configuration cache')
693
And execute the configuration with the following command-line::
695
$ waf configure --confcache
699
lst = [str(v) for (p, v) in kw.items() if p != 'env']
700
h = Utils.h_list(lst)
701
dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h)
711
self.fatal('cannot use the configuration test folder %r' % dir)
713
cachemode = getattr(Options.options, 'confcache', None)
714
if cachemode == CACHE_RESULTS:
716
proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code'))
717
ret = proj['cache_run_c_code']
721
if isinstance(ret, str) and ret.startswith('Test does not build'):
725
bdir = os.path.join(dir, 'testbuild')
727
if not os.path.exists(bdir):
730
self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir)
735
if kw['compile_filename']:
736
node = bld.srcnode.make_node(kw['compile_filename'])
737
node.write(kw['code'])
739
bld.logger = self.logger
740
bld.all_envs.update(self.all_envs) # not really necessary
743
o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog')
745
for k, v in kw.items():
748
self.to_log("==>\n%s\n<==" % kw['code'])
750
# compile the program
757
except Errors.WafError:
758
ret = 'Test does not build: %s' % Utils.ex_stack()
761
ret = getattr(bld, 'retval', 0)
763
# cache the results each time
764
proj = ConfigSet.ConfigSet()
765
proj['cache_run_c_code'] = ret
766
proj.store(os.path.join(dir, 'cache_run_c_code'))
771
def check_cxx(self, *k, **kw):
773
Same as :py:func:`waflib.Tools.c_config.check` but default to the *c++* programming language
775
kw['compiler'] = 'cxx'
776
return self.check(*k, **kw)
779
def check_cc(self, *k, **kw):
781
Same as :py:func:`waflib.Tools.c_config.check` but default to the *c* programming language
784
return self.check(*k, **kw)
787
def define(self, key, val, quote=True):
789
Store a single define and its state into conf.env.DEFINES
791
:param key: define name
794
:type val: int or string
795
:param quote: enclose strings in quotes (yes by default)
798
assert key and isinstance(key, str)
800
if isinstance(val, int) or isinstance(val, float):
803
s = quote and '%s="%s"' or '%s=%s'
804
app = s % (key, str(val))
807
lst = self.env['DEFINES']
809
if x.startswith(ban):
810
lst[lst.index(x)] = app
813
self.env.append_value('DEFINES', app)
815
self.env.append_unique(DEFKEYS, key)
818
def undefine(self, key):
820
Remove a define from conf.env.DEFINES
822
:param key: define name
825
assert key and isinstance(key, str)
828
lst = [x for x in self.env['DEFINES'] if not x.startswith(ban)]
829
self.env['DEFINES'] = lst
830
self.env.append_unique(DEFKEYS, key)
833
def define_cond(self, key, val):
835
Conditionally define a name::
838
conf.define_cond('A', True)
840
# if val: conf.define('A', 1)
841
# else: conf.undefine('A')
843
:param key: define name
846
:type val: int or string
848
assert key and isinstance(key, str)
856
def is_defined(self, key):
858
:param key: define name
860
:return: True if the define is set
863
assert key and isinstance(key, str)
866
for x in self.env['DEFINES']:
867
if x.startswith(ban):
872
def get_define(self, key):
874
:param key: define name
876
:return: the value of a previously stored define or None if it is not set
878
assert key and isinstance(key, str)
881
for x in self.env['DEFINES']:
882
if x.startswith(ban):
887
def have_define(self, key):
889
:param key: define name
891
:return: the input key prefixed by *HAVE_* and substitute any invalid characters.
894
return self.__dict__.get('HAVE_PAT', 'HAVE_%s') % Utils.quote_define_name(key)
897
def write_config_header(self, configfile='', guard='', top=False, env=None, defines=True, headers=False, remove=True):
899
Write a configuration header containing defines and includes::
903
cnf.write_config_header('config.h')
905
:param configfile: relative path to the file to create
906
:type configfile: string
907
:param env: config set to read the definitions from (default is conf.env)
908
:type env: :py:class:`waflib.ConfigSet.ConfigSet`
909
:param top: write the configuration header from the build directory (default is from the current path)
911
:param defines: add the defines (yes by default)
913
:param headers: add #include in the file
915
:param remove: remove the defines after they are added (yes by default)
918
if not configfile: configfile = WAF_CONFIG_H
919
waf_guard = guard or '_%s_WAF' % Utils.quote_define_name(configfile)
921
node = top and self.bldnode or self.path.get_bld()
922
node = node.make_node(configfile)
925
lst = ['/* WARNING! All changes made to this file will be lost! */\n']
926
lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard))
927
lst.append(self.get_config_header(defines, headers))
928
lst.append('\n#endif /* %s */\n' % waf_guard)
930
node.write('\n'.join(lst))
932
env = env or self.env
934
# config files are not removed on "waf clean"
935
env.append_unique(Build.CFG_FILES, [node.abspath()])
938
for key in self.env[DEFKEYS]:
940
self.env[DEFKEYS] = []
943
def get_config_header(self, defines=True, headers=False):
945
Create the contents of a ``config.h`` file from the defines and includes
946
set in conf.env.define_key / conf.env.include_key. No include guards are added.
948
:param defines: write the defines values
950
:param headers: write the headers
952
:return: the contents of a ``config.h`` file
957
for x in self.env[INCKEYS]:
958
lst.append('#include <%s>' % x)
961
for x in self.env[DEFKEYS]:
962
if self.is_defined(x):
963
val = self.get_define(x)
964
lst.append('#define %s %s' % (x, val))
966
lst.append('/* #undef %s */' % x)
967
return "\n".join(lst)
970
def cc_add_flags(conf):
972
Read the CFLAGS/CPPFLAGS from os.environ and add to conf.env.CFLAGS
974
conf.add_os_flags('CPPFLAGS', 'CFLAGS')
975
conf.add_os_flags('CFLAGS')
978
def cxx_add_flags(conf):
980
Read the CXXFLAGS/CPPFLAGS and add to conf.env.CXXFLAGS
982
conf.add_os_flags('CPPFLAGS', 'CXXFLAGS')
983
conf.add_os_flags('CXXFLAGS')
986
def link_add_flags(conf):
988
Read the LINKFLAGS/LDFLAGS and add to conf.env.LDFLAGS
990
conf.add_os_flags('LINKFLAGS')
991
conf.add_os_flags('LDFLAGS', 'LINKFLAGS')
994
def cc_load_tools(conf):
998
if not conf.env.DEST_OS:
999
conf.env.DEST_OS = Utils.unversioned_sys_platform()
1003
def cxx_load_tools(conf):
1007
if not conf.env.DEST_OS:
1008
conf.env.DEST_OS = Utils.unversioned_sys_platform()
1012
def get_cc_version(conf, cc, gcc=False, icc=False):
1014
Run the preprocessor to determine the compiler version
1016
The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env*
1018
cmd = cc + ['-dM', '-E', '-']
1019
env = conf.env.env or None
1021
p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env)
1022
p.stdin.write('\n'.encode())
1023
out = p.communicate()[0]
1025
conf.fatal('Could not determine the compiler version %r' % cmd)
1027
if not isinstance(out, str):
1028
out = out.decode(sys.stdout.encoding)
1031
if out.find('__INTEL_COMPILER') >= 0:
1032
conf.fatal('The intel compiler pretends to be gcc')
1033
if out.find('__GNUC__') < 0:
1034
conf.fatal('Could not determine the compiler type')
1036
if icc and out.find('__INTEL_COMPILER') < 0:
1037
conf.fatal('Not icc/icpc')
1041
out = out.split('\n')
1043
lst = shlex.split(line)
1053
return var in k and k[var] != '0'
1055
# Some documentation is available at http://predef.sourceforge.net
1056
# The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns.
1057
if not conf.env.DEST_OS:
1058
conf.env.DEST_OS = ''
1059
for i in MACRO_TO_DESTOS:
1061
conf.env.DEST_OS = MACRO_TO_DESTOS[i]
1064
if isD('__APPLE__') and isD('__MACH__'):
1065
conf.env.DEST_OS = 'darwin'
1066
elif isD('__unix__'): # unix must be tested last as it's a generic fallback
1067
conf.env.DEST_OS = 'generic'
1070
conf.env.DEST_BINFMT = 'elf'
1071
elif isD('__WINNT__') or isD('__CYGWIN__'):
1072
conf.env.DEST_BINFMT = 'pe'
1073
conf.env.LIBDIR = conf.env['PREFIX'] + '/bin'
1074
elif isD('__APPLE__'):
1075
conf.env.DEST_BINFMT = 'mac-o'
1077
if not conf.env.DEST_BINFMT:
1078
# Infer the binary format from the os name.
1079
conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS)
1081
for i in MACRO_TO_DEST_CPU:
1083
conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i]
1086
Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')]))
1088
ver = k['__INTEL_COMPILER']
1089
conf.env['CC_VERSION'] = (ver[:-2], ver[-2], ver[-1])
1091
conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__'])
1095
def get_xlc_version(conf, cc):
1096
"""Get the compiler version"""
1098
version_re = re.compile(r"IBM XL C/C\+\+.*, V(?P<major>\d*)\.(?P<minor>\d*)", re.I).search
1099
cmd = cc + ['-qversion']
1102
out, err = conf.cmd_and_log(cmd, output=0)
1103
except Errors.WafError:
1104
conf.fatal('Could not find xlc %r' % cmd)
1105
if out: match = version_re(out)
1106
else: match = version_re(err)
1108
conf.fatal('Could not determine the XLC version.')
1109
k = match.groupdict()
1110
conf.env['CC_VERSION'] = (k['major'], k['minor'])
1112
# ============ the --as-needed flag should added during the configuration, not at runtime =========
1115
def add_as_needed(self):
1117
Add ``--as-needed`` to the *LINKFLAGS*
1119
if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME):
1120
self.env.append_unique('LINKFLAGS', '--as-needed')
1122
# ============ parallel configuration
1124
class cfgtask(Task.TaskBase):
1126
A task that executes configuration tests
1127
make sure that the checks write to conf.env in a thread-safe manner
1129
for the moment it only executes conf.check
1134
def runnable_status(self):
1139
bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath())
1142
bld.in_msg = 1 # suppress top-level start_msg
1143
bld.logger = self.logger
1145
bld.check(**self.args)
1150
def multicheck(self, *k, **kw):
1152
Use tuples to perform parallel configuration tests
1154
self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)))
1159
self.cache_global = Options.cache_global
1160
self.nocache = Options.options.nocache
1161
self.returned_tasks = []
1164
def to_log(self, *k, **kw):
1170
x = cfgtask(bld=bld)
1177
# bind a logger that will keep the info in memory
1178
x.logger = Logs.make_mem_logger(str(id(x)), self.logger)
1184
p = Runner.Parallel(bld, Options.options.jobs)
1188
# flush the logs in order into the config.log
1190
x.logger.memhandler.flush()
1193
if x.hasrun != Task.SUCCESS:
1194
self.end_msg(kw.get('errmsg', 'no'), color='YELLOW')
1195
self.fatal(kw.get('fatalmsg', None) or 'One of the tests has failed, see the config.log for more information')