Merge pull request #51 from teto/update_waf
authorMatthieu Coudron <matthieu.coudron@upmc.fr>
Thu, 18 Aug 2016 16:06:49 +0200
changeset 753 57c296302418
parent 751 38c5a67a548a (current diff)
parent 752 ae6043e6156d (diff)
child 754 e650f77485e4
Merge pull request #51 from teto/update_waf Updated waf to 1.8.19
--- a/myscripts/dce-mpi-udp/wscript	Thu Aug 18 15:10:37 2016 +0200
+++ b/myscripts/dce-mpi-udp/wscript	Thu Aug 18 16:06:49 2016 +0200
@@ -1,7 +1,6 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 import ns3waf
-import Options
 
 def configure(conf):
     ns3waf.check_modules(conf, ['core', 'internet', 'point-to-point', 'mpi'], mandatory = True)
--- a/ns3waf/__init__.py	Thu Aug 18 15:10:37 2016 +0200
+++ b/ns3waf/__init__.py	Thu Aug 18 16:06:49 2016 +0200
@@ -5,9 +5,9 @@
 import os
 import re
 
+from waflib import Utils, Scripting, Configure, Build, Options, TaskGen, Context, Task, Logs, Errors
+
 def options(opt):
-    opt.tool_options('compiler_cc')
-    opt.tool_options('compiler_cxx')
     opt.add_option('--enable-static',
                    help=('Compile module statically: works only on linux, without python'),
                    dest='enable_static', action='store_true',
@@ -73,7 +73,6 @@
         print "%-30s: %s" % (caption, status)
 
 def _check_static(conf):
-    import Options
     import sys
     import re
     import os
@@ -121,7 +120,6 @@
 
 
 def _check_win32(conf):
-    import Options
     import sys
     import subprocess
     import os
@@ -149,6 +147,7 @@
 def _check_dependencies(conf, required, mandatory):
     found = []
     match_pkg = None
+
     for module in required:
         if module in conf.env['NS3_MODULES_FOUND']:
             continue
@@ -206,13 +205,10 @@
         return bld.env['cshlib_PATTERN'] % libname
 
 def check_modules(conf, modules, mandatory = True):
-    import Options
     import os
 
     if not 'NS3_CHECK_MODULE_ONCE' in conf.env:
         conf.env['NS3_CHECK_MODULE_ONCE'] = ''
-        conf.check_tool('compiler_cc')
-        conf.check_tool('compiler_cxx')
         conf.check_cfg(atleast_pkgconfig_version='0.0.0')
         _check_win32(conf)
         _check_static(conf)
Binary file waf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/boost.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,411 @@
+#!/usr/bin/env python
+# encoding: utf-8
+#
+# partially based on boost.py written by Gernot Vormayr
+# written by Ruediger Sonderfeld <ruediger@c-plusplus.de>, 2008
+# modified by Bjoern Michaelsen, 2008
+# modified by Luca Fossati, 2008
+# rewritten for waf 1.5.1, Thomas Nagy, 2008
+# rewritten for waf 1.6.2, Sylvain Rouquette, 2011
+
+'''
+
+This is an extra tool, not bundled with the default waf binary.
+To add the boost tool to the waf file:
+$ ./waf-light --tools=compat15,boost
+	or, if you have waf >= 1.6.2
+$ ./waf update --files=boost
+
+When using this tool, the wscript will look like:
+
+	def options(opt):
+		opt.load('compiler_cxx boost')
+
+	def configure(conf):
+		conf.load('compiler_cxx boost')
+		conf.check_boost(lib='system filesystem')
+
+	def build(bld):
+		bld(source='main.cpp', target='app', use='BOOST')
+
+Options are generated, in order to specify the location of boost includes/libraries.
+The `check_boost` configuration function allows to specify the used boost libraries.
+It can also provide default arguments to the --boost-mt command-line arguments.
+Everything will be packaged together in a BOOST component that you can use.
+
+When using MSVC, a lot of compilation flags need to match your BOOST build configuration:
+ - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined.
+   Errors: C4530
+ - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC
+   So before calling `conf.check_boost` you might want to disabling by adding
+		conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB']
+   Errors:
+ - boost might also be compiled with /MT, which links the runtime statically.
+   If you have problems with redefined symbols,
+		self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
+		self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc']
+Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases.
+
+'''
+
+import sys
+import re
+from waflib import Utils, Logs, Errors
+from waflib.Configure import conf
+from waflib.TaskGen import feature, after_method
+
+BOOST_LIBS = ['/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu',
+			  '/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib']
+BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include']
+BOOST_VERSION_FILE = 'boost/version.hpp'
+BOOST_VERSION_CODE = '''
+#include <iostream>
+#include <boost/version.hpp>
+int main() { std::cout << BOOST_LIB_VERSION << std::endl; }
+'''
+
+BOOST_ERROR_CODE = '''
+#include <boost/system/error_code.hpp>
+int main() { boost::system::error_code c; }
+'''
+
+BOOST_THREAD_CODE = '''
+#include <boost/thread.hpp>
+int main() { boost::thread t; }
+'''
+
+# toolsets from {boost_dir}/tools/build/v2/tools/common.jam
+PLATFORM = Utils.unversioned_sys_platform()
+detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il'
+detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang'
+detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc'
+BOOST_TOOLSETS = {
+	'borland':  'bcb',
+	'clang':	detect_clang,
+	'como':	 'como',
+	'cw':	   'cw',
+	'darwin':   'xgcc',
+	'edg':	  'edg',
+	'g++':	  detect_mingw,
+	'gcc':	  detect_mingw,
+	'icpc':	 detect_intel,
+	'intel':	detect_intel,
+	'kcc':	  'kcc',
+	'kylix':	'bck',
+	'mipspro':  'mp',
+	'mingw':	'mgw',
+	'msvc':	 'vc',
+	'qcc':	  'qcc',
+	'sun':	  'sw',
+	'sunc++':   'sw',
+	'tru64cxx': 'tru',
+	'vacpp':	'xlc'
+}
+
+
+def options(opt):
+	opt.add_option('--boost-includes', type='string',
+				   default='', dest='boost_includes',
+				   help='''path to the boost includes root (~boost root)
+				   e.g. /path/to/boost_1_47_0''')
+	opt.add_option('--boost-libs', type='string',
+				   default='', dest='boost_libs',
+				   help='''path to the directory where the boost libs are
+				   e.g. /path/to/boost_1_47_0/stage/lib''')
+	opt.add_option('--boost-mt', action='store_true',
+				   default=False, dest='boost_mt',
+				   help='select multi-threaded libraries')
+	opt.add_option('--boost-abi', type='string', default='', dest='boost_abi',
+				   help='''select libraries with tags (gd for debug, static is automatically added),
+				   see doc Boost, Getting Started, chapter 6.1''')
+	opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect',
+				   help="auto-detect boost linkage options (don't get used to it / might break other stuff)")
+	opt.add_option('--boost-toolset', type='string',
+				   default='', dest='boost_toolset',
+				   help='force a toolset e.g. msvc, vc90, \
+						gcc, mingw, mgw45 (default: auto)')
+	py_version = '%d%d' % (sys.version_info[0], sys.version_info[1])
+	opt.add_option('--boost-python', type='string',
+				   default=py_version, dest='boost_python',
+				   help='select the lib python with this version \
+						(default: %s)' % py_version)
+
+
+@conf
+def __boost_get_version_file(self, d):
+	if not d:
+		return None
+	dnode = self.root.find_dir(d)
+	if dnode:
+		return dnode.find_node(BOOST_VERSION_FILE)
+	return None
+
+@conf
+def boost_get_version(self, d):
+	"""silently retrieve the boost version number"""
+	node = self.__boost_get_version_file(d)
+	if node:
+		try:
+			txt = node.read()
+		except EnvironmentError:
+			Logs.error("Could not read the file %r" % node.abspath())
+		else:
+			re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"', re.M)
+			m = re_but.search(txt)
+			if m:
+				return m.group(1)
+	return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True)
+
+@conf
+def boost_get_includes(self, *k, **kw):
+	includes = k and k[0] or kw.get('includes', None)
+	if includes and self.__boost_get_version_file(includes):
+		return includes
+	for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES:
+		if self.__boost_get_version_file(d):
+			return d
+	if includes:
+		self.end_msg('headers not found in %s' % includes)
+		self.fatal('The configuration failed')
+	else:
+		self.end_msg('headers not found, please provide a --boost-includes argument (see help)')
+		self.fatal('The configuration failed')
+
+
+@conf
+def boost_get_toolset(self, cc):
+	toolset = cc
+	if not cc:
+		build_platform = Utils.unversioned_sys_platform()
+		if build_platform in BOOST_TOOLSETS:
+			cc = build_platform
+		else:
+			cc = self.env.CXX_NAME
+	if cc in BOOST_TOOLSETS:
+		toolset = BOOST_TOOLSETS[cc]
+	return isinstance(toolset, str) and toolset or toolset(self.env)
+
+
+@conf
+def __boost_get_libs_path(self, *k, **kw):
+	''' return the lib path and all the files in it '''
+	if 'files' in kw:
+		return self.root.find_dir('.'), Utils.to_list(kw['files'])
+	libs = k and k[0] or kw.get('libs', None)
+	if libs:
+		path = self.root.find_dir(libs)
+		files = path.ant_glob('*boost_*')
+	if not libs or not files:
+		for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS:
+			if not d:
+				continue
+			path = self.root.find_dir(d)
+			if path:
+				files = path.ant_glob('*boost_*')
+				if files:
+					break
+			path = self.root.find_dir(d + '64')
+			if path:
+				files = path.ant_glob('*boost_*')
+				if files:
+					break
+	if not path:
+		if libs:
+			self.end_msg('libs not found in %s' % libs)
+			self.fatal('The configuration failed')
+		else:
+			self.end_msg('libs not found, please provide a --boost-libs argument (see help)')
+			self.fatal('The configuration failed')
+
+	self.to_log('Found the boost path in %r with the libraries:' % path)
+	for x in files:
+		self.to_log('    %r' % x)
+	return path, files
+
+@conf
+def boost_get_libs(self, *k, **kw):
+	'''
+	return the lib path and the required libs
+	according to the parameters
+	'''
+	path, files = self.__boost_get_libs_path(**kw)
+	files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True)
+	toolset = self.boost_get_toolset(kw.get('toolset', ''))
+	toolset_pat = '(-%s[0-9]{0,3})' % toolset
+	version = '-%s' % self.env.BOOST_VERSION
+
+	def find_lib(re_lib, files):
+		for file in files:
+			if re_lib.search(file.name):
+				self.to_log('Found boost lib %s' % file)
+				return file
+		return None
+
+	def format_lib_name(name):
+		if name.startswith('lib') and self.env.CC_NAME != 'msvc':
+			name = name[3:]
+		return name[:name.rfind('.')]
+
+	def match_libs(lib_names, is_static):
+		libs = []
+		lib_names = Utils.to_list(lib_names)
+		if not lib_names:
+			return libs
+		t = []
+		if kw.get('mt', False):
+			t.append('-mt')
+		if kw.get('abi', None):
+			t.append('%s%s' % (is_static and '-s' or '-', kw['abi']))
+		elif is_static:
+			t.append('-s')
+		tags_pat = t and ''.join(t) or ''
+		ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN
+		ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN
+
+		for lib in lib_names:
+			if lib == 'python':
+				# for instance, with python='27',
+				# accepts '-py27', '-py2', '27' and '2'
+				# but will reject '-py3', '-py26', '26' and '3'
+				tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python'])
+			else:
+				tags = tags_pat
+			# Trying libraries, from most strict match to least one
+			for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext),
+							'boost_%s%s%s%s$' % (lib, tags, version, ext),
+							# Give up trying to find the right version
+							'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext),
+							'boost_%s%s%s$' % (lib, tags, ext),
+							'boost_%s%s$' % (lib, ext),
+							'boost_%s' % lib]:
+				self.to_log('Trying pattern %s' % pattern)
+				file = find_lib(re.compile(pattern), files)
+				if file:
+					libs.append(format_lib_name(file.name))
+					break
+			else:
+				self.end_msg('lib %s not found in %s' % (lib, path.abspath()))
+				self.fatal('The configuration failed')
+		return libs
+
+	return  path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True)
+
+
+@conf
+def check_boost(self, *k, **kw):
+	"""
+	Initialize boost libraries to be used.
+
+	Keywords: you can pass the same parameters as with the command line (without "--boost-").
+	Note that the command line has the priority, and should preferably be used.
+	"""
+	if not self.env['CXX']:
+		self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
+
+	params = {
+		'lib': k and k[0] or kw.get('lib', None),
+		'stlib': kw.get('stlib', None)
+	}
+	for key, value in self.options.__dict__.items():
+		if not key.startswith('boost_'):
+			continue
+		key = key[len('boost_'):]
+		params[key] = value and value or kw.get(key, '')
+
+	var = kw.get('uselib_store', 'BOOST')
+
+	self.start_msg('Checking boost includes')
+	self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params)
+	self.env.BOOST_VERSION = self.boost_get_version(inc)
+	self.end_msg(self.env.BOOST_VERSION)
+	if Logs.verbose:
+		Logs.pprint('CYAN', '	path : %s' % self.env['INCLUDES_%s' % var])
+
+	if not params['lib'] and not params['stlib']:
+		return
+	if 'static' in kw or 'static' in params:
+		Logs.warn('boost: static parameter is deprecated, use stlib instead.')
+	self.start_msg('Checking boost libs')
+	path, libs, stlibs = self.boost_get_libs(**params)
+	self.env['LIBPATH_%s' % var] = [path]
+	self.env['STLIBPATH_%s' % var] = [path]
+	self.env['LIB_%s' % var] = libs
+	self.env['STLIB_%s' % var] = stlibs
+	self.end_msg('ok')
+	if Logs.verbose:
+		Logs.pprint('CYAN', '	path : %s' % path)
+		Logs.pprint('CYAN', '	shared libs : %s' % libs)
+		Logs.pprint('CYAN', '	static libs : %s' % stlibs)
+
+
+	def try_link():
+		if (params['lib'] and 'system' in params['lib']) or \
+			params['stlib'] and 'system' in params['stlib']:
+			self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False)
+		if (params['lib'] and 'thread' in params['lib']) or \
+			params['stlib'] and 'thread' in params['stlib']:
+			self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False)
+
+	if params.get('linkage_autodetect', False):
+		self.start_msg("Attempting to detect boost linkage flags")
+		toolset = self.boost_get_toolset(kw.get('toolset', ''))
+		if toolset in ('vc',):
+			# disable auto-linking feature, causing error LNK1181
+			# because the code wants to be linked against
+			self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB']
+
+			# if no dlls are present, we guess the .lib files are not stubs
+			has_dlls = False
+			for x in Utils.listdir(path):
+				if x.endswith(self.env.cxxshlib_PATTERN % ''):
+					has_dlls = True
+					break
+			if not has_dlls:
+				self.env['STLIBPATH_%s' % var] = [path]
+				self.env['STLIB_%s' % var] = libs
+				del self.env['LIB_%s' % var]
+				del self.env['LIBPATH_%s' % var]
+
+			# we attempt to play with some known-to-work CXXFLAGS combinations
+			for cxxflags in (['/MD', '/EHsc'], []):
+				self.env.stash()
+				self.env["CXXFLAGS_%s" % var] += cxxflags
+				try:
+					try_link()
+					self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var]))
+					exc = None
+					break
+				except Errors.ConfigurationError as e:
+					self.env.revert()
+					exc = e
+
+			if exc is not None:
+				self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=exc)
+				self.fatal('The configuration failed')
+		else:
+			self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain")
+			self.fatal('The configuration failed')
+	else:
+		self.start_msg('Checking for boost linkage')
+		try:
+			try_link()
+		except Errors.ConfigurationError as e:
+			self.end_msg("Could not link against boost libraries using supplied options")
+			self.fatal('The configuration failed')
+		self.end_msg('ok')
+
+
+@feature('cxx')
+@after_method('apply_link')
+def install_boost(self):
+	if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'):
+		return
+	install_boost.done = True
+	inst_to = getattr(self, 'install_path', '${BINDIR}')
+	for lib in self.env.LIB_BOOST:
+		try:
+			file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST)
+			self.bld.install_files(inst_to, self.bld.root.find_node(file))
+		except:
+			continue
+install_boost.done = False
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/cflags.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,194 @@
+from waflib import Logs, Options, Utils
+
+
+class CompilerTraits(object):
+	def get_warnings_flags(self, level):
+		"""get_warnings_flags(level) -> list of cflags"""
+		raise NotImplementedError
+
+	def get_optimization_flags(self, level):
+		"""get_optimization_flags(level) -> list of cflags"""
+		raise NotImplementedError
+
+	def get_debug_flags(self, level):
+		"""get_debug_flags(level) -> (list of cflags, list of cppdefines)"""
+		raise NotImplementedError
+
+
+class GccTraits(CompilerTraits):
+	def __init__(self):
+		super(GccTraits, self).__init__()
+		# cumulative list of warnings per level
+		self.warnings_flags = [['-Wall'], ['-Werror'], ['-Wextra']]
+
+	def get_warnings_flags(self, level):
+		warnings = []
+		for l in range(level):
+			if l < len(self.warnings_flags):
+				warnings.extend(self.warnings_flags[l])
+			else:
+				break
+		return warnings
+
+	def get_optimization_flags(self, level):
+		if level == 0:
+			return ['-O0']
+		elif level == 1:
+			return ['-O']
+		elif level == 2:
+			return ['-O2']
+		elif level == 3:
+			return ['-O3']
+
+	def get_debug_flags(self, level):
+		if level == 0:
+			return (['-g0'], ['NDEBUG'])
+		elif level == 1:
+			return (['-g'], [])
+		elif level >= 2:
+			return (['-ggdb', '-g3'], ['_DEBUG'])
+		
+
+class IccTraits(CompilerTraits):
+	def __init__(self):
+		super(IccTraits, self).__init__()
+		# cumulative list of warnings per level
+		# icc is _very_ verbose with -Wall, -Werror is barely achievable
+		self.warnings_flags = [[], [], ['-Wall']]
+		
+	def get_warnings_flags(self, level):
+		warnings = []
+		for l in range(level):
+			if l < len(self.warnings_flags):
+				warnings.extend(self.warnings_flags[l])
+			else:
+				break
+		return warnings
+
+	def get_optimization_flags(self, level):
+		if level == 0:
+			return ['-O0']
+		elif level == 1:
+			return ['-O']
+		elif level == 2:
+			return ['-O2']
+		elif level == 3:
+			return ['-O3']
+
+	def get_debug_flags(self, level):
+		if level == 0:
+			return (['-g0'], ['NDEBUG'])
+		elif level == 1:
+			return (['-g'], [])
+		elif level >= 2:
+			return (['-ggdb', '-g3'], ['_DEBUG'])
+		
+
+
+class MsvcTraits(CompilerTraits):
+	def __init__(self):
+		super(MsvcTraits, self).__init__()
+		# cumulative list of warnings per level
+		self.warnings_flags = [['/W2'], ['/WX'], ['/Wall']]
+
+	def get_warnings_flags(self, level):
+		warnings = []
+		for l in range(level):
+			if l < len(self.warnings_flags):
+				warnings.extend(self.warnings_flags[l])
+			else:
+				break
+		return warnings
+
+	def get_optimization_flags(self, level):
+		if level == 0:
+			return ['/Od']
+		elif level == 1:
+			return []
+		elif level == 2:
+			return ['/O2']
+		elif level == 3:
+			return ['/Ox']
+
+	def get_debug_flags(self, level):
+		if level == 0:
+			return ([], ['NDEBUG'])
+		elif level == 1:
+			return (['/ZI', '/RTC1'], [])
+		elif level >= 2:
+			return (['/ZI', '/RTC1'], ['_DEBUG'])
+
+
+
+gcc = GccTraits()
+icc = IccTraits()
+msvc = MsvcTraits()
+
+# how to map env['COMPILER_CC'] or env['COMPILER_CXX'] into a traits object
+compiler_mapping = {
+	'gcc': gcc,
+	'g++': gcc,
+	'msvc': msvc,
+	'icc': icc,
+	'icpc': icc,
+	'clang': gcc,
+	'clang++': gcc,
+}
+
+profiles = {
+	# profile name: [optimization_level, warnings_level, debug_level]
+	'default': [2, 1, 1],
+	'debug': [0, 2, 3],
+	'release': [3, 1, 0],
+	}
+
+default_profile = 'default'
+
+def options(opt):
+	assert default_profile in profiles
+	opt.add_option('-d', '--build-profile',
+		       action='store',
+		       default=default_profile,
+		       help=("Specify the build profile.  "
+			     "Build profiles control the default compilation flags"
+			     " used for C/C++ programs, if CCFLAGS/CXXFLAGS are not"
+			     " set in the environment. [Allowed Values: %s]"
+			     % ", ".join([repr(p) for p in list(profiles.keys())])),
+		       choices=list(profiles.keys()),
+		       dest='build_profile')
+	opt.add_option('--check-profile',
+		       help=('print out current build profile'),
+		       default=False, dest='check_profile', action="store_true")
+def configure(conf):
+	cc = conf.env['COMPILER_CC'] or None
+	cxx = conf.env['COMPILER_CXX'] or None
+	if not (cc or cxx):
+		raise Utils.WafError("neither COMPILER_CC nor COMPILER_CXX are defined; "
+				     "maybe the compiler_cc or compiler_cxx tool has not been configured yet?")
+	
+	try:
+		compiler = compiler_mapping[cc]
+	except KeyError:
+		try:
+			compiler = compiler_mapping[cxx]
+		except KeyError:
+			Logs.warn("No compiler flags support for compiler %r or %r"
+				  % (cc, cxx))
+			return
+
+	opt_level, warn_level, dbg_level = profiles[Options.options.build_profile]
+
+	optimizations = compiler.get_optimization_flags(opt_level)
+	debug, debug_defs = compiler.get_debug_flags(dbg_level)
+	warnings = compiler.get_warnings_flags(warn_level)
+	
+	if cc and not conf.env['CCFLAGS']:
+		conf.env.append_value('CCFLAGS', optimizations)
+		conf.env.append_value('CCFLAGS', debug)
+		conf.env.append_value('CCFLAGS', warnings)
+		conf.env.append_value('CCDEFINES', debug_defs)
+	if cxx and not conf.env['CXXFLAGS']:
+		conf.env.append_value('CXXFLAGS', optimizations)
+		conf.env.append_value('CXXFLAGS', debug)
+		conf.env.append_value('CXXFLAGS', warnings)
+		conf.env.append_value('CXXDEFINES', debug_defs)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/clang_compilation_database.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# encoding: utf-8
+# Christoph Koke, 2013
+
+"""
+Writes the c and cpp compile commands into build/compile_commands.json
+see http://clang.llvm.org/docs/JSONCompilationDatabase.html
+
+Usage:
+
+    def configure(conf):
+        conf.load('compiler_cxx')
+        ...
+        conf.load('clang_compilation_database')
+"""
+
+import sys, os, json, shlex, pipes
+from waflib import Logs, TaskGen
+from waflib.Tools import c, cxx
+
+if sys.hexversion >= 0x3030000:
+	quote = shlex.quote
+else:
+	quote = pipes.quote
+
+@TaskGen.feature('*')
+@TaskGen.after_method('process_use')
+def collect_compilation_db_tasks(self):
+	"Add a compilation database entry for compiled tasks"
+	try:
+		clang_db = self.bld.clang_compilation_database_tasks
+	except AttributeError:
+		clang_db = self.bld.clang_compilation_database_tasks = []
+		self.bld.add_post_fun(write_compilation_database)
+
+	for task in getattr(self, 'compiled_tasks', []):
+		if isinstance(task, (c.c, cxx.cxx)):
+			clang_db.append(task)
+
+def write_compilation_database(ctx):
+	"Write the clang compilation database as JSON"
+	database_file = ctx.bldnode.make_node('compile_commands.json')
+	Logs.info("Build commands will be stored in %s" % database_file.path_from(ctx.path))
+	try:
+		root = json.load(database_file)
+	except IOError:
+		root = []
+	clang_db = dict((x["file"], x) for x in root)
+	for task in getattr(ctx, 'clang_compilation_database_tasks', []):
+		try:
+			cmd = task.last_cmd
+		except AttributeError:
+			continue
+		directory = getattr(task, 'cwd', ctx.variant_dir)
+		f_node = task.inputs[0]
+		filename = os.path.relpath(f_node.abspath(), directory)
+		cmd = " ".join(map(quote, cmd))
+		entry = {
+			"directory": directory,
+			"command": cmd,
+			"file": filename,
+		}
+		clang_db[filename] = entry
+	root = list(clang_db.values())
+	database_file.write(json.dumps(root, indent=2))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/command.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,131 @@
+import re
+import subprocess
+
+# import feature, taskgen_method, before_method, task_gen
+from waflib import TaskGen, Node, Task, Utils, Build, Options, Logs, Task
+debug = Logs.debug
+error = Logs.error
+
+import shellcmd
+#shellcmd.subprocess = pproc # the WAF version of the subprocess module is supposedly less buggy
+shellcmd.debug = debug
+
+
+arg_rx = re.compile(r"(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})", re.M)
+
+class command_task(Task.Task):
+	color = "BLUE"
+	def __init__(self, env, generator):
+		Task.Task.__init__(self, env=env, normal=1, generator=generator)
+
+	def __str__(self):
+		"string to display to the user"
+		env = self.env
+		src_str = ' '.join([a.bldpath() for a in self.inputs])
+		tgt_str = ' '.join([a.bldpath() for a in self.outputs])
+		if self.outputs:
+			sep = ' -> '
+		else:
+			sep = ''
+
+		pipeline = shellcmd.Pipeline()
+		pipeline.parse(self.generator.command)
+		cmd = pipeline.get_abbreviated_command()
+		return 'command (%s): %s%s%s\n' % (cmd, src_str, sep, tgt_str)
+
+	def _subst_arg(self, arg, direction, namespace):
+		"""
+		@param arg: the command argument (or stdin/stdout/stderr) to substitute
+		@param direction: direction of the argument: 'in', 'out', or None
+		"""
+		def repl(match):
+			if match.group('dollar'):
+				return "$"
+			elif match.group('subst'):
+				var = match.group('var')
+				code = match.group('code')
+				result = eval(var+code, namespace)
+				if isinstance(result, Node.Node):
+					if var == 'TGT':
+						return result.get_bld().abspath()
+					elif var == 'SRC':
+						return result.srcpath()
+					else:
+						raise ValueError("Bad subst variable %r" % var)
+				elif result is self.inputs:
+					if len(self.inputs) == 1:
+						return result[0].srcpath()
+					else:
+						raise ValueError("${SRC} requested but have multiple sources; which one?")
+				elif result is self.outputs:
+					if len(self.outputs) == 1:
+						return result[0].get_bld().abspath()
+					else:
+						raise ValueError("${TGT} requested but have multiple targets; which one?")
+				elif isinstance(result, list):
+					assert len(result) == 1
+					return result[0]
+				else:
+					return result
+			return None
+
+		return arg_rx.sub(repl, arg)
+
+	def run(self):
+		pipeline = shellcmd.Pipeline()
+		pipeline.parse(self.generator.command)
+		namespace = self.env.get_merged_dict()
+		if self.generator.variables is not None:
+			namespace.update(self.generator.variables)
+		namespace.update(env=self.env, SRC=self.inputs, TGT=self.outputs)
+		for cmd in pipeline.pipeline:
+			if isinstance(cmd, shellcmd.Command):
+				if isinstance(cmd.stdin, str):
+					cmd.stdin = self._subst_arg(cmd.stdin, 'in', namespace)
+				if isinstance(cmd.stdout, str):
+					cmd.stdout = self._subst_arg(cmd.stdout, 'out', namespace)
+				if isinstance(cmd.stderr, str):
+					cmd.stderr = self._subst_arg(cmd.stderr, 'out', namespace)
+				for argI in range(len(cmd.argv)):
+					cmd.argv[argI] = self._subst_arg(cmd.argv[argI], None, namespace)
+				if cmd.env_vars is not None:
+					env_vars = dict()
+					for name, value in cmd.env_vars.items():
+						env_vars[name] = self._subst_arg(value, None, namespace)
+					cmd.env_vars = env_vars
+			elif isinstance(cmd, shellcmd.Chdir):
+				cmd.dir = self._subst_arg(cmd.dir, None, namespace)
+		return pipeline.run(verbose=(Options.options.verbose > 0))
+
+@TaskGen.taskgen_method
+@TaskGen.feature('command')
+def init_command(self):
+	Utils.def_attrs(self,
+					# other variables that can be used in the command: ${VARIABLE}
+					variables = None,
+					rule='')
+
+
+
+@TaskGen.feature('command')
+@TaskGen.after_method('process_rule')
+def apply_command(self):
+	#self.meths.remove('apply_core')
+	# create the task
+	task = self.create_task('command')
+	setattr(task, "dep_vars", getattr(self, "dep_vars", None))
+	# process the sources
+	inputs = []
+	for node in self.source:
+		inputs.append(node)
+	task.set_inputs(inputs)
+	task.set_outputs([self.path.find_or_declare(tgt) for tgt in self.to_list(self.target)])
+	self.source = ''
+	#Task.file_deps = Task.extract_deps
+
+
+
+# class command_taskgen(task_gen):
+# 	def __init__(self, *k, **kw):
+# 		task_gen.__init__(self, *k, **kw)
+# 		self.features.append('command')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/misc.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,413 @@
+#!/usr/bin/env python
+# encoding: utf-8
+# Thomas Nagy, 2006-2010 (ita)
+
+"""
+This tool is totally deprecated
+
+Try using:
+	.pc.in files for .pc files
+	the feature intltool_in - see demos/intltool
+	make-like rules
+"""
+
+import shutil, re, os
+from waflib import TaskGen, Node, Task, Utils, Build, Errors
+from waflib.TaskGen import feature, after_method, before_method
+from waflib.Logs import debug
+
+def copy_attrs(orig, dest, names, only_if_set=False):
+	"""
+	copy class attributes from an object to another
+	"""
+	for a in Utils.to_list(names):
+		u = getattr(orig, a, ())
+		if u or not only_if_set:
+			setattr(dest, a, u)
+
+def copy_func(tsk):
+	"Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)"
+	env = tsk.env
+	infile = tsk.inputs[0].abspath()
+	outfile = tsk.outputs[0].abspath()
+	try:
+		shutil.copy2(infile, outfile)
+	except EnvironmentError:
+		return 1
+	else:
+		if tsk.chmod: os.chmod(outfile, tsk.chmod)
+		return 0
+
+def action_process_file_func(tsk):
+	"Ask the function attached to the task to process it"
+	if not tsk.fun: raise Errors.WafError('task must have a function attached to it for copy_func to work!')
+	return tsk.fun(tsk)
+
+@feature('cmd')
+def apply_cmd(self):
+	"call a command everytime"
+	if not self.fun: raise Errors.WafError('cmdobj needs a function!')
+	tsk = Task.TaskBase()
+	tsk.fun = self.fun
+	tsk.env = self.env
+	self.tasks.append(tsk)
+	tsk.install_path = self.install_path
+
+@feature('copy')
+@before_method('process_source')
+def apply_copy(self):
+	Utils.def_attrs(self, fun=copy_func)
+	self.default_install_path = 0
+
+	lst = self.to_list(self.source)
+	self.meths.remove('process_source')
+
+	for filename in lst:
+		node = self.path.find_resource(filename)
+		if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
+
+		target = self.target
+		if not target or len(lst)>1: target = node.name
+
+		# TODO the file path may be incorrect
+		newnode = self.path.find_or_declare(target)
+
+		tsk = self.create_task('copy', node, newnode)
+		tsk.fun = self.fun
+		tsk.chmod = getattr(self, 'chmod', Utils.O644)
+
+		if not tsk.env:
+			tsk.debug()
+			raise Errors.WafError('task without an environment')
+
+def subst_func(tsk):
+	"Substitutes variables in a .in file"
+
+	m4_re = re.compile('@(\w+)@', re.M)
+
+	code = tsk.inputs[0].read() #Utils.readf(infile)
+
+	# replace all % by %% to prevent errors by % signs in the input file while string formatting
+	code = code.replace('%', '%%')
+
+	s = m4_re.sub(r'%(\1)s', code)
+
+	env = tsk.env
+	di = getattr(tsk, 'dict', {}) or getattr(tsk.generator, 'dict', {})
+	if not di:
+		names = m4_re.findall(code)
+		for i in names:
+			di[i] = env.get_flat(i) or env.get_flat(i.upper())
+
+	tsk.outputs[0].write(s % di)
+
+@feature('subst')
+@before_method('process_source')
+def apply_subst(self):
+	Utils.def_attrs(self, fun=subst_func)
+	lst = self.to_list(self.source)
+	self.meths.remove('process_source')
+
+	self.dict = getattr(self, 'dict', {})
+
+	for filename in lst:
+		node = self.path.find_resource(filename)
+		if not node: raise Errors.WafError('cannot find input file %s for processing' % filename)
+
+		if self.target:
+			newnode = self.path.find_or_declare(self.target)
+		else:
+			newnode = node.change_ext('')
+
+		try:
+			self.dict = self.dict.get_merged_dict()
+		except AttributeError:
+			pass
+
+		if self.dict and not self.env['DICT_HASH']:
+			self.env = self.env.derive()
+			keys = list(self.dict.keys())
+			keys.sort()
+			lst = [self.dict[x] for x in keys]
+			self.env['DICT_HASH'] = str(Utils.h_list(lst))
+
+		tsk = self.create_task('copy', node, newnode)
+		tsk.fun = self.fun
+		tsk.dict = self.dict
+		tsk.dep_vars = ['DICT_HASH']
+		tsk.chmod = getattr(self, 'chmod', Utils.O644)
+
+		if not tsk.env:
+			tsk.debug()
+			raise Errors.WafError('task without an environment')
+
+####################
+## command-output ####
+####################
+
+class cmd_arg(object):
+	"""command-output arguments for representing files or folders"""
+	def __init__(self, name, template='%s'):
+		self.name = name
+		self.template = template
+		self.node = None
+
+class input_file(cmd_arg):
+	def find_node(self, base_path):
+		assert isinstance(base_path, Node.Node)
+		self.node = base_path.find_resource(self.name)
+		if self.node is None:
+			raise Errors.WafError("Input file %s not found in " % (self.name, base_path))
+
+	def get_path(self, env, absolute):
+		if absolute:
+			return self.template % self.node.abspath()
+		else:
+			return self.template % self.node.srcpath()
+
+class output_file(cmd_arg):
+	def find_node(self, base_path):
+		assert isinstance(base_path, Node.Node)
+		self.node = base_path.find_or_declare(self.name)
+		if self.node is None:
+			raise Errors.WafError("Output file %s not found in " % (self.name, base_path))
+
+	def get_path(self, env, absolute):
+		if absolute:
+			return self.template % self.node.abspath()
+		else:
+			return self.template % self.node.bldpath()
+
+class cmd_dir_arg(cmd_arg):
+	def find_node(self, base_path):
+		assert isinstance(base_path, Node.Node)
+		self.node = base_path.find_dir(self.name)
+		if self.node is None:
+			raise Errors.WafError("Directory %s not found in " % (self.name, base_path))
+
+class input_dir(cmd_dir_arg):
+	def get_path(self, dummy_env, dummy_absolute):
+		return self.template % self.node.abspath()
+
+class output_dir(cmd_dir_arg):
+	def get_path(self, env, dummy_absolute):
+		return self.template % self.node.abspath()
+
+
+class command_output(Task.Task):
+	color = "BLUE"
+	def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr):
+		Task.Task.__init__(self, env=env)
+		assert isinstance(command, (str, Node.Node))
+		self.command = command
+		self.command_args = command_args
+		self.stdin = stdin
+		self.stdout = stdout
+		self.cwd = cwd
+		self.os_env = os_env
+		self.stderr = stderr
+
+		if command_node is not None: self.dep_nodes = [command_node]
+		self.dep_vars = [] # additional environment variables to look
+
+	def run(self):
+		task = self
+		#assert len(task.inputs) > 0
+
+		def input_path(node, template):
+			if task.cwd is None:
+				return template % node.bldpath()
+			else:
+				return template % node.abspath()
+		def output_path(node, template):
+			fun = node.abspath
+			if task.cwd is None: fun = node.bldpath
+			return template % fun()
+
+		if isinstance(task.command, Node.Node):
+			argv = [input_path(task.command, '%s')]
+		else:
+			argv = [task.command]
+
+		for arg in task.command_args:
+			if isinstance(arg, str):
+				argv.append(arg)
+			else:
+				assert isinstance(arg, cmd_arg)
+				argv.append(arg.get_path(task.env, (task.cwd is not None)))
+
+		if task.stdin:
+			stdin = open(input_path(task.stdin, '%s'))
+		else:
+			stdin = None
+
+		if task.stdout:
+			stdout = open(output_path(task.stdout, '%s'), "w")
+		else:
+			stdout = None
+
+		if task.stderr:
+			stderr = open(output_path(task.stderr, '%s'), "w")
+		else:
+			stderr = None
+
+		if task.cwd is None:
+			cwd = ('None (actually %r)' % os.getcwd())
+		else:
+			cwd = repr(task.cwd)
+		debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" %
+			     (cwd, stdin, stdout, argv))
+
+		if task.os_env is None:
+			os_env = os.environ
+		else:
+			os_env = task.os_env
+		command = Utils.subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env)
+		return command.wait()
+
+@feature('command-output')
+def init_cmd_output(self):
+	Utils.def_attrs(self,
+		stdin = None,
+		stdout = None,
+		stderr = None,
+		# the command to execute
+		command = None,
+
+		# whether it is an external command; otherwise it is assumed
+		# to be an executable binary or script that lives in the
+		# source or build tree.
+		command_is_external = False,
+
+		# extra parameters (argv) to pass to the command (excluding
+		# the command itself)
+		argv = [],
+
+		# dependencies to other objects -> this is probably not what you want (ita)
+		# values must be 'task_gen' instances (not names!)
+		dependencies = [],
+
+		# dependencies on env variable contents
+		dep_vars = [],
+
+		# input files that are implicit, i.e. they are not
+		# stdin, nor are they mentioned explicitly in argv
+		hidden_inputs = [],
+
+		# output files that are implicit, i.e. they are not
+		# stdout, nor are they mentioned explicitly in argv
+		hidden_outputs = [],
+
+		# change the subprocess to this cwd (must use obj.input_dir() or output_dir() here)
+		cwd = None,
+
+		# OS environment variables to pass to the subprocess
+		# if None, use the default environment variables unchanged
+		os_env = None)
+
+@feature('command-output')
+@after_method('init_cmd_output')
+def apply_cmd_output(self):
+	if self.command is None:
+		raise Errors.WafError("command-output missing command")
+	if self.command_is_external:
+		cmd = self.command
+		cmd_node = None
+	else:
+		cmd_node = self.path.find_resource(self.command)
+		assert cmd_node is not None, ('''Could not find command '%s' in source tree.
+Hint: if this is an external command,
+use command_is_external=True''') % (self.command,)
+		cmd = cmd_node
+
+	if self.cwd is None:
+		cwd = None
+
+	args = []
+	inputs = []
+	outputs = []
+
+	for arg in self.argv:
+		if isinstance(arg, cmd_arg):
+			arg.find_node(self.path)
+			if isinstance(arg, input_file):
+				inputs.append(arg.node)
+			if isinstance(arg, output_file):
+				outputs.append(arg.node)
+
+	if self.stdout is None:
+		stdout = None
+	else:
+		assert isinstance(self.stdout, str)
+		stdout = self.path.find_or_declare(self.stdout)
+		if stdout is None:
+			raise Errors.WafError("File %s not found" % (self.stdout,))
+		outputs.append(stdout)
+
+	if self.stderr is None:
+		stderr = None
+	else:
+		assert isinstance(self.stderr, str)
+		stderr = self.path.find_or_declare(self.stderr)
+		if stderr is None:
+			raise Errors.WafError("File %s not found" % (self.stderr,))
+		outputs.append(stderr)
+
+	if self.stdin is None:
+		stdin = None
+	else:
+		assert isinstance(self.stdin, str)
+		stdin = self.path.find_resource(self.stdin)
+		if stdin is None:
+			raise Errors.WafError("File %s not found" % (self.stdin,))
+		inputs.append(stdin)
+
+	for hidden_input in self.to_list(self.hidden_inputs):
+		node = self.path.find_resource(hidden_input)
+		if node is None:
+			raise Errors.WafError("File %s not found in dir %s" % (hidden_input, self.path))
+		inputs.append(node)
+
+	for hidden_output in self.to_list(self.hidden_outputs):
+		node = self.path.find_or_declare(hidden_output)
+		if node is None:
+			raise Errors.WafError("File %s not found in dir %s" % (hidden_output, self.path))
+		outputs.append(node)
+
+	if not (inputs or getattr(self, 'no_inputs', None)):
+		raise Errors.WafError('command-output objects must have at least one input file or give self.no_inputs')
+	if not (outputs or getattr(self, 'no_outputs', None)):
+		raise Errors.WafError('command-output objects must have at least one output file or give self.no_outputs')
+
+	cwd = self.bld.variant_dir
+	task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr)
+	task.generator = self
+	copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True)
+	self.tasks.append(task)
+
+	task.inputs = inputs
+	task.outputs = outputs
+	task.dep_vars = self.to_list(self.dep_vars)
+
+	for dep in self.dependencies:
+		assert dep is not self
+		dep.post()
+		for dep_task in dep.tasks:
+			task.set_run_after(dep_task)
+
+	if not task.inputs:
+		# the case for svnversion, always run, and update the output nodes
+		task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run
+		task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__)
+
+	# TODO the case with no outputs?
+
+def post_run(self):
+	for x in self.outputs:
+		x.sig = Utils.h_file(x.abspath())
+
+def runnable_status(self):
+	return self.RUN_ME
+
+Task.task_factory('copy', vars=[], func=action_process_file_func)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/relocation.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,85 @@
+#! /usr/bin/env python
+# encoding: utf-8
+
+"""
+Waf 1.6
+
+Try to detect if the project directory was relocated, and if it was,
+change the node representing the project directory. Just call:
+
+ waf configure build
+
+Note that if the project directory name changes, the signatures for the tasks using
+files in that directory will change, causing a partial build.
+"""
+from __future__ import print_function
+import os
+from waflib import Build, ConfigSet, Task, Utils, Errors
+from waflib.TaskGen import feature, before_method, after_method
+
+EXTRA_LOCK = '.old_srcdir'
+
+old1 = Build.BuildContext.store
+def store(self):
+	old1(self)
+	db = os.path.join(self.variant_dir, EXTRA_LOCK)
+	env = ConfigSet.ConfigSet()
+	env.SRCDIR = self.srcnode.abspath()
+	env.store(db)
+Build.BuildContext.store = store
+
+old2 = Build.BuildContext.init_dirs
+def init_dirs(self):
+
+	if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)):
+		raise Errors.WafError('The project was not configured: run "waf configure" first!')
+
+	srcdir = None
+	db = os.path.join(self.variant_dir, EXTRA_LOCK)
+	env = ConfigSet.ConfigSet()
+	try:
+		env.load(db)
+		srcdir = env.SRCDIR
+	except:
+		pass
+
+	if srcdir:
+		d = self.root.find_node(srcdir)
+		if d and srcdir != self.top_dir and getattr(d, 'children', ''):
+			srcnode = self.root.make_node(self.top_dir)
+			print(("relocating the source directory %r -> %r" % (srcdir, self.top_dir)))
+			srcnode.children = {}
+
+			for (k, v) in list(d.children.items()):
+				srcnode.children[k] = v
+				v.parent = srcnode
+			d.children = {}
+
+	old2(self)
+
+Build.BuildContext.init_dirs = init_dirs
+
+
+def uid(self):
+	try:
+		return self.uid_
+	except AttributeError:
+		# this is not a real hot zone, but we want to avoid surprises here
+		m = Utils.md5()
+		up = m.update
+		up(self.__class__.__name__.encode())
+		for x in self.inputs + self.outputs:
+			up(x.path_from(x.ctx.srcnode).encode())
+		self.uid_ = m.digest()
+		return self.uid_
+Task.Task.uid = uid
+
+@feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes')
+@after_method('propagate_uselib_vars', 'process_source')
+def apply_incpaths(self):
+	lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES'])
+	self.includes_nodes = lst
+	bld = self.bld
+	self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.bldnode) or x.abspath() for x in lst]
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/waf-tools/shellcmd.py	Thu Aug 18 16:06:49 2016 +0200
@@ -0,0 +1,357 @@
+# Copyright (C) 2008 Gustavo J. A. M. Carneiro  <gjcarneiro@gmail.com>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from __future__ import print_function
+import shlex
+import subprocess
+import sys
+import re
+import os
+
+env_var_rx = re.compile(r"^([a-zA-Z0-9_]+)=(\S+)$")
+
+def debug(message):
+    print(message, file=sys.stderr)
+
+
+if sys.platform == 'win32':
+    dev_null = open("NUL:", "w")
+else:
+    dev_null = open("/dev/null", "w")
+
+fcntl = fd = fl = None
+try:
+    import fcntl
+except ImportError:
+    pass
+else:
+    fd = dev_null.fileno()
+    fl = fcntl.fcntl(fd, fcntl.F_GETFD)
+    fcntl.fcntl(fd, fcntl.F_SETFD, fl | fcntl.FD_CLOEXEC)
+del fcntl, fd, fl
+
+def _open_out_file(filename):
+    if filename in ['NUL:', '/dev/null']:
+        return dev_null
+    else:
+        return open(filename, 'wb')
+
+
+class Node(object):
+    pass
+
+class Op(Node):
+    pass
+
+class Pipe(Op):
+    pass
+
+class And(Op):
+    pass
+
+class Or(Op):
+    pass
+
+class Command(Node):
+    class PIPE(object):
+        pass # PIPE is a constant
+    class STDOUT(object):
+        pass # PIPE is a constant
+
+    def __init__(self, name):
+        super(Command, self).__init__()
+        self.name = name # command name
+        self.argv = [name] # command argv
+        self.stdin = None
+        self.stdout = None
+        self.stderr = None
+        self.env_vars = None
+
+    def __repr__(self):
+        return "Command(%r, argv=%r, stdin=%r, stdout=%r, stderr=%r)" \
+            % (self.name, self.argv, self.stdin, self.stdout, self.stderr)
+
+class Chdir(Node):
+    def __init__(self):
+        super(Chdir, self).__init__()
+        self.dir = None
+
+    def __repr__(self):
+        return "Chdir(%r)" \
+            % (self.dir)
+
+class Pipeline(object):
+    def __init__(self):
+        self.current_command = None
+        self.pipeline = []
+
+    def _commit_command(self):
+        assert self.current_command is not None
+        self.pipeline.append(self.current_command)
+        self.current_command = None
+
+    def get_abbreviated_command(self):
+        l = []
+        for node in self.pipeline:
+            if isinstance(node, Command):
+                l.append(node.name)
+            if isinstance(node, Chdir):
+                l.append('cd %s' % node.dir)
+            elif isinstance(node, Pipe):
+                l.append('|')
+            elif isinstance(node, And):
+                l.append('&&')
+            elif isinstance(node, And):
+                l.append('||')
+        return ' '.join(l)
+
+    def parse(self, command):
+        self.current_command = None
+        self.pipeline = []
+
+        if isinstance(command, list):
+            tokens = list(command)
+        else:
+            tokens = shlex.split(command)
+        debug("command: shlex: %r" % (tokens,))
+
+        BEGIN, COMMAND, CHDIR, STDERR, STDOUT, STDIN = list(range(6))
+        state = BEGIN
+        self.current_command = None
+        env_vars = dict()
+
+        while tokens:
+            token = tokens.pop(0)
+            if state == BEGIN:
+                env_var_match = env_var_rx.match(token)
+                if env_var_match is not None:
+                    env_vars[env_var_match.group(1)] = env_var_match.group(2)
+                else:
+                    assert self.current_command is None
+                    if token == 'cd':
+                        self.current_command = Chdir()
+                        assert not env_vars
+                        state = CHDIR
+                    else:
+                        self.current_command = Command(token)
+                        if env_vars:
+                            self.current_command.env_vars = env_vars
+                            env_vars = dict()
+                        state = COMMAND
+            elif state == COMMAND:
+                if token == '>':
+                    state = STDOUT
+                elif token == '2>':
+                    state = STDERR
+                elif token == '2>&1':
+                    assert self.current_command.stderr is None
+                    self.current_command.stderr = Command.STDOUT
+                elif token == '<':
+                    state = STDIN
+                elif token == '|':
+                    assert self.current_command.stdout is None
+                    self.current_command.stdout = Command.PIPE
+                    self._commit_command()
+                    self.pipeline.append(Pipe())
+                    state = BEGIN
+                elif token == '&&':
+                    self._commit_command()
+                    self.pipeline.append(And())
+                    state = BEGIN
+                elif token == '||':
+                    self._commit_command()
+                    self.pipeline.append(Or())
+                    state = BEGIN
+                else:
+                    self.current_command.argv.append(token)
+            elif state == CHDIR:
+                if token == '&&':
+                    self._commit_command()
+                    self.pipeline.append(And())
+                    state = BEGIN
+                else:
+                    assert self.current_command.dir is None
+                    self.current_command.dir = token
+            elif state == STDOUT:
+                assert self.current_command.stdout is None
+                self.current_command.stdout = token
+                state = COMMAND
+            elif state == STDERR:
+                assert self.current_command.stderr is None
+                self.current_command.stderr = token
+                state = COMMAND
+            elif state == STDIN:
+                assert self.current_command.stdin is None
+                self.current_command.stdin = token
+                state = COMMAND
+        self._commit_command()
+        return self.pipeline
+
+    def _exec_piped_commands(self, commands):
+        retvals = []
+        for cmd in commands:
+            retvals.append(cmd.wait())
+        retval = 0
+        for r in retvals:
+            if r:
+                retval = retvals[-1]
+                break
+        return retval
+
+    def run(self, verbose=False):
+        pipeline = list(self.pipeline)
+        files_to_close = []
+        piped_commands = []
+        piped_commands_display = []
+        BEGIN, PIPE = list(range(2))
+        state = BEGIN
+        cwd = '.'
+        while pipeline:
+            node = pipeline.pop(0)
+
+            if isinstance(node, Chdir):
+                next_op = pipeline.pop(0)
+                assert isinstance(next_op, And)
+                cwd = os.path.join(cwd, node.dir)
+                if verbose:
+                    piped_commands_display.append("cd %s &&" % node.dir)
+                continue
+            
+            assert isinstance(node, (Command, Chdir))
+            cmd = node
+            if verbose:
+                if cmd.env_vars:
+                    env_vars_str = ' '.join(['%s=%s' % (key, val) for key, val in cmd.env_vars.items()])
+                    piped_commands_display.append("%s %s" % (env_vars_str, ' '.join(cmd.argv)))
+                else:
+                    piped_commands_display.append(' '.join(cmd.argv))
+
+            if state == PIPE:
+                stdin = piped_commands[-1].stdout
+            elif cmd.stdin is not None:
+                stdin = open(cmd.stdin, "r")
+                if verbose:
+                    piped_commands_display.append('< %s' % cmd.stdin)
+                files_to_close.append(stdin)
+            else:
+                stdin = None
+
+            if cmd.stdout is None:
+                stdout = None
+            elif cmd.stdout is Command.PIPE:
+                stdout = subprocess.PIPE
+            else:
+                stdout = _open_out_file(cmd.stdout)
+                files_to_close.append(stdout)
+                if verbose:
+                    piped_commands_display.append('> %s' % cmd.stdout)
+
+            if cmd.stderr is None:
+                stderr = None
+            elif cmd.stderr is Command.PIPE:
+                stderr = subprocess.PIPE
+            elif cmd.stderr is Command.STDOUT:
+                stderr = subprocess.STDOUT
+                if verbose:
+                    piped_commands_display.append('2>&1')
+            else:
+                stderr = _open_out_file(cmd.stderr)
+                files_to_close.append(stderr)
+                if verbose:
+                    piped_commands_display.append('2> %s' % cmd.stderr)
+
+            if cmd.env_vars:
+                env = dict(os.environ)
+                env.update(cmd.env_vars)
+            else:
+                env = None
+
+            if cwd == '.':
+                proc_cwd = None
+            else:
+                proc_cwd = cwd
+
+            debug("command: subprocess.Popen(argv=%r, stdin=%r, stdout=%r, stderr=%r, env_vars=%r, cwd=%r)"
+                  % (cmd.argv, stdin, stdout, stderr, cmd.env_vars, proc_cwd))
+            proc = subprocess.Popen(cmd.argv, stdin=stdin, stdout=stdout, stderr=stderr, env=env, cwd=proc_cwd)
+            del stdin, stdout, stderr
+            piped_commands.append(proc)
+
+            try:
+                next_node = pipeline.pop(0)
+            except IndexError:
+                try:
+                    retval = self._exec_piped_commands(piped_commands)
+                    if verbose:
+                        print("%s: exit code %i" % (' '.join(piped_commands_display), retval))
+                finally:
+                    for f in files_to_close:
+                        if f is not dev_null:
+                            f.close()
+                    files_to_close = []
+                return retval
+            else:
+
+                if isinstance(next_node, Pipe):
+                    state = PIPE
+                    piped_commands_display.append('|')
+
+                elif isinstance(next_node, Or):
+                    try:
+                        this_retval = self._exec_piped_commands(piped_commands)
+                    finally:
+                        for f in files_to_close:
+                            if f is not dev_null:
+                                f.close()
+                        files_to_close = []
+                    if this_retval == 0:
+                        if verbose:
+                            print("%s: exit code %i (|| is short-circuited)" % (' '.join(piped_commands_display), retval))
+                        return this_retval
+                    if verbose:
+                        print("%s: exit code %i (|| proceeds)" % (' '.join(piped_commands_display), retval))
+                    state = BEGIN
+                    piped_commands = []
+                    piped_commands_display = []
+
+                elif isinstance(next_node, And):
+                    try:
+                        this_retval = self._exec_piped_commands(piped_commands)
+                    finally:
+                        for f in files_to_close:
+                            if f is not dev_null:
+                                f.close()
+                        files_to_close = []
+                    if this_retval != 0:
+                        if verbose:
+                            print("%s: exit code %i (&& is short-circuited)" % (' '.join(piped_commands_display), retval))
+                        return this_retval
+                    if verbose:
+                        print("%s: exit code %i (&& proceeds)" % (' '.join(piped_commands_display), retval))
+                    state = BEGIN
+                    piped_commands = []
+                    piped_commands_display = []
+
+
+
+def _main():
+    pipeline = Pipeline()
+    pipeline.parse('./foo.py 2>&1 < xxx | cat && ls')
+    print(pipeline.run())
+
+if __name__ == '__main__':
+    _main()
+
--- a/wscript	Thu Aug 18 15:10:37 2016 +0200
+++ b/wscript	Thu Aug 18 16:06:49 2016 +0200
@@ -1,7 +1,6 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 import os
-import Options
 import os.path
 import ns3waf
 import sys
@@ -9,11 +8,12 @@
 # local modules
 import wutils
 import subprocess
-import Logs
+from waflib import Utils, Scripting, Configure, Build, Options, TaskGen, Context, Task, Logs, Errors
 from waflib.Errors import WafError
 
 def options(opt):
-    opt.tool_options('compiler_cc') 
+    opt.load('compiler_c')
+    opt.load('compiler_cxx')
     ns3waf.options(opt)
     opt.add_option('--enable-kernel-stack',
                    help=('Path to the prefix where the kernel wrapper headers are installed'),
@@ -77,6 +77,15 @@
     return None
 
 def configure(conf):
+
+    conf.load('relocation', tooldir=['waf-tools'])
+    conf.load('compiler_c')
+    cc_string = '.'.join(conf.env['CC_VERSION'])
+    conf.msg('Checking for cc version',cc_string,'GREEN')
+    conf.load('compiler_cxx')
+
+    conf.load('clang_compilation_database', tooldir=['waf-tools'])
+
     if Options.options.with_ns3 is not None and os.path.isdir(Options.options.with_ns3):
         conf.env['NS3_DIR']= os.path.abspath(Options.options.with_ns3)
         if not 'PKG_CONFIG_PATH' in os.environ:
@@ -96,7 +105,6 @@
     ns3waf.check_modules(conf, ['visualizer'], mandatory = False)
     ns3waf.check_modules(conf, ['applications'], mandatory = False)
     ns3waf.check_modules(conf, ['fd-net-device'], mandatory = False)
-    conf.check_tool('compiler_cc')
     conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H', mandatory=False)
     conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H', mandatory=False)
     conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H', mandatory=False)
--- a/wutils.py	Thu Aug 18 15:10:37 2016 +0200
+++ b/wutils.py	Thu Aug 18 16:06:49 2016 +0200
@@ -3,15 +3,11 @@
 import sys
 import subprocess
 import shlex
+import re
 
 # WAF modules
-import Options
-import Utils
-import Logs
-import TaskGen
-import Build
-import re
 from waflib.Errors import WafError
+from waflib import Utils, Scripting, Configure, Build, Options, TaskGen, Context, Task, Logs, Errors
 
 # these are set from the main wscript file
 APPNAME=None