3 # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
7 # Thomas Nagy, 2005-2016 (ita)
10 C/C++/D configuration helpers
13 from __future__ import with_statement
16 from waflib import Build, Utils, Task, Options, Logs, Errors, Runner
17 from waflib.TaskGen import after_method, feature
18 from waflib.Configure import conf
20 WAF_CONFIG_H = 'config.h'
21 """default name for the config.h file"""
23 DEFKEYS = 'define_key'
24 INCKEYS = 'include_key'
27 'atleast-version': '>=',
28 'exact-version': '==',
33 int main(int argc, char **argv) {
35 (void)argc; (void)argv;
40 """Code template for checking for functions"""
43 int main(int argc, char **argv) {
44 (void)argc; (void)argv;
45 if ((%(type_name)s *) 0) return 0;
46 if (sizeof (%(type_name)s)) return 0;
50 """Code template for checking for types"""
52 SNIP_EMPTY_PROGRAM = '''
53 int main(int argc, char **argv) {
54 (void)argc; (void)argv;
60 int main(int argc, char **argv) {
62 (void)argc; (void)argv;
63 off = (char*) &((%(type_name)s*)0)->%(field_name)s;
64 return (size_t) off < sizeof(%(type_name)s);
69 '__linux__' : 'linux',
70 '__GNU__' : 'gnu', # hurd
71 '__FreeBSD__' : 'freebsd',
72 '__NetBSD__' : 'netbsd',
73 '__OpenBSD__' : 'openbsd',
78 '__CYGWIN__' : 'cygwin',
79 '__MSYS__' : 'cygwin',
83 # Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file.
84 '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin',
85 '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone
87 '__native_client__' : 'nacl' # google native client platform
91 '__x86_64__' : 'x86_64',
92 '__amd64__' : 'x86_64',
96 '__sparc__' : 'sparc',
97 '__alpha__' : 'alpha',
98 '__aarch64__' : 'aarch64',
99 '__thumb__' : 'thumb',
102 '__powerpc__' : 'powerpc',
103 '__ppc__' : 'powerpc',
104 '__convex__' : 'convex',
106 '__s390x__' : 's390x',
109 '__xtensa__' : 'xtensa',
113 def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=None):
115 Parses flags from the input lines, and adds them to the relevant use variables::
118 conf.parse_flags('-O3', 'FOO')
119 # conf.env.CXXFLAGS_FOO = ['-O3']
120 # conf.env.CFLAGS_FOO = ['-O3']
124 :param uselib_store: where to add the flags
125 :type uselib_store: string
126 :param env: config set or conf.env by default
127 :type env: :py:class:`waflib.ConfigSet.ConfigSet`
130 assert(isinstance(line, str))
132 env = env or self.env
138 posix = ('\\ ' in line) or ('\\\\' in line)
140 lex = shlex.shlex(line, posix=posix)
141 lex.whitespace_split = True
145 # append_unique is not always possible
146 # for example, apple flags may require both -arch i386 and -arch ppc
147 uselib = uselib_store
149 env.append_value('%s_%s' % (var, uselib), val)
151 env.append_unique('%s_%s' % (var, uselib), val)
158 if st == '-I' or st == '/I':
163 tmp = [x, lst.pop(0)]
166 elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but..
173 prefix = 'STLIB' if (force_static or static) else 'LIB'
178 prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH'
180 elif x.startswith('/LIBPATH:'):
181 prefix = 'STLIBPATH' if (force_static or static) else 'LIBPATH'
182 appu(prefix, x.replace('/LIBPATH:', ''))
183 elif x.startswith('-std='):
184 prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS'
186 elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'):
190 elif x == '-framework':
191 appu('FRAMEWORK', lst.pop(0))
192 elif x.startswith('-F'):
193 appu('FRAMEWORKPATH', x[2:])
194 elif x == '-Wl,-rpath' or x == '-Wl,-R':
195 app('RPATH', lst.pop(0).lstrip('-Wl,'))
196 elif x.startswith('-Wl,-R,'):
198 elif x.startswith('-Wl,-R'):
200 elif x.startswith('-Wl,-rpath,'):
202 elif x == '-Wl,-Bstatic' or x == '-Bstatic':
204 elif x == '-Wl,-Bdynamic' or x == '-Bdynamic':
206 elif x.startswith('-Wl') or x in ('-rdynamic', '-pie'):
208 elif x.startswith(('-m', '-f', '-dynamic', '-O')):
211 elif x.startswith('-bundle'):
213 elif x.startswith(('-undefined', '-Xlinker')):
215 app('LINKFLAGS', [x, arg])
216 elif x.startswith(('-arch', '-isysroot')):
217 tmp = [x, lst.pop(0)]
220 app('LINKFLAGS', tmp)
221 elif x.endswith(('.a', '.so', '.dylib', '.lib')):
222 appu('LINKFLAGS', x) # not cool, #762
224 self.to_log('Unhandled flag %r' % x)
227 def validate_cfg(self, kw):
229 Searches for the program *pkg-config* if missing, and validates the
230 parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`.
232 :param path: the **-config program to use** (default is *pkg-config*)
233 :type path: list of string
234 :param msg: message to display to describe the test executed
236 :param okmsg: message to display when the test is successful
238 :param errmsg: message to display in case of error
242 if not self.env.PKGCONFIG:
243 self.find_program('pkg-config', var='PKGCONFIG')
244 kw['path'] = self.env.PKGCONFIG
247 if 'atleast_pkgconfig_version' in kw:
249 kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version']
252 if not 'okmsg' in kw:
254 if not 'errmsg' in kw:
255 kw['errmsg'] = 'not found'
257 if 'modversion' in kw:
259 kw['msg'] = 'Checking for %r version' % kw['modversion']
260 if not 'uselib_store' in kw:
261 kw['uselib_store'] = kw['modversion']
262 if not 'define_name' in kw:
263 kw['define_name'] = '%s_VERSION' % Utils.quote_define_name(kw['uselib_store'])
266 if not 'package' in kw:
267 raise ValueError('a package name is required')
269 if not 'uselib_store' in kw:
270 kw['uselib_store'] = kw['package'].upper()
272 if not 'define_name' in kw:
273 kw['define_name'] = self.have_define(kw['uselib_store'])
276 kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path'])
279 # Gotcha: only one predicate is allowed at a time
280 # TODO remove in waf 2.0
281 y = x.replace('-', '_')
283 package = kw['package']
285 Logs.warn('Passing %r to conf.check_cfg() is obsolete, pass parameters directly, eg:', y)
286 Logs.warn(" conf.check_cfg(package='%s', args=['--libs', '--cflags', '%s >= 1.6'])", package, package)
288 kw['msg'] = 'Checking for %r %s %s' % (package, cfg_ver[x], kw[y])
292 def exec_cfg(self, kw):
294 Executes ``pkg-config`` or other ``-config`` applications to colect configuration flags:
296 * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return
297 * if modversion is given, then return the module version
298 * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable
300 :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests)
301 :type atleast_pkgconfig_version: string
302 :param package: package name, for example *gtk+-2.0*
303 :type package: string
304 :param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables.
305 :type uselib_store: string
306 :param modversion: if provided, return the version of the given module and define *name*\_VERSION
307 :type modversion: string
308 :param args: arguments to give to *package* when retrieving flags
309 :type args: list of string
310 :param variables: return the values of particular variables
311 :type variables: list of string
312 :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES)
313 :type define_variable: dict(string: string)
316 path = Utils.to_list(kw['path'])
317 env = self.env.env or None
318 if kw.get('pkg_config_path'):
320 env = dict(self.environ)
321 env['PKG_CONFIG_PATH'] = kw['pkg_config_path']
324 define_name = kw['define_name']
325 # by default, add HAVE_X to the config.h, else provide DEFINES_X for use=X
326 if kw.get('global_define', 1):
327 self.define(define_name, 1, False)
329 self.env.append_unique('DEFINES_%s' % kw['uselib_store'], "%s=1" % define_name)
331 if kw.get('add_have_to_env', 1):
332 self.env[define_name] = 1
335 if 'atleast_pkgconfig_version' in kw:
336 cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']]
337 self.cmd_and_log(cmd, env=env)
338 if not 'okmsg' in kw:
343 # TODO remove in waf 2.0
344 y = x.replace('-', '_')
346 self.cmd_and_log(path + ['--%s=%s' % (x, kw[y]), kw['package']], env=env)
347 if not 'okmsg' in kw:
352 # single version for a module
353 if 'modversion' in kw:
354 version = self.cmd_and_log(path + ['--modversion', kw['modversion']], env=env).strip()
355 self.define(kw['define_name'], version)
360 defi = kw.get('define_variable')
362 defi = self.env.PKG_CONFIG_DEFINES or {}
363 for key, val in defi.items():
364 lst.append('--define-variable=%s=%s' % (key, val))
366 static = kw.get('force_static', False)
368 args = Utils.to_list(kw['args'])
369 if '--static' in args or '--static-libs' in args:
373 # tools like pkgconf expect the package argument after the -- ones -_-
374 lst.extend(Utils.to_list(kw['package']))
376 # retrieving variables of a module
377 if 'variables' in kw:
378 v_env = kw.get('env', self.env)
379 vars = Utils.to_list(kw['variables'])
381 val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip()
382 var = '%s_%s' % (kw['uselib_store'], v)
384 if not 'okmsg' in kw:
388 # so we assume the command-line will output flags to be parsed afterwards
389 ret = self.cmd_and_log(lst, env=env)
390 if not 'okmsg' in kw:
394 self.parse_flags(ret, kw['uselib_store'], kw.get('env', self.env), force_static=static, posix=kw.get('posix'))
398 def check_cfg(self, *k, **kw):
400 Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc).
401 This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg`
406 conf.load('compiler_c')
407 conf.check_cfg(package='glib-2.0', args='--libs --cflags')
408 conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0',
409 args='--cflags --libs')
410 conf.check_cfg(package='pango')
411 conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs'])
412 conf.check_cfg(package='pango',
413 args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'],
414 msg="Checking for 'pango 0.1.0'")
415 conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL')
416 conf.check_cfg(path='mpicc', args='--showme:compile --showme:link',
417 package='', uselib_store='OPEN_MPI', mandatory=False)
419 conf.check_cfg(package='gtk+-2.0', variables=['includedir', 'prefix'], uselib_store='FOO')
420 print(conf.env.FOO_includedir)
424 kw['package'] = lst[0]
425 kw['args'] = ' '.join(lst[1:])
427 self.validate_cfg(kw)
429 self.start_msg(kw['msg'], **kw)
432 ret = self.exec_cfg(kw)
433 except self.errors.WafError:
435 self.end_msg(kw['errmsg'], 'YELLOW', **kw)
439 self.fatal('The configuration failed')
445 self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw)
451 Build function that is used for running configuration tests with ``conf.check()``
453 if bld.kw['compile_filename']:
454 node = bld.srcnode.make_node(bld.kw['compile_filename'])
455 node.write(bld.kw['code'])
457 o = bld(features=bld.kw['features'], source=bld.kw['compile_filename'], target='testprog')
459 for k, v in bld.kw.items():
462 if not bld.kw.get('quiet'):
463 bld.conf.to_log("==>\n%s\n<==" % bld.kw['code'])
466 def validate_c(self, kw):
468 Pre-checks the parameters that will be given to :py:func:`waflib.Configure.run_build`
470 :param compiler: c or cxx (tries to guess what is best)
471 :type compiler: string
472 :param type: cprogram, cshlib, cstlib - not required if *features are given directly*
473 :type type: binary to create
474 :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib``
475 :type feature: list of string
476 :param fragment: provide a piece of code for the test (default is to let the system create one)
477 :type fragment: string
478 :param uselib_store: define variables after the test is executed (IMPORTANT!)
479 :type uselib_store: string
480 :param use: parameters to use for building (just like the normal *use* keyword)
481 :type use: list of string
482 :param define_name: define to set when the check is over
483 :type define_name: string
484 :param execute: execute the resulting binary
486 :param define_ret: if execute is set to True, use the execution output in both the define and the return value
487 :type define_ret: bool
488 :param header_name: check for a particular header
489 :type header_name: string
490 :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers
491 :type auto_add_header_name: bool
494 if not 'build_fun' in kw:
495 kw['build_fun'] = build_fun
498 kw['env'] = self.env.derive()
501 if not 'compiler' in kw and not 'features' in kw:
503 if env.CXX_NAME and Task.classes.get('cxx'):
504 kw['compiler'] = 'cxx'
506 self.fatal('a c++ compiler is required')
509 self.fatal('a c compiler is required')
511 if not 'compile_mode' in kw:
512 kw['compile_mode'] = 'c'
513 if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx':
514 kw['compile_mode'] = 'cxx'
517 kw['type'] = 'cprogram'
519 if not 'features' in kw:
520 if not 'header_name' in kw or kw.get('link_header_test', True):
521 kw['features'] = [kw['compile_mode'], kw['type']] # "c ccprogram"
523 kw['features'] = [kw['compile_mode']]
525 kw['features'] = Utils.to_list(kw['features'])
527 if not 'compile_filename' in kw:
528 kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '')
531 if 'header_name' in dct:
532 dct = Utils.to_list(dct['header_name'])
533 return ''.join(['#include <%s>\n' % x for x in dct])
537 if 'framework_name' in kw:
538 fwkname = kw['framework_name']
539 if not 'uselib_store' in kw:
540 kw['uselib_store'] = fwkname.upper()
541 if not kw.get('no_header', False):
542 if not 'header_name' in kw:
543 kw['header_name'] = []
544 fwk = '%s/%s.h' % (fwkname, fwkname)
545 if kw.get('remove_dot_h'):
547 kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk]
549 kw['msg'] = 'Checking for framework %s' % fwkname
550 kw['framework'] = fwkname
551 #kw['frameworkpath'] = set it yourself
553 if 'function_name' in kw:
554 fu = kw['function_name']
556 kw['msg'] = 'Checking for function %s' % fu
557 kw['code'] = to_header(kw) + SNIP_FUNCTION % fu
558 if not 'uselib_store' in kw:
559 kw['uselib_store'] = fu.upper()
560 if not 'define_name' in kw:
561 kw['define_name'] = self.have_define(fu)
563 elif 'type_name' in kw:
565 if not 'header_name' in kw:
566 kw['header_name'] = 'stdint.h'
567 if 'field_name' in kw:
568 field = kw['field_name']
569 kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field}
571 kw['msg'] = 'Checking for field %s in %s' % (field, tu)
572 if not 'define_name' in kw:
573 kw['define_name'] = self.have_define((tu + '_' + field).upper())
575 kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu}
577 kw['msg'] = 'Checking for type %s' % tu
578 if not 'define_name' in kw:
579 kw['define_name'] = self.have_define(tu.upper())
581 elif 'header_name' in kw:
583 kw['msg'] = 'Checking for header %s' % kw['header_name']
585 l = Utils.to_list(kw['header_name'])
586 assert len(l), 'list of headers in header_name is empty'
588 kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM
589 if not 'uselib_store' in kw:
590 kw['uselib_store'] = l[0].upper()
591 if not 'define_name' in kw:
592 kw['define_name'] = self.have_define(l[0])
596 kw['msg'] = 'Checking for library %s' % kw['lib']
597 if not 'uselib_store' in kw:
598 kw['uselib_store'] = kw['lib'].upper()
602 kw['msg'] = 'Checking for static library %s' % kw['stlib']
603 if not 'uselib_store' in kw:
604 kw['uselib_store'] = kw['stlib'].upper()
607 # an additional code fragment may be provided to replace the predefined code
609 kw['code'] = kw['fragment']
611 kw['msg'] = 'Checking for code snippet'
612 if not 'errmsg' in kw:
615 for (flagsname,flagstype) in (('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')):
618 kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname])
619 if not 'errmsg' in kw:
622 if not 'execute' in kw:
623 kw['execute'] = False
625 kw['features'].append('test_exec')
626 kw['chmod'] = Utils.O755
628 if not 'errmsg' in kw:
629 kw['errmsg'] = 'not found'
631 if not 'okmsg' in kw:
635 kw['code'] = SNIP_EMPTY_PROGRAM
637 # if there are headers to append automatically to the next tests
638 if self.env[INCKEYS]:
639 kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code']
641 # in case defines lead to very long command-lines
642 if kw.get('merge_config_header', False) or env.merge_config_header:
643 kw['code'] = '%s\n\n%s' % (self.get_config_header(), kw['code'])
644 env.DEFINES = [] # modify the copy
646 if not kw.get('success'): kw['success'] = None
648 if 'define_name' in kw:
649 self.undefine(kw['define_name'])
651 self.fatal('missing "msg" in conf.check(...)')
654 def post_check(self, *k, **kw):
656 Sets the variables after a test executed in
657 :py:func:`waflib.Tools.c_config.check` was run successfully
661 if kw['success'] is not None:
662 if kw.get('define_ret', False):
663 is_success = kw['success']
665 is_success = (kw['success'] == 0)
667 is_success = (kw['success'] == 0)
669 if kw.get('define_name'):
670 # TODO this is still way too complicated
671 comment = kw.get('comment', '')
672 define_name = kw['define_name']
673 if kw['execute'] and kw.get('define_ret') and isinstance(is_success, str):
674 if kw.get('global_define', 1):
675 self.define(define_name, is_success, quote=kw.get('quote', 1), comment=comment)
677 if kw.get('quote', 1):
678 succ = '"%s"' % is_success
680 succ = int(is_success)
681 val = '%s=%s' % (define_name, succ)
682 var = 'DEFINES_%s' % kw['uselib_store']
683 self.env.append_value(var, val)
685 if kw.get('global_define', 1):
686 self.define_cond(define_name, is_success, comment=comment)
688 var = 'DEFINES_%s' % kw['uselib_store']
689 self.env.append_value(var, '%s=%s' % (define_name, int(is_success)))
691 # define conf.env.HAVE_X to 1
692 if kw.get('add_have_to_env', 1):
693 if kw.get('uselib_store'):
694 self.env[self.have_define(kw['uselib_store'])] = 1
695 elif kw['execute'] and kw.get('define_ret'):
696 self.env[define_name] = is_success
698 self.env[define_name] = int(is_success)
700 if 'header_name' in kw:
701 if kw.get('auto_add_header_name', False):
702 self.env.append_value(INCKEYS, Utils.to_list(kw['header_name']))
704 if is_success and 'uselib_store' in kw:
705 from waflib.Tools import ccroot
706 # See get_uselib_vars in ccroot.py
708 for x in kw['features']:
709 if x in ccroot.USELIB_VARS:
710 _vars |= ccroot.USELIB_VARS[x]
715 self.env.append_value(k + '_' + kw['uselib_store'], kw[x])
719 def check(self, *k, **kw):
721 Performs a configuration test by calling :py:func:`waflib.Configure.run_build`.
722 For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`.
723 To force a specific compiler, pass ``compiler='c'`` or ``compiler='cxx'`` to the list of arguments
725 Besides build targets, complete builds can be given through a build function. All files will
726 be written to a temporary directory::
729 lib_node = bld.srcnode.make_node('libdir/liblc1.c')
730 lib_node.parent.mkdir()
731 lib_node.write('#include <stdio.h>\\nint lib_func(void) { FILE *f = fopen("foo", "r");}\\n', 'w')
732 bld(features='c cshlib', source=[lib_node], linkflags=conf.env.EXTRA_LDFLAGS, target='liblc')
733 conf.check(build_fun=build, msg=msg)
736 self.start_msg(kw['msg'], **kw)
739 ret = self.run_build(*k, **kw)
740 except self.errors.ConfigurationError:
741 self.end_msg(kw['errmsg'], 'YELLOW', **kw)
745 self.fatal('The configuration failed')
749 ret = self.post_check(*k, **kw)
751 self.end_msg(kw['errmsg'], 'YELLOW', **kw)
752 self.fatal('The configuration failed %r' % ret)
754 self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw)
757 class test_exec(Task.Task):
759 A task that runs programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`.
763 if getattr(self.generator, 'rpath', None):
764 if getattr(self.generator, 'define_ret', False):
765 self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()])
767 self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()])
769 env = self.env.env or {}
770 env.update(dict(os.environ))
771 for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'):
772 env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '')
773 if getattr(self.generator, 'define_ret', False):
774 self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env)
776 self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env)
778 @feature('test_exec')
779 @after_method('apply_link')
780 def test_exec_fun(self):
782 The feature **test_exec** is used to create a task that will to execute the binary
783 created (link task output) during the build. The exit status will be set
784 on the build context, so only one program may have the feature *test_exec*.
785 This is used by configuration tests::
788 conf.check(execute=True)
790 self.create_task('test_exec', self.link_task.outputs[0])
793 def check_cxx(self, *k, **kw):
795 Runs a test with a task generator of the form::
797 conf.check(features='cxx cxxprogram', ...)
799 kw['compiler'] = 'cxx'
800 return self.check(*k, **kw)
803 def check_cc(self, *k, **kw):
805 Runs a test with a task generator of the form::
807 conf.check(features='c cprogram', ...)
810 return self.check(*k, **kw)
813 def set_define_comment(self, key, comment):
815 Sets a comment that will appear in the configuration header
818 :type comment: string
820 coms = self.env.DEFINE_COMMENTS
822 coms = self.env.DEFINE_COMMENTS = {}
823 coms[key] = comment or ''
826 def get_define_comment(self, key):
828 Returns the comment associated to a define
832 coms = self.env.DEFINE_COMMENTS or {}
833 return coms.get(key, '')
836 def define(self, key, val, quote=True, comment=''):
838 Stores a single define and its state into ``conf.env.DEFINES``. The value is cast to an integer (0/1).
840 :param key: define name
843 :type val: int or string
844 :param quote: enclose strings in quotes (yes by default)
847 assert isinstance(key, str)
852 elif val in (False, None):
855 if isinstance(val, int) or isinstance(val, float):
858 s = quote and '%s="%s"' or '%s=%s'
859 app = s % (key, str(val))
862 lst = self.env.DEFINES
864 if x.startswith(ban):
865 lst[lst.index(x)] = app
868 self.env.append_value('DEFINES', app)
870 self.env.append_unique(DEFKEYS, key)
871 self.set_define_comment(key, comment)
874 def undefine(self, key, comment=''):
876 Removes a global define from ``conf.env.DEFINES``
878 :param key: define name
881 assert isinstance(key, str)
885 lst = [x for x in self.env.DEFINES if not x.startswith(ban)]
886 self.env.DEFINES = lst
887 self.env.append_unique(DEFKEYS, key)
888 self.set_define_comment(key, comment)
891 def define_cond(self, key, val, comment=''):
893 Conditionally defines a name::
896 conf.define_cond('A', True)
898 # if val: conf.define('A', 1)
899 # else: conf.undefine('A')
901 :param key: define name
904 :type val: int or string
906 assert isinstance(key, str)
910 self.define(key, 1, comment=comment)
912 self.undefine(key, comment=comment)
915 def is_defined(self, key):
917 Indicates whether a particular define is globally set in ``conf.env.DEFINES``.
919 :param key: define name
921 :return: True if the define is set
924 assert key and isinstance(key, str)
927 for x in self.env.DEFINES:
928 if x.startswith(ban):
933 def get_define(self, key):
935 Returns the value of an existing define, or None if not found
937 :param key: define name
941 assert key and isinstance(key, str)
944 for x in self.env.DEFINES:
945 if x.startswith(ban):
950 def have_define(self, key):
952 Returns a variable suitable for command-line or header use by removing invalid characters
953 and prefixing it with ``HAVE_``
955 :param key: define name
957 :return: the input key prefixed by *HAVE_* and substitute any invalid characters.
960 return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key)
963 def write_config_header(self, configfile='', guard='', top=False, defines=True, headers=False, remove=True, define_prefix=''):
965 Writes a configuration header containing defines and includes::
969 cnf.write_config_header('config.h')
971 This function only adds include guards (if necessary), consult
972 :py:func:`waflib.Tools.c_config.get_config_header` for details on the body.
974 :param configfile: path to the file to create (relative or absolute)
975 :type configfile: string
976 :param guard: include guard name to add, by default it is computed from the file name
978 :param top: write the configuration header from the build directory (default is from the current path)
980 :param defines: add the defines (yes by default)
982 :param headers: add #include in the file
984 :param remove: remove the defines after they are added (yes by default, works like in autoconf)
986 :type define_prefix: string
987 :param define_prefix: prefix all the defines in the file with a particular prefix
989 if not configfile: configfile = WAF_CONFIG_H
990 waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile)
992 node = top and self.bldnode or self.path.get_bld()
993 node = node.make_node(configfile)
996 lst = ['/* WARNING! All changes made to this file will be lost! */\n']
997 lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard))
998 lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix))
999 lst.append('\n#endif /* %s */\n' % waf_guard)
1001 node.write('\n'.join(lst))
1003 # config files must not be removed on "waf clean"
1004 self.env.append_unique(Build.CFG_FILES, [node.abspath()])
1007 for key in self.env[DEFKEYS]:
1009 self.env[DEFKEYS] = []
1012 def get_config_header(self, defines=True, headers=False, define_prefix=''):
1014 Creates the contents of a ``config.h`` file from the defines and includes
1015 set in conf.env.define_key / conf.env.include_key. No include guards are added.
1017 A prelude will be added from the variable env.WAF_CONFIG_H_PRELUDE if provided. This
1018 can be used to insert complex macros or include guards::
1020 def configure(conf):
1021 conf.env.WAF_CONFIG_H_PRELUDE = '#include <unistd.h>\\n'
1022 conf.write_config_header('config.h')
1024 :param defines: write the defines values
1026 :param headers: write include entries for each element in self.env.INCKEYS
1028 :type define_prefix: string
1029 :param define_prefix: prefix all the defines with a particular prefix
1030 :return: the contents of a ``config.h`` file
1035 if self.env.WAF_CONFIG_H_PRELUDE:
1036 lst.append(self.env.WAF_CONFIG_H_PRELUDE)
1039 for x in self.env[INCKEYS]:
1040 lst.append('#include <%s>' % x)
1044 for k in self.env.DEFINES:
1045 a, _, b = k.partition('=')
1048 for k in self.env[DEFKEYS]:
1049 caption = self.get_define_comment(k)
1051 caption = ' /* %s */' % caption
1053 txt = '#define %s%s %s%s' % (define_prefix, k, tbl[k], caption)
1055 txt = '/* #undef %s%s */%s' % (define_prefix, k, caption)
1057 return "\n".join(lst)
1060 def cc_add_flags(conf):
1062 Adds CFLAGS / CPPFLAGS from os.environ to conf.env
1064 conf.add_os_flags('CPPFLAGS', dup=False)
1065 conf.add_os_flags('CFLAGS', dup=False)
1068 def cxx_add_flags(conf):
1070 Adds CXXFLAGS / CPPFLAGS from os.environ to conf.env
1072 conf.add_os_flags('CPPFLAGS', dup=False)
1073 conf.add_os_flags('CXXFLAGS', dup=False)
1076 def link_add_flags(conf):
1078 Adds LINKFLAGS / LDFLAGS from os.environ to conf.env
1080 conf.add_os_flags('LINKFLAGS', dup=False)
1081 conf.add_os_flags('LDFLAGS', dup=False)
1084 def cc_load_tools(conf):
1086 Loads the Waf c extensions
1088 if not conf.env.DEST_OS:
1089 conf.env.DEST_OS = Utils.unversioned_sys_platform()
1093 def cxx_load_tools(conf):
1095 Loads the Waf c++ extensions
1097 if not conf.env.DEST_OS:
1098 conf.env.DEST_OS = Utils.unversioned_sys_platform()
1102 def get_cc_version(conf, cc, gcc=False, icc=False, clang=False):
1104 Runs the preprocessor to determine the gcc/icc/clang version
1106 The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env*
1108 :raise: :py:class:`waflib.Errors.ConfigurationError`
1110 cmd = cc + ['-dM', '-E', '-']
1111 env = conf.env.env or None
1113 out, err = conf.cmd_and_log(cmd, output=0, input='\n', env=env)
1115 conf.fatal('Could not determine the compiler version %r' % cmd)
1118 if out.find('__INTEL_COMPILER') >= 0:
1119 conf.fatal('The intel compiler pretends to be gcc')
1120 if out.find('__GNUC__') < 0 and out.find('__clang__') < 0:
1121 conf.fatal('Could not determine the compiler type')
1123 if icc and out.find('__INTEL_COMPILER') < 0:
1124 conf.fatal('Not icc/icpc')
1126 if clang and out.find('__clang__') < 0:
1127 conf.fatal('Not clang/clang++')
1128 if not clang and out.find('__clang__') >= 0:
1129 conf.fatal('Could not find gcc/g++ (only Clang), if renamed try eg: CC=gcc48 CXX=g++48 waf configure')
1132 if icc or gcc or clang:
1133 out = out.splitlines()
1135 lst = shlex.split(line)
1144 # Some documentation is available at http://predef.sourceforge.net
1145 # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns.
1146 if not conf.env.DEST_OS:
1147 conf.env.DEST_OS = ''
1148 for i in MACRO_TO_DESTOS:
1150 conf.env.DEST_OS = MACRO_TO_DESTOS[i]
1153 if isD('__APPLE__') and isD('__MACH__'):
1154 conf.env.DEST_OS = 'darwin'
1155 elif isD('__unix__'): # unix must be tested last as it's a generic fallback
1156 conf.env.DEST_OS = 'generic'
1159 conf.env.DEST_BINFMT = 'elf'
1160 elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'):
1161 conf.env.DEST_BINFMT = 'pe'
1162 conf.env.LIBDIR = conf.env.BINDIR
1163 elif isD('__APPLE__'):
1164 conf.env.DEST_BINFMT = 'mac-o'
1166 if not conf.env.DEST_BINFMT:
1167 # Infer the binary format from the os name.
1168 conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS)
1170 for i in MACRO_TO_DEST_CPU:
1172 conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i]
1175 Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')]))
1177 ver = k['__INTEL_COMPILER']
1178 conf.env.CC_VERSION = (ver[:-2], ver[-2], ver[-1])
1180 if isD('__clang__') and isD('__clang_major__'):
1181 conf.env.CC_VERSION = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__'])
1183 # older clang versions and gcc
1184 conf.env.CC_VERSION = (k['__GNUC__'], k['__GNUC_MINOR__'], k.get('__GNUC_PATCHLEVEL__', '0'))
1188 def get_xlc_version(conf, cc):
1190 Returns the Aix compiler version
1192 :raise: :py:class:`waflib.Errors.ConfigurationError`
1194 cmd = cc + ['-qversion']
1196 out, err = conf.cmd_and_log(cmd, output=0)
1197 except Errors.WafError:
1198 conf.fatal('Could not find xlc %r' % cmd)
1200 # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..."
1201 for v in (r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",):
1202 version_re = re.compile(v, re.I).search
1203 match = version_re(out or err)
1205 k = match.groupdict()
1206 conf.env.CC_VERSION = (k['major'], k['minor'])
1209 conf.fatal('Could not determine the XLC version.')
1212 def get_suncc_version(conf, cc):
1214 Returns the Sun compiler version
1216 :raise: :py:class:`waflib.Errors.ConfigurationError`
1220 out, err = conf.cmd_and_log(cmd, output=0)
1221 except Errors.WafError ,e:
1222 # Older versions of the compiler exit with non-zero status when reporting their version
1223 if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')):
1224 conf.fatal('Could not find suncc %r' % cmd)
1228 version = (out or err)
1229 version = version.splitlines()[0]
1231 # cc: Sun C 5.10 SunOS_i386 2009/06/03
1232 # cc: Studio 12.5 Sun C++ 5.14 SunOS_sparc Beta 2015/11/17
1233 # cc: WorkShop Compilers 5.0 98/12/15 C 5.0
1234 version_re = re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P<major>\d*)\.(?P<minor>\d*)', re.I).search
1235 match = version_re(version)
1237 k = match.groupdict()
1238 conf.env.CC_VERSION = (k['major'], k['minor'])
1240 conf.fatal('Could not determine the suncc version.')
1242 # ============ the --as-needed flag should added during the configuration, not at runtime =========
1245 def add_as_needed(self):
1247 Adds ``--as-needed`` to the *LINKFLAGS*
1248 On some platforms, it is a default flag. In some cases (e.g., in NS-3) it is necessary to explicitly disable this feature with `-Wl,--no-as-needed` flag.
1250 if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME):
1251 self.env.append_unique('LINKFLAGS', '-Wl,--as-needed')
1253 # ============ parallel configuration
1255 class cfgtask(Task.TaskBase):
1257 A task that executes build configuration tests (calls conf.check)
1259 Make sure to use locks if concurrent access to the same conf.env data is necessary.
1261 def __init__(self, *k, **kw):
1262 Task.TaskBase.__init__(self, *k, **kw)
1263 self.run_after = set()
1268 def runnable_status(self):
1269 for x in self.run_after:
1271 return Task.ASK_LATER
1275 return Utils.SIG_NIL
1279 bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath())
1282 bld.in_msg = 1 # suppress top-level start_msg
1283 bld.logger = self.logger
1284 bld.multicheck_task = self
1288 bld.test(build_fun=args['func'],
1289 msg=args.get('msg', ''),
1290 okmsg=args.get('okmsg', ''),
1291 errmsg=args.get('errmsg', ''),
1294 args['multicheck_mandatory'] = args.get('mandatory', True)
1295 args['mandatory'] = True
1299 args['mandatory'] = args['multicheck_mandatory']
1304 Task.TaskBase.process(self)
1305 if 'msg' in self.args:
1306 with self.generator.bld.multicheck_lock:
1307 self.conf.start_msg(self.args['msg'])
1308 if self.hasrun == Task.NOT_RUN:
1309 self.conf.end_msg('test cancelled', 'YELLOW')
1310 elif self.hasrun != Task.SUCCESS:
1311 self.conf.end_msg(self.args.get('errmsg', 'no'), 'YELLOW')
1313 self.conf.end_msg(self.args.get('okmsg', 'yes'), 'GREEN')
1316 def multicheck(self, *k, **kw):
1318 Runs configuration tests in parallel; results are printed sequentially at the end of the build
1319 but each test must provide its own msg value to display a line::
1321 def test_build(ctx):
1322 ctx.in_msg = True # suppress console outputs
1323 ctx.check_large_file(mandatory=False)
1326 {'header_name':'stdio.h', 'msg':'... stdio', 'uselib_store':'STDIO', 'global_define':False},
1327 {'header_name':'xyztabcd.h', 'msg':'... optional xyztabcd.h', 'mandatory': False},
1328 {'header_name':'stdlib.h', 'msg':'... stdlib', 'okmsg': 'aye', 'errmsg': 'nope'},
1329 {'func': test_build, 'msg':'... testing an arbitrary build function', 'okmsg':'ok'},
1330 msg = 'Checking for headers in parallel',
1331 mandatory = True, # mandatory tests raise an error at the end
1332 run_all_tests = True, # try running all tests
1335 The configuration tests may modify the values in conf.env in any order, and the define
1336 values can affect configuration tests being executed. It is hence recommended
1337 to provide `uselib_store` values with `global_define=False` to prevent such issues.
1339 self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)), **kw)
1341 # Force a copy so that threads append to the same list at least
1342 # no order is guaranteed, but the values should not disappear at least
1343 for var in ('DEFINES', DEFKEYS):
1344 self.env.append_value(var, [])
1345 self.env.DEFINE_COMMENTS = self.env.DEFINE_COMMENTS or {}
1347 # define a task object that will execute our tests
1352 self.progress_bar = 0
1355 def to_log(self, *k, **kw):
1359 bld.keep = kw.get('run_all_tests', True)
1364 x = Task.classes['cfgtask'](bld=bld)
1371 # bind a logger that will keep the info in memory
1372 x.logger = Logs.make_mem_logger(str(id(x)), self.logger)
1375 id_to_task[dct['id']] = x
1377 # second pass to set dependencies with after_test/before_test
1379 for key in Utils.to_list(x.args.get('before_tests', [])):
1380 tsk = id_to_task[key]
1382 raise ValueError('No test named %r' % key)
1383 tsk.run_after.add(x)
1384 for key in Utils.to_list(x.args.get('after_tests', [])):
1385 tsk = id_to_task[key]
1387 raise ValueError('No test named %r' % key)
1388 x.run_after.add(tsk)
1394 bld.producer = p = Runner.Parallel(bld, Options.options.jobs)
1395 bld.multicheck_lock = Utils.threading.Lock()
1398 self.end_msg('started')
1401 # flush the logs in order into the config.log
1403 x.logger.memhandler.flush()
1405 self.start_msg('-> processing test results')
1408 if getattr(x, 'err_msg', None):
1409 self.to_log(x.err_msg)
1410 self.end_msg('fail', color='RED')
1411 raise Errors.WafError('There is an error in the library, read config.log for more information')
1415 if x.hasrun not in (Task.SUCCESS, Task.NOT_RUN):
1419 self.end_msg(kw.get('errmsg', '%s test failed' % failure_count), color='YELLOW', **kw)
1421 self.end_msg('all ok', **kw)
1424 if x.hasrun != Task.SUCCESS:
1425 if x.args.get('mandatory', True):
1426 self.fatal(kw.get('fatalmsg') or 'One of the tests has failed, read config.log for more information')