diff --git a/.hgignore b/.hgignore index ba9effb2d..97329aa78 100644 --- a/.hgignore +++ b/.hgignore @@ -7,7 +7,7 @@ ^testpy-output ^doc/html ^doc/latex -^\.lock-wscript +^\.lock-wafbuild ^\.waf ^doc/introspected-doxygen\.h$ .*\.py[co]$ diff --git a/bindings/python/wscript b/bindings/python/wscript index 3dc3e33fe..c7c5b43fb 100644 --- a/bindings/python/wscript +++ b/bindings/python/wscript @@ -2,7 +2,7 @@ import types import re import os -import pproc as subprocess +import subprocess import shutil import sys @@ -14,6 +14,8 @@ import Logs import Build import Utils +from waflib.Errors import WafError + ## https://launchpad.net/pybindgen/ REQUIRED_PYBINDGEN_VERSION = (0, 15, 0, 795) REQUIRED_PYGCCXML_VERSION = (0, 9, 5) @@ -21,17 +23,17 @@ REQUIRED_PYGCCXML_VERSION = (0, 9, 5) from TaskGen import feature, after -import Task, ccroot -from python import _get_python_variables # this comes from wafadmin/Tools/python.py +import Task +#from python import _get_python_variables # this comes from wafadmin/Tools/python.py - -# Patch a bug in waf-1.5.16's python detection, see -# https://www.nsnam.org/bugzilla/show_bug.cgi?id=1250 -import python -python.FRAG_2 = """ -#include -""" + python.FRAG_2 -del python +if 0: + # Patch a bug in waf-1.5.16's python detection, see + # https://www.nsnam.org/bugzilla/show_bug.cgi?id=1250 + import python + python.FRAG_2 = """ + #include + """ + python.FRAG_2 + del python @@ -46,18 +48,14 @@ def set_pybindgen_pythonpath(env): add_to_python_path(env['WITH_PYBINDGEN']) -def set_options(opt): +def options(opt): opt.tool_options('python') opt.add_option('--disable-python', help=("Don't build Python bindings."), action="store_true", default=False, dest='python_disable') - opt.add_option('--python-scan', - help=("Rescan Python bindings. Needs working GCCXML / pygccxml environment."), - action="store_true", default=False, - dest='python_scan') opt.add_option('--apiscan', - help=("EXPERIMENTAL: Rescan the API for the indicated module(s), for Python bindings. " + help=("Rescan the API for the indicated module(s), for Python bindings. " "Needs working GCCXML / pygccxml environment. " "The metamodule 'all' expands to all available ns-3 modules."), default=None, dest='apiscan', metavar="MODULE[,MODULE...]") @@ -86,7 +84,7 @@ def configure(conf): available_modules.sort() all_modules_enabled = (enabled_modules == available_modules) - conf.check_tool('misc') + conf.check_tool('misc', tooldir=['waf-tools']) if sys.platform == 'cygwin': conf.report_optional_feature("python", "Python Bindings", False, @@ -103,17 +101,33 @@ def configure(conf): conf.report_optional_feature("python", "Python Bindings", False, str(ex)) return + # stupid Mac OSX Python wants to build extensions as "universal + # binaries", i386, x86_64, and ppc, but this way the type + # __uint128_t is not available. We need to disable the multiarch + # crap by removing the -arch parameters. + for flags_var in ["CFLAGS_PYEXT", "CFLAGS_PYEMBED", "CXXFLAGS_PYEMBED", + "CXXFLAGS_PYEXT", "LINKFLAGS_PYEMBED", "LINKFLAGS_PYEXT"]: + flags = conf.env[flags_var] + i = 0 + while i < len(flags): + if flags[i] == '-arch': + del flags[i] + del flags[i] + continue + i += 1 + conf.env[flags_var] = flags - # alternative code to computing PYTHONDIR, that is more correct than the one in waf 1.5.16 - if 'PYTHONDIR' in conf.environ: - pydir = conf.environ['PYTHONDIR'] - else: - (pydir,) = _get_python_variables(conf.env['PYTHON'], - ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r)" % conf.env['PREFIX']], - ['from distutils.sysconfig import get_python_lib']) - if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist - conf.define('PYTHONDIR', pydir) - conf.env['PYTHONDIR'] = pydir + if 0: + # alternative code to computing PYTHONDIR, that is more correct than the one in waf 1.5.16 + if 'PYTHONDIR' in conf.environ: + pydir = conf.environ['PYTHONDIR'] + else: + (pydir,) = _get_python_variables(conf.env['PYTHON'], + ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r)" % conf.env['PREFIX']], + ['from distutils.sysconfig import get_python_lib']) + if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist + conf.define('PYTHONDIR', pydir) + conf.env['PYTHONDIR'] = pydir # -fvisibility=hidden optimization @@ -125,7 +139,7 @@ def configure(conf): # Check for the location of pybindgen if Options.options.with_pybindgen is not None: if os.path.isdir(Options.options.with_pybindgen): - conf.check_message("pybindgen location", '', True, ("%s (given)" % Options.options.with_pybindgen)) + conf.msg("Checking for pybindgen location", ("%s (given)" % Options.options.with_pybindgen)) conf.env['WITH_PYBINDGEN'] = os.path.abspath(Options.options.with_pybindgen) else: # ns-3-dev uses ../pybindgen, while ns-3 releases use ../REQUIRED_PYBINDGEN_VERSION @@ -133,15 +147,15 @@ def configure(conf): pybindgen_release_str = "pybindgen-" + '.'.join([str(x) for x in REQUIRED_PYBINDGEN_VERSION]) pybindgen_release_dir = os.path.join('..', pybindgen_release_str) if os.path.isdir(pybindgen_dir): - conf.check_message("pybindgen location", '', True, ("%s (guessed)" % pybindgen_dir)) + conf.msg("Checking for pybindgen location", ("%s (guessed)" % pybindgen_dir)) conf.env['WITH_PYBINDGEN'] = os.path.abspath(pybindgen_dir) elif os.path.isdir(pybindgen_release_dir): - conf.check_message("pybindgen location", '', True, ("%s (guessed)" % pybindgen_release_dir)) + conf.msg("Checking for pybindgen location", ("%s (guessed)" % pybindgen_release_dir)) conf.env['WITH_PYBINDGEN'] = os.path.abspath(pybindgen_release_dir) del pybindgen_dir del pybindgen_release_dir if not conf.env['WITH_PYBINDGEN']: - conf.check_message("pybindgen location", '', False) + conf.msg("pybindgen location", False) # Check for pybindgen @@ -155,15 +169,13 @@ def configure(conf): "PyBindGen missing") return else: - out = subprocess.Popen([conf.env['PYTHON'], "-c", + out = subprocess.Popen([conf.env['PYTHON'][0], "-c", "import pybindgen.version; " "print '.'.join([str(x) for x in pybindgen.version.__version__])"], stdout=subprocess.PIPE).communicate()[0] pybindgen_version_str = out.strip() pybindgen_version = tuple([int(x) for x in pybindgen_version_str.split('.')]) - conf.check_message('pybindgen', 'version', - (pybindgen_version == REQUIRED_PYBINDGEN_VERSION), - pybindgen_version_str) + conf.msg('Checking for pybindgen version', pybindgen_version_str) if not (pybindgen_version == REQUIRED_PYBINDGEN_VERSION): Logs.warn("pybindgen (found %s), (need %s)" % (pybindgen_version_str, @@ -188,10 +200,10 @@ int main () try: ret = conf.run_c_code(code=test_program, env=conf.env.copy(), compile_filename='test.cc', - compile_mode='cxx',type='cprogram', execute=False) + features='cxx cprogram', execute=False) except Configure.ConfigurationError: ret = 1 - conf.check_message_custom('types %s and %s' % (t1, t2), 'equivalency', (ret and 'no' or 'yes')) + conf.msg('Checking for types %s and %s equivalence' % (t1, t2), (ret and 'no' or 'yes')) return not ret uint64_is_long = test("uint64_t", "unsigned long") @@ -208,7 +220,7 @@ int main () else: msg = conf.env['PYTHON_BINDINGS_APIDEFS'] - conf.check_message_custom('the apidefs that can be used for Python bindings', '', msg) + conf.msg('Checking for the apidefs that can be used for Python bindings', msg) if conf.env['PYTHON_BINDINGS_APIDEFS'] is None: conf.report_optional_feature("python", "Python Bindings", False, @@ -230,9 +242,9 @@ int main () return 0; } """ - gcc_rtti_abi = conf.check(fragment=fragment, msg="Checking for internal GCC cxxabi", - okmsg="complete", errmsg='incomplete', - mandatory=False) + gcc_rtti_abi = conf.check_nonfatal(fragment=fragment, msg="Checking for internal GCC cxxabi", + okmsg="complete", errmsg='incomplete', + mandatory=False) conf.env["GCC_RTTI_ABI_COMPLETE"] = str(bool(gcc_rtti_abi)) @@ -245,14 +257,12 @@ int main () "Missing 'pygccxml' Python module") return - out = subprocess.Popen([conf.env['PYTHON'], "-c", + out = subprocess.Popen([conf.env['PYTHON'][0], "-c", "import pygccxml; print pygccxml.__version__"], stdout=subprocess.PIPE).communicate()[0] pygccxml_version_str = out.strip() pygccxml_version = tuple([int(x) for x in pygccxml_version_str.split('.')]) - conf.check_message('pygccxml', 'version', - (pygccxml_version >= REQUIRED_PYGCCXML_VERSION), - pygccxml_version_str) + conf.msg('Checking for pygccxml version', pygccxml_version_str) if not (pygccxml_version >= REQUIRED_PYGCCXML_VERSION): Logs.warn("pygccxml (found %s) is too old (need %s) => " "automatic scanning of API definitions will not be possible" % @@ -264,7 +274,10 @@ int main () ## Check gccxml version - gccxml = conf.find_program('gccxml', var='GCCXML') + try: + gccxml = conf.find_program('gccxml', var='GCCXML') + except WafError: + gccxml = None if not gccxml: Logs.warn("gccxml missing; automatic scanning of API definitions will not be possible") conf.report_optional_feature("pygccxml", "Python API Scanning Support", False, @@ -275,7 +288,7 @@ int main () m = re.match( "^GCC-XML version (\d\.\d(\.\d)?)$", gccxml_version_line) gccxml_version = m.group(1) gccxml_version_ok = ([int(s) for s in gccxml_version.split('.')] >= [0, 9]) - conf.check_message('gccxml', 'version', True, gccxml_version) + conf.msg('Checking for gccxml version', gccxml_version) if not gccxml_version_ok: Logs.warn("gccxml too old, need version >= 0.9; automatic scanning of API definitions will not be possible") conf.report_optional_feature("pygccxml", "Python API Scanning Support", False, @@ -291,19 +304,18 @@ int main () def get_headers_map(bld): headers_map = {} # header => module for ns3headers in bld.all_task_gen: - if type(ns3headers).__name__ == 'ns3header_taskgen': # XXX: find less hackish way to compare + if 'ns3header' in getattr(ns3headers, "features", []): if ns3headers.module.endswith('-test'): continue - for h in ns3headers.to_list(ns3headers.source): + for h in ns3headers.to_list(ns3headers.headers): headers_map[os.path.basename(h)] = ns3headers.module return headers_map def get_module_path(bld, module): for ns3headers in bld.all_task_gen: - if type(ns3headers).__name__ == 'ns3header_taskgen': # XXX: find less hackish way to compare + if 'ns3header' in getattr(ns3headers, "features", []): if ns3headers.module == module: break - else: raise ValueError("Module %r not found" % module) return ns3headers.path.abspath() @@ -311,8 +323,8 @@ def get_module_path(bld, module): class apiscan_task(Task.TaskBase): """Uses gccxml to scan the file 'everything.h' and extract API definitions. """ - after = 'gen_ns3_module_header_task ns3header_task' - before = 'cc cxx gchx' + after = 'gen_ns3_module_header ns3header' + before = 'cc cxx command' color = "BLUE" def __init__(self, curdirnode, env, bld, target, cflags, module): self.bld = bld @@ -327,7 +339,7 @@ class apiscan_task(Task.TaskBase): return 'api-scan-%s\n' % (self.target,) def run(self): - top_builddir = self.curdirnode.find_dir('../..').abspath(self.env) + top_builddir = self.bld.bldnode.abspath() module_path = get_module_path(self.bld, self.module) headers_map = get_headers_map(self.bld) scan_header = os.path.join(top_builddir, "ns3", "%s-module.h" % self.module) @@ -337,7 +349,7 @@ class apiscan_task(Task.TaskBase): return 0 argv = [ - self.env['PYTHON'], + self.env['PYTHON'][0], os.path.join(self.curdirnode.abspath(), 'ns3modulescan-modular.py'), # scanning script top_builddir, self.module, @@ -367,58 +379,22 @@ def get_modules_and_headers(bld): ## find the headers object for this module headers = [] for ns3headers in bld.all_task_gen: - if type(ns3headers).__name__ != 'ns3header_taskgen': # XXX: find less hackish way to compare + if 'ns3header' not in getattr(ns3headers, "features", []): continue if ns3headers.module != module_name: continue - for source in ns3headers.to_list(ns3headers.source): + for source in ns3headers.to_list(ns3headers.headers): headers.append(os.path.basename(source)) retval[module_name] = (list(module.module_deps), headers) return retval -class python_scan_task(Task.TaskBase): - """Uses gccxml to scan the file 'everything.h' and extract API definitions. - """ - after = 'gen_everything_h_task' - before = 'cc cxx gchx' - color = "BLUE" - def __init__(self, curdirnode, env, bld, target, cflags): - self.bld = bld - super(python_scan_task, self).__init__(generator=self) - self.curdirnode = curdirnode - self.env = env - self.target = target - self.cflags = cflags - - def display(self): - return 'python-scan-%s\n' % (self.target,) - - def run(self): - defsdir = os.path.join(self.curdirnode.abspath(), 'apidefs', self.target) - try: - os.mkdir(defsdir) - except OSError: - pass - argv = [ - self.env['PYTHON'], - os.path.join(self.curdirnode.abspath(), 'ns3modulescan.py'), # scanning script - self.curdirnode.find_dir('../..').abspath(self.env), # include path (where the ns3 include dir is) - self.curdirnode.find_or_declare('everything.h').abspath(self.env), - os.path.join(defsdir, 'ns3modulegen_generated.py'), # output file - self.cflags, - ] - scan = subprocess.Popen(argv, stdin=subprocess.PIPE) - print >> scan.stdin, repr(get_modules_and_headers(self.bld)) - scan.stdin.close() - retval = scan.wait() - return retval class python_scan_task_collector(Task.TaskBase): """Tasks that waits for the python-scan-* tasks to complete and then signals WAF to exit """ - after = 'python_scan_task apiscan_task' + after = 'apiscan' before = 'cc cxx' color = "BLUE" def __init__(self, curdirnode, env, bld): @@ -434,19 +410,20 @@ class python_scan_task_collector(Task.TaskBase): # signal stop (we generated files into the source dir and WAF # can't cope with it, so we have to force the user to restart # WAF) - self.bld.generator.stop = 1 + self.bld.producer.stop = 1 + self.bld.producer.free_task_pool() return 0 class gen_ns3_compat_pymod_task(Task.Task): """Generates a 'ns3.py' compatibility module.""" - before = 'cc cxx gchx' + before = 'cc cxx' color = 'BLUE' def run(self): assert len(self.outputs) == 1 - outfile = file(self.outputs[0].abspath(self.env), "w") + outfile = file(self.outputs[0].abspath(), "w") print >> outfile, "import warnings" print >> outfile, 'warnings.warn("the ns3 module is a compatibility layer '\ 'and should not be used in newly written code", DeprecationWarning, stacklevel=2)' @@ -505,16 +482,20 @@ def build(bld): scan_modules = Options.options.apiscan.split(',') print "Modules to scan: ", scan_modules for target, cflags in scan_targets: + group = bld.get_group(bld.current_group) for module in scan_modules: - apiscan_task(bld.path, env, bld, target, cflags, module) - python_scan_task_collector(bld.path, env, bld) + group.append(apiscan_task(bld.path, env, bld, target, cflags, module)) + group.append(python_scan_task_collector(bld.path, env, bld)) return if env['ENABLE_PYTHON_BINDINGS']: - task = gen_ns3_compat_pymod_task(env) + task = gen_ns3_compat_pymod_task(env=env.derive()) task.set_outputs(bld.path.find_or_declare("ns3.py")) task.dep_vars = ['PYTHON_MODULES_BUILT'] + task.bld = bld + grp = bld.get_group(bld.current_group) + grp.append(task) # note: the actual build commands for the python bindings are in # src/wscript, not here. diff --git a/src/aodv/wscript b/src/aodv/wscript index cdb113ccf..6209a5b26 100644 --- a/src/aodv/wscript +++ b/src/aodv/wscript @@ -23,7 +23,7 @@ def build(bld): 'test/loopback.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'aodv' headers.source = [ 'model/aodv-id-cache.h', diff --git a/src/applications/wscript b/src/applications/wscript index 695abf946..684d1ce90 100644 --- a/src/applications/wscript +++ b/src/applications/wscript @@ -32,7 +32,7 @@ def build(bld): 'test/udp-client-server-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'applications' headers.source = [ 'model/bulk-send-application.h', diff --git a/src/bridge/wscript b/src/bridge/wscript index 5d3c8a744..8ff5e22af 100644 --- a/src/bridge/wscript +++ b/src/bridge/wscript @@ -7,7 +7,7 @@ def build(bld): 'model/bridge-channel.cc', 'helper/bridge-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'bridge' headers.source = [ 'model/bridge-net-device.h', diff --git a/src/click/wscript b/src/click/wscript index a600b78ee..fb7423cba 100644 --- a/src/click/wscript +++ b/src/click/wscript @@ -4,24 +4,32 @@ import os import Options -def set_options(opt): +def options(opt): opt.add_option('--with-nsclick', help=('Path to Click source or installation prefix for NS-3 Click Integration support'), dest='with_nsclick', default=None) + opt.add_option('--disable-nsclick', + help=('Disable NS-3 Click Integration support'), + dest='disable_nsclick', default=False, action="store_true") def configure(conf): + if Options.options.disable_nsclick: + conf.report_optional_feature("nsclick", "NS-3 Click Integration", False, + "disabled by user request") + return + if Options.options.with_nsclick: if os.path.isdir(Options.options.with_nsclick): - conf.check_message("libnsclick.so location", '', True, ("%s (given)" % Options.options.with_nsclick)) + conf.msg("libnsclick.so location", ("%s (given)" % Options.options.with_nsclick)) conf.env['WITH_NSCLICK'] = os.path.abspath(Options.options.with_nsclick) else: nsclick_dir = os.path.join('..','click') if os.path.isdir(nsclick_dir): - conf.check_message("click location", '', True, ("%s (guessed)" % nsclick_dir)) + conf.msg("click location", ("%s (guessed)" % nsclick_dir)) conf.env['WITH_NSCLICK'] = os.path.abspath(nsclick_dir) del nsclick_dir if not conf.env['WITH_NSCLICK']: - conf.check_message("click location", '', False) + conf.msg("click location", False) conf.report_optional_feature("nsclick", "NS-3 Click Integration", False, "nsclick not enabled (see option --with-nsclick)") @@ -58,7 +66,7 @@ int main() return 0; } ''' - conf.env['DL'] = conf.check(mandatory=True, lib='dl', define_name='DL', uselib='DL') + conf.env['DL'] = conf.check(mandatory=True, lib='dl', define_name='DL', uselib_store='DL') for tmp in ['lib', 'ns']: libdir = os.path.abspath(os.path.join(conf.env['WITH_NSCLICK'],tmp)) @@ -68,11 +76,11 @@ int main() conf.env['CPPPATH_NSCLICK'] = [os.path.abspath(os.path.join(conf.env['WITH_NSCLICK'],'include'))] - conf.env['NSCLICK'] = conf.check(fragment=test_code, lib='nsclick', uselib='NSCLICK DL') + conf.env['NSCLICK'] = conf.check_nonfatal(fragment=test_code, lib='nsclick', use='DL', uselib_store='NSCLICK') conf.report_optional_feature("nsclick", "NS-3 Click Integration", conf.env['NSCLICK'], "nsclick library not found") if conf.env['NSCLICK']: - conf.env.append_value('CXXDEFINES', 'NS3_CLICK') + conf.env.append_value('DEFINES', 'NS3_CLICK') conf.env.append_value('CPPPATH', conf.env['CPPPATH_NSCLICK']) else: # Add this module to the list of modules that won't be built @@ -84,7 +92,7 @@ def build(bld): if 'click' in bld.env['MODULES_NOT_BUILT']: return - module = bld.create_ns3_module('click', ['internet']) + module = bld.create_ns3_module('click', ['core', 'network', 'internet']) module.includes = '. CPPPATH_NSCLICK' module.source = [ 'model/ipv4-click-routing.cc', @@ -98,10 +106,10 @@ def build(bld): ] if bld.env['NSCLICK'] and bld.env['DL']: - module.uselib = 'NSCLICK DL' - module_test.uselib = 'NSCLICK DL' + module.use = 'NSCLICK DL' + module_test.use = 'NSCLICK DL' - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'click' headers.source = [ 'model/ipv4-click-routing.h', diff --git a/src/config-store/wscript b/src/config-store/wscript index 49f016caa..c52b51e7a 100644 --- a/src/config-store/wscript +++ b/src/config-store/wscript @@ -29,7 +29,7 @@ def build(bld): 'model/raw-text-config.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'config-store' headers.source = [ 'model/file-config.h', diff --git a/src/core/model/int64x64-128.h b/src/core/model/int64x64-128.h index d1a60c605..a116b8874 100644 --- a/src/core/model/int64x64-128.h +++ b/src/core/model/int64x64-128.h @@ -6,7 +6,7 @@ #include #include -#if defined(HAVE___UINT128_T)and !defined(HAVE_UINT128_T) +#if defined(HAVE___UINT128_T) && !defined(HAVE_UINT128_T) typedef __uint128_t uint128_t; typedef __int128_t int128_t; #endif diff --git a/src/core/wscript b/src/core/wscript index 74e8afe51..07db59c19 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -3,7 +3,7 @@ import sys import Options -def set_options(opt): +def options(opt): opt.add_option('--int64x64-as-double', help=('Whether to use a double floating point' ' type for int64x64 values' @@ -15,9 +15,8 @@ def set_options(opt): def configure(conf): - a = conf.check(type_name='uint128_t', define_name='HAVE_UINT128_T') - b = conf.check(type_name='__uint128_t', define_name='HAVE___UINT128_T') - + a = conf.check_nonfatal(type_name='uint128_t', define_name='HAVE_UINT128_T') + b = conf.check_nonfatal(type_name='__uint128_t', define_name='HAVE___UINT128_T') if Options.options.int64x64_as_double: conf.define('INT64X64_USE_DOUBLE', 1) @@ -32,20 +31,20 @@ def configure(conf): conf.env['INT64X64_USE_CAIRO'] = 1 highprec = 'cairo 128-bit integer' - conf.check_message_custom('high precision time', 'implementation', highprec) + conf.msg('Checking high precision time implementation', highprec) - conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H') - conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H') - conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H') - conf.check(header_name='sys/types.h', define_name='HAVE_SYS_TYPES_H') - conf.check(header_name='sys/stat.h', define_name='HAVE_SYS_STAT_H') - conf.check(header_name='dirent.h', define_name='HAVE_DIRENT_H') + conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H') + conf.check_nonfatal(header_name='inttypes.h', define_name='HAVE_INTTYPES_H') + conf.check_nonfatal(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H') + conf.check_nonfatal(header_name='sys/types.h', define_name='HAVE_SYS_TYPES_H') + conf.check_nonfatal(header_name='sys/stat.h', define_name='HAVE_SYS_STAT_H') + conf.check_nonfatal(header_name='dirent.h', define_name='HAVE_DIRENT_H') - if conf.check(header_name='stdlib.h'): + if conf.check_nonfatal(header_name='stdlib.h'): conf.define('HAVE_STDLIB_H', 1) conf.define('HAVE_GETENV', 1) - conf.check(header_name='signal.h', define_name='HAVE_SIGNAL_H') + conf.check_nonfatal(header_name='signal.h', define_name='HAVE_SIGNAL_H') # Check for POSIX threads test_env = conf.env.copy() @@ -62,10 +61,9 @@ int main () return 0; } """ - have_pthread = conf.check(header_name='pthread.h', define_name='HAVE_PTHREAD_H', - env=test_env, fragment=fragment, - errmsg='Could not find pthread support (build/config.log for details)', - mandatory=False) + have_pthread = conf.check_nonfatal(header_name='pthread.h', define_name='HAVE_PTHREAD_H', + env=test_env, fragment=fragment, + errmsg='Could not find pthread support (build/config.log for details)') if have_pthread: # darwin accepts -pthread but prints a warning saying it is ignored if Options.platform != 'darwin' and Options.platform != 'cygwin': @@ -79,12 +77,12 @@ int main () conf.env['ENABLE_THREADING'], " include not detected") - conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H') - conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H') + conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H') + conf.check_nonfatal(header_name='inttypes.h', define_name='HAVE_INTTYPES_H') - conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H') + conf.check_nonfatal(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H') - if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'): + if not conf.check_nonfatal(lib='rt', uselib='RT', define_name='HAVE_RT'): conf.report_optional_feature("RealTime", "Real Time Simulator", False, "librt is not available") else: @@ -170,7 +168,7 @@ def build(bld): 'test/watchdog-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'core' headers.source = [ 'model/nstime.h', @@ -252,7 +250,7 @@ def build(bld): ]) - env = bld.env_of_name('default') + env = bld.env if env['INT64X64_USE_DOUBLE']: headers.source.extend(['model/int64x64-double.h']) elif env['INT64X64_USE_128']: diff --git a/src/create-module.py b/src/create-module.py new file mode 100755 index 000000000..38622662b --- /dev/null +++ b/src/create-module.py @@ -0,0 +1,207 @@ +#! /usr/bin/env python +import sys +from optparse import OptionParser +import os + + +WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +# def options(opt): +# pass + +# def configure(conf): +# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H') + +def build(bld): + module = bld.create_ns3_module(%(MODULE)r, ['core']) + module.source = [ + 'model/%(MODULE)s.cc', + 'helper/%(MODULE)s-helper.cc', + ] + + headers = bld.new_task_gen(features=['ns3header']) + headers.module = %(MODULE)r + headers.source = [ + 'model/%(MODULE)s.h', + 'helper/%(MODULE)s-helper.h', + ] + + if bld.env.ENABLE_EXAMPLES: + bld.add_subdirs('examples') + + # bld.ns3_python_bindings() + +''' + + + +MODEL_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "%(MODULE)s.h" + +namespace ns3 { + +/* ... */ + + +} + +''' + + + +MODEL_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +#ifndef %(INCLUDE_GUARD)s +#define %(INCLUDE_GUARD)s + +namespace ns3 { + +/* ... */ + +} + +#endif /* %(INCLUDE_GUARD)s */ + +''' + + + +HELPER_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "%(MODULE)s-helper.h" + +namespace ns3 { + +/* ... */ + + +} + +''' + + + +HELPER_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +#ifndef %(INCLUDE_GUARD)s +#define %(INCLUDE_GUARD)s + +#include "ns3/%(MODULE)s.h" + +namespace ns3 { + +/* ... */ + +} + +#endif /* %(INCLUDE_GUARD)s */ + +''' + + +EXAMPLES_WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_program('%(MODULE)s-example', [%(MODULE)r]) + obj.source = '%(MODULE)s-example.cc' + +''' + +EXAMPLE_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#include "ns3/core-module.h" +#include "ns3/%(MODULE)s-helper.h" + +using namespace ns3; + + +int +main (int argc, char *argv[]) +{ + bool verbose = true; + + CommandLine cmd; + cmd.AddValue ("verbose", "Tell application to log if true", verbose); + + cmd.Parse (argc,argv); + + /* ... */ + + Simulator::Run (); + Simulator::Destroy (); + return 0; +} + + +''' + + +def main(argv): + parser = OptionParser(usage=("Usage: %prog [options] modulename\n" + "Utility script to create a basic template for a new ns-3 module")) + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + return 1 + + modname = args[0] + assert os.path.sep not in modname + + moduledir = os.path.join(os.path.dirname(__file__), modname) + + if os.path.exists(moduledir): + print >> sys.stderr, "Module %r already exists" % (modname,) + return 2 + + os.mkdir(moduledir) + wscript = file(os.path.join(moduledir, "wscript"), "wt") + wscript.write(WSCRIPT_TEMPLATE % dict(MODULE=modname)) + wscript.close() + + + # + # model + # + modeldir = os.path.join(moduledir, "model") + os.mkdir(modeldir) + + model_cc = file(os.path.join(moduledir, "model", "%s.cc" % modname), "wt") + model_cc.write(MODEL_CC_TEMPLATE % dict(MODULE=modname)) + model_cc.close() + + model_h = file(os.path.join(moduledir, "model", "%s.h" % modname), "wt") + model_h.write(MODEL_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="__%s_H__" % (modname.upper()),)) + model_h.close() + + + + # + # helper + # + helperdir = os.path.join(moduledir, "helper") + os.mkdir(helperdir) + + helper_cc = file(os.path.join(moduledir, "helper", "%s-helper.cc" % modname), "wt") + helper_cc.write(HELPER_CC_TEMPLATE % dict(MODULE=modname)) + helper_cc.close() + + helper_h = file(os.path.join(moduledir, "helper", "%s-helper.h" % modname), "wt") + helper_h.write(HELPER_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="__%s_HELPER_H__" % (modname.upper()),)) + helper_h.close() + + + examplesdir = os.path.join(moduledir, "examples") + os.mkdir(examplesdir) + + examples_wscript = file(os.path.join(examplesdir, "wscript"), "wt") + examples_wscript.write(EXAMPLES_WSCRIPT_TEMPLATE % dict(MODULE=modname)) + examples_wscript.close() + + example_cc = file(os.path.join(moduledir, "examples", "%s-example.cc" % modname), "wt") + example_cc.write(EXAMPLE_CC_TEMPLATE % dict(MODULE=modname)) + example_cc.close() + + + return 0 + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/src/csma-layout/wscript b/src/csma-layout/wscript index 79f0062e9..c692d3511 100644 --- a/src/csma-layout/wscript +++ b/src/csma-layout/wscript @@ -5,7 +5,7 @@ def build(bld): obj.source = [ 'model/csma-star-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'csma-layout' headers.source = [ 'model/csma-star-helper.h', diff --git a/src/csma/wscript b/src/csma/wscript index c5d10af5a..3b6294c21 100644 --- a/src/csma/wscript +++ b/src/csma/wscript @@ -8,7 +8,7 @@ def build(bld): 'model/csma-channel.cc', 'helper/csma-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'csma' headers.source = [ 'model/backoff.h', diff --git a/src/dsdv/wscript b/src/dsdv/wscript index 36fc14574..9790a83cd 100644 --- a/src/dsdv/wscript +++ b/src/dsdv/wscript @@ -16,7 +16,7 @@ def build(bld): 'test/dsdv-testcase.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'dsdv' headers.source = [ 'model/dsdv-rtable.h', diff --git a/src/emu/examples/wscript b/src/emu/examples/wscript index 3a2f70452..56e917589 100644 --- a/src/emu/examples/wscript +++ b/src/emu/examples/wscript @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - env = bld.env_of_name('default') + env = bld.env if env['ENABLE_EMU']: obj = bld.create_ns3_program('emu-udp-echo', ['emu', 'internet', 'applications']) obj.source = 'emu-udp-echo.cc' diff --git a/src/emu/wscript b/src/emu/wscript index 97fa4cb9f..43c51106d 100644 --- a/src/emu/wscript +++ b/src/emu/wscript @@ -4,7 +4,7 @@ import os.path def configure(conf): if conf.env['ENABLE_THREADING']: - conf.env['ENABLE_EMU'] = conf.check(header_name='netpacket/packet.h', + conf.env['ENABLE_EMU'] = conf.check_nonfatal(header_name='netpacket/packet.h', define_name='HAVE_PACKET_H') conf.report_optional_feature("EmuNetDevice", "Emulated Net Device", conf.env['ENABLE_EMU'], @@ -15,7 +15,8 @@ def configure(conf): "needs threading support which is not available") if conf.env['ENABLE_EMU']: - blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) + #blddir = conf.bldnode.abspath() + blddir = os.path.abspath(os.path.join(conf.bldnode.abspath(), conf.variant)) emucreatordir = os.path.abspath(os.path.join(blddir, "src/emu")) conf.env.append_value('NS3_EXECUTABLE_PATH', emucreatordir) else: @@ -35,7 +36,7 @@ def build(bld): 'helper/emu-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'emu' headers.source = [ 'model/emu-net-device.h', diff --git a/src/energy/wscript b/src/energy/wscript index 6892a3183..db582dcc3 100644 --- a/src/energy/wscript +++ b/src/energy/wscript @@ -25,7 +25,7 @@ def build(bld): 'test/li-ion-energy-source-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'energy' headers.source = [ 'model/wifi-radio-energy-model.h', diff --git a/src/flow-monitor/wscript b/src/flow-monitor/wscript index 29586c948..13fcabded 100644 --- a/src/flow-monitor/wscript +++ b/src/flow-monitor/wscript @@ -17,7 +17,7 @@ def build(bld): 'test/histogram-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'flow-monitor' headers.source = ["model/%s" % s for s in [ 'flow-monitor.h', diff --git a/src/internet/wscript b/src/internet/wscript index 554b975fa..65aeaa70a 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -11,7 +11,7 @@ import Task NSC_RELEASE_NAME = "nsc-0.5.2" -def set_options(opt): +def options(opt): opt.add_option('--with-nsc', help=('Use Network Simulation Cradle, given by the indicated path,' ' to allow the use of real-world network stacks'), @@ -32,23 +32,23 @@ def configure(conf): # Check for the location of NSC if Options.options.with_nsc: if os.path.isdir(Options.options.with_nsc): - conf.check_message("NSC location", '', True, ("%s (given)" % Options.options.with_nsc)) + conf.msg("NSC location", ("%s (given)" % Options.options.with_nsc)) conf.env['WITH_NSC'] = os.path.abspath(Options.options.with_nsc) else: # ns-3-dev uses ../nsc, while ns-3 releases use ../NSC_RELEASE_NAME nsc_dir = os.path.join('..', "nsc") nsc_release_dir = os.path.join('..', NSC_RELEASE_NAME) if os.path.isdir(nsc_dir): - conf.check_message("NSC location", '', True, ("%s (guessed)" % nsc_dir)) + conf.msg("NSC location",("%s (guessed)" % nsc_dir)) conf.env['WITH_NSC'] = os.path.abspath(nsc_dir) elif os.path.isdir(nsc_release_dir): - conf.check_message("NSC location", '', True, ("%s (guessed)" % nsc_release_dir)) + conf.msg("NSC location", ("%s (guessed)" % nsc_release_dir)) conf.env['WITH_NSC'] = os.path.abspath(nsc_release_dir) del nsc_dir del nsc_release_dir if not conf.env['WITH_NSC']: - conf.check_message("NSC location", '', False) + conf.msg("NSC location", False) conf.report_optional_feature("nsc", "Network Simulation Cradle", False, "NSC not found (see option --with-nsc)") return @@ -61,9 +61,9 @@ def configure(conf): if arch in ('x86_64', 'i686', 'i586', 'i486', 'i386'): conf.env['NSC_ENABLED'] = True conf.env.append_value('CXXDEFINES', 'NETWORK_SIMULATION_CRADLE') - conf.check(mandatory=True, lib='dl', define_name='HAVE_DL', uselib='DL') + conf.check_nonfatal(mandatory=True, lib='dl', define_name='HAVE_DL', uselib='DL') ok = True - conf.check_message('NSC supported architecture', arch, ok) + conf.msg('NSC supported architecture ' + arch, ok) if not ok: conf.env['NSC_ENABLED'] = False @@ -205,7 +205,7 @@ def build(bld): 'test/udp-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'internet' headers.source = [ 'model/udp-header.h', diff --git a/src/lte/wscript b/src/lte/wscript index b1e8aba31..3608ff50b 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -47,7 +47,7 @@ def build(bld): 'test/lte-propagation-loss-model-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'lte' headers.source = [ 'model/lte-spectrum-phy.h', diff --git a/src/mesh/wscript b/src/mesh/wscript index 6ce45246c..79011c8e5 100644 --- a/src/mesh/wscript +++ b/src/mesh/wscript @@ -53,7 +53,7 @@ def build(bld): 'test/flame/regression.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'mesh' headers.source = [ 'model/mesh-information-element.h', diff --git a/src/mobility/wscript b/src/mobility/wscript index da6f3fbd1..3225b2028 100644 --- a/src/mobility/wscript +++ b/src/mobility/wscript @@ -30,7 +30,7 @@ def build(bld): 'test/waypoint-mobility-model-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'mobility' headers.source = [ 'model/box.h', diff --git a/src/mpi/wscript b/src/mpi/wscript index c70fa1375..52ed53312 100644 --- a/src/mpi/wscript +++ b/src/mpi/wscript @@ -2,11 +2,14 @@ import sys import subprocess import Options - +from waflib.Errors import WafError def configure(conf): env = conf.env - conf.find_program('mpic++', var='MPI') + try: + conf.find_program('mpic++', var='MPI') + except WafError: + return if Options.options.enable_mpi and conf.env['MPI']: p = subprocess.Popen([conf.env['MPI'], '-showme:compile'], stdout=subprocess.PIPE) flags = p.stdout.read().rstrip().split() @@ -29,7 +32,7 @@ def configure(conf): def build(bld): - env = bld.env_of_name('default') + env = bld.env sim = bld.create_ns3_module('mpi', ['core', 'network']) sim.source = [ 'model/distributed-simulator-impl.cc', @@ -37,7 +40,7 @@ def build(bld): 'model/mpi-receiver.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'mpi' headers.source = [ 'model/distributed-simulator-impl.h', diff --git a/src/netanim/wscript b/src/netanim/wscript index bc76fd484..9d5710173 100644 --- a/src/netanim/wscript +++ b/src/netanim/wscript @@ -8,7 +8,7 @@ def build (bld) : 'helper/animation-interface-helper.cc', ] - headers = bld.new_task_gen ('ns3header') + headers = bld.new_task_gen (features=['ns3header']) headers.module = 'netanim' headers.source = [ 'model/animation-interface.h', diff --git a/src/network/wscript b/src/network/wscript index 5d06dff81..d36cfe41e 100644 --- a/src/network/wscript +++ b/src/network/wscript @@ -67,7 +67,7 @@ def build(bld): 'test/sequence-number-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'network' headers.source = [ 'model/address.h', diff --git a/src/nix-vector-routing/wscript b/src/nix-vector-routing/wscript index e0332a872..660631a2f 100644 --- a/src/nix-vector-routing/wscript +++ b/src/nix-vector-routing/wscript @@ -8,7 +8,7 @@ def build(bld): 'helper/ipv4-nix-vector-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'nix-vector-routing' headers.source = [ 'model/ipv4-nix-vector-routing.h', diff --git a/src/olsr/wscript b/src/olsr/wscript index bbe0427c2..ed2c4811e 100644 --- a/src/olsr/wscript +++ b/src/olsr/wscript @@ -20,7 +20,7 @@ def build(bld): 'test/tc-regression-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'olsr' headers.source = [ 'model/olsr-routing-protocol.h', diff --git a/src/openflow/wscript b/src/openflow/wscript index 1c3c3939c..5038cacbd 100644 --- a/src/openflow/wscript +++ b/src/openflow/wscript @@ -2,27 +2,24 @@ import os import Options +from waflib.Errors import WafError -def set_options(opt): +def options(opt): opt.add_option('--with-openflow', help=('Path to OFSID source for NS-3 OpenFlow Integration support'), default='', dest='with_openflow') - opt.tool_options('boost') + opt.tool_options('boost', tooldir=["waf-tools"]) def configure(conf): - conf.check_tool('boost') - conf.env['BOOST'] = conf.check_boost(lib = 'signals filesystem', - kind = 'STATIC_BOTH', - score_version = (-1000, 1000), - tag_minscore = 1000) - if not conf.env['BOOST']: - conf.env['BOOST'] = conf.check_boost(lib = 'signals filesystem', - kind = 'STATIC_BOTH', - score_version = (-1000, 1000), - tag_minscore = 1000, - libpath="/usr/lib64") + try: + conf.check_tool('boost') + conf.check_boost(lib='signals filesystem') + if not conf.env.LIB_BOOST: + conf.check_boost(lib='signals filesystem', libpath="/usr/lib64") + except WafError: + conf.env['LIB_BOOST'] = [] - if not conf.env['BOOST']: + if not conf.env.LIB_BOOST: conf.report_optional_feature("openflow", "NS-3 OpenFlow Integration", False, "Required boost libraries not found") @@ -34,16 +31,16 @@ def configure(conf): if Options.options.with_openflow: if os.path.isdir(Options.options.with_openflow): - conf.check_message("OpenFlow location", '', True, ("%s (given)" % Options.options.with_openflow)) + conf.msg("Checking for OpenFlow location", ("%s (given)" % Options.options.with_openflow)) conf.env['WITH_OPENFLOW'] = os.path.abspath(Options.options.with_openflow) else: openflow_dir = os.path.join('..','openflow') if os.path.isdir(openflow_dir): - conf.check_message("OpenFlow location", '', True, ("%s (guessed)" % openflow_dir)) + conf.msg("Checking for OpenFlow location", ("%s (guessed)" % openflow_dir)) conf.env['WITH_OPENFLOW'] = os.path.abspath(openflow_dir) del openflow_dir if not conf.env['WITH_OPENFLOW']: - conf.check_message("OpenFlow location", '', False) + conf.msg("Checking for OpenFlow location", False) conf.report_optional_feature("openflow", "NS-3 OpenFlow Integration", False, "OpenFlow not enabled (see option --with-openflow)") # Add this module to the list of modules that won't be built @@ -104,23 +101,19 @@ int main() conf.env.append_value('NS3_MODULE_PATH',os.path.abspath(os.path.join(conf.env['WITH_OPENFLOW'],'build','default'))) - conf.env['CPPPATH_OPENFLOW'] = [ + conf.env['INCLUDES_OPENFLOW'] = [ os.path.abspath(os.path.join(conf.env['WITH_OPENFLOW'],'include'))] conf.env['LIBPATH_OPENFLOW'] = [ os.path.abspath(os.path.join(conf.env['WITH_OPENFLOW'],'build','default')), os.path.abspath(os.path.join(conf.env['WITH_OPENFLOW'],'lib'))] - conf.env['OPENFLOW'] = conf.check(fragment=test_code, lib='openflow', - libpath=conf.env['LIBPATH_OPENFLOW'], - uselib='OPENFLOW DL XML2') - + conf.env['OPENFLOW'] = conf.check_nonfatal(fragment=test_code, lib='openflow', + libpath=conf.env['LIBPATH_OPENFLOW'], + use='OPENFLOW DL XML2') conf.report_optional_feature("openflow", "NS-3 OpenFlow Integration", conf.env['OPENFLOW'], "openflow library not found") if conf.env['OPENFLOW']: conf.env['ENABLE_OPENFLOW'] = True - conf.env.append_value('CXXDEFINES', 'NS3_OPENFLOW') - conf.env.append_value('CPPPATH', conf.env['CPPPATH_OPENFLOW']) - conf.env.append_value('LIBPATH', conf.env['LIBPATH_OPENFLOW']) else: # Add this module to the list of modules that won't be built # if they are enabled. @@ -146,7 +139,7 @@ def build(bld): obj.uselib = 'OPENFLOW DL XML2' obj_test.uselib = 'OPENFLOW DL XML2' - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'openflow' headers.source = [ ] @@ -155,6 +148,10 @@ def build(bld): obj.source.append('model/openflow-interface.cc') obj.source.append('model/openflow-switch-net-device.cc') obj.source.append('helper/openflow-switch-helper.cc') + + obj.env.append_value('DEFINES', 'NS3_OPENFLOW') + obj.use = "OPENFLOW" + obj_test.source.append('test/openflow-switch-test-suite.cc') headers.source.append('model/openflow-interface.h') headers.source.append('model/openflow-switch-net-device.h') diff --git a/src/point-to-point-layout/wscript b/src/point-to-point-layout/wscript index 4ab18b42d..d29d04ec6 100644 --- a/src/point-to-point-layout/wscript +++ b/src/point-to-point-layout/wscript @@ -9,7 +9,7 @@ def build(bld): 'model/point-to-point-star.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'point-to-point-layout' headers.source = [ 'model/point-to-point-dumbbell.h', diff --git a/src/point-to-point/wscript b/src/point-to-point/wscript index ce8faa742..f3b4ba8e6 100644 --- a/src/point-to-point/wscript +++ b/src/point-to-point/wscript @@ -16,7 +16,7 @@ def build(bld): 'test/point-to-point-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'point-to-point' headers.source = [ 'model/point-to-point-net-device.h', diff --git a/src/propagation/wscript b/src/propagation/wscript index df7d068e4..094a7de82 100644 --- a/src/propagation/wscript +++ b/src/propagation/wscript @@ -15,7 +15,7 @@ def build(bld): 'test/propagation-loss-model-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'propagation' headers.source = [ 'model/propagation-delay-model.h', diff --git a/src/spectrum/wscript b/src/spectrum/wscript index 49e205fb7..0ba4d8f4d 100644 --- a/src/spectrum/wscript +++ b/src/spectrum/wscript @@ -39,7 +39,7 @@ def build(bld): 'test/spectrum-ideal-phy-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'spectrum' headers.source = [ 'model/spectrum-model.h', diff --git a/src/stats/wscript b/src/stats/wscript index a4d4c5085..13d632dba 100644 --- a/src/stats/wscript +++ b/src/stats/wscript @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def configure(conf): - conf.env['SQLITE_STATS'] = conf.check(lib='sqlite3', define_name='SQLITE3', uselib='SQLITE3') + conf.env['SQLITE_STATS'] = conf.check_nonfatal(lib='sqlite3', define_name='SQLITE3', uselib='SQLITE3') conf.report_optional_feature("SqliteDataOutput", "SQlite stats data output", conf.env['SQLITE_STATS'], "library 'sqlite3' not found") @@ -23,7 +23,7 @@ def build(bld): 'test/basic-data-calculators-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'stats' headers.source = [ 'model/data-calculator.h', diff --git a/src/tap-bridge/examples/wscript b/src/tap-bridge/examples/wscript index fa63e92c6..aeca10764 100644 --- a/src/tap-bridge/examples/wscript +++ b/src/tap-bridge/examples/wscript @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - env = bld.env_of_name('default') + env = bld.env if env['ENABLE_TAP']: obj = bld.create_ns3_program('tap-csma', ['csma', 'tap-bridge', 'internet', 'wifi']) obj.source = 'tap-csma.cc' diff --git a/src/tap-bridge/wscript b/src/tap-bridge/wscript index 4ee038ab5..ab1376b60 100644 --- a/src/tap-bridge/wscript +++ b/src/tap-bridge/wscript @@ -4,7 +4,7 @@ import os.path def configure(conf): if conf.env['ENABLE_THREADING']: - conf.env['ENABLE_TAP'] = conf.check(header_name='linux/if_tun.h', + conf.env['ENABLE_TAP'] = conf.check_nonfatal(header_name='linux/if_tun.h', define_name='HAVE_IF_TUN_H') conf.report_optional_feature("TapBridge", "Tap Bridge", conf.env['ENABLE_TAP'], @@ -15,7 +15,7 @@ def configure(conf): "needs threading support which is not available") if conf.env['ENABLE_TAP']: - blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) + blddir = os.path.abspath(os.path.join(conf.bldnode.abspath(), conf.variant)) tapcreatordir = os.path.abspath(os.path.join(blddir, "src/tap-bridge")) conf.env.append_value('NS3_EXECUTABLE_PATH', tapcreatordir) else: @@ -34,7 +34,7 @@ def build(bld): 'model/tap-encode-decode.cc', 'helper/tap-bridge-helper.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'tap-bridge' headers.source = [ 'model/tap-bridge.h', diff --git a/src/template/wscript b/src/template/wscript index 00c30d4f5..787bdb7dd 100644 --- a/src/template/wscript +++ b/src/template/wscript @@ -27,7 +27,7 @@ def build(bld): ] # Make headers be installed for this module. - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'template' # Set the C++ header files for this module. diff --git a/src/test/ns3tcp/wscript b/src/test/ns3tcp/wscript index 514353eab..5fe1f7488 100644 --- a/src/test/ns3tcp/wscript +++ b/src/test/ns3tcp/wscript @@ -16,7 +16,7 @@ def build(bld): return ns3tcp = bld.create_ns3_module('ns3tcp', ['internet', 'point-to-point', 'csma', 'applications']) - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'ns3tcp' headers.source = [ 'ns3tcp.h', diff --git a/src/test/ns3wifi/wscript b/src/test/ns3wifi/wscript index 13feb446c..68d431725 100644 --- a/src/test/ns3wifi/wscript +++ b/src/test/ns3wifi/wscript @@ -16,7 +16,7 @@ def build(bld): return ns3wifi = bld.create_ns3_module('ns3wifi', ['internet', 'mobility', 'propagation', 'wifi', 'applications']) - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'ns3wifi' headers.source = [ 'ns3wifi.h', diff --git a/src/test/wscript b/src/test/wscript index 56e15765d..ab4d0420f 100644 --- a/src/test/wscript +++ b/src/test/wscript @@ -20,7 +20,7 @@ def build(bld): return test = bld.create_ns3_module('test', ['internet', 'mobility', 'applications', 'csma', 'bridge', 'config-store', 'tools', 'point-to-point', 'csma-layout', 'flow-monitor']) - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'test' test_test = bld.create_ns3_module_test_library('test') diff --git a/src/tools/wscript b/src/tools/wscript index 31f096317..b036ee29e 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -14,7 +14,7 @@ def build(bld): 'test/event-garbage-collector-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'tools' headers.source = [ 'model/average.h', diff --git a/src/topology-read/wscript b/src/topology-read/wscript index d50441e1b..8e69e8651 100644 --- a/src/topology-read/wscript +++ b/src/topology-read/wscript @@ -15,7 +15,7 @@ def build(bld): 'test/rocketfuel-topology-reader-test-suite.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'topology-read' headers.source = [ 'model/topology-reader.h', diff --git a/src/uan/wscript b/src/uan/wscript index 2030ee156..2ae8f189c 100644 --- a/src/uan/wscript +++ b/src/uan/wscript @@ -32,7 +32,7 @@ def build(bld): 'test/uan-test.cc', 'test/uan-energy-model-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'uan' headers.source = [ 'model/uan-channel.h', diff --git a/src/virtual-net-device/wscript b/src/virtual-net-device/wscript index 2b462afc2..590e3a845 100644 --- a/src/virtual-net-device/wscript +++ b/src/virtual-net-device/wscript @@ -6,7 +6,7 @@ def build(bld): module.source = [ 'model/virtual-net-device.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'virtual-net-device' headers.source = [ 'model/virtual-net-device.h', diff --git a/src/visualizer/wscript b/src/visualizer/wscript index 9dea2216e..8857f458e 100644 --- a/src/visualizer/wscript +++ b/src/visualizer/wscript @@ -13,7 +13,7 @@ def build(bld): if 'visualizer' in bld.env['MODULES_NOT_BUILT']: return - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'visualizer' headers.source = [ ] @@ -36,8 +36,8 @@ def build(bld): return module.features.append('pyembed') - module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS']) - module.includes = '.' + #module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS']) + #module.includes = '.' module.source.extend([ 'model/pyviz.cc', diff --git a/src/wifi/wscript b/src/wifi/wscript index 0784c8ee2..39a2f2c3a 100644 --- a/src/wifi/wscript +++ b/src/wifi/wscript @@ -75,7 +75,7 @@ def build(bld): 'test/wifi-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'wifi' headers.source = [ 'model/wifi-information-element.h', diff --git a/src/wimax/wscript b/src/wimax/wscript index 5f96e2a35..9a586fd05 100644 --- a/src/wimax/wscript +++ b/src/wimax/wscript @@ -63,7 +63,7 @@ def build(bld): 'test/wimax-fragmentation-test.cc', ] - headers = bld.new_task_gen('ns3header') + headers = bld.new_task_gen(features=['ns3header']) headers.module = 'wimax' headers.source = [ 'model/wimax-channel.h', diff --git a/src/wscript b/src/wscript index 8a81ba89e..a5c08d052 100644 --- a/src/wscript +++ b/src/wscript @@ -6,15 +6,13 @@ import shutil import types import warnings +from waflib.Errors import WafError + import TaskGen import Task import Options import Build import Utils -import Constants - -import ccroot -ccroot.USE_TOP_LEVEL = True import wutils @@ -23,53 +21,21 @@ try: except NameError: from sets import Set as set # Python 2.3 fallback -all_modules = [ - 'core', - 'network', - 'config-store', - 'internet', - 'propagation', - 'point-to-point', - 'csma', - 'emu', - 'bridge', - 'tap-bridge', - 'virtual-net-device', - 'applications', - 'nix-vector-routing', - 'olsr', - 'aodv', - 'dsdv', - 'click', - 'openflow', - 'mobility', - 'wifi', - 'netanim', - 'stats', - 'uan', - 'spectrum', - 'mesh', - 'test', - 'test/ns3tcp', - 'test/ns3wifi', - 'flow-monitor', - 'wimax', - 'lte', - 'mpi', - 'topology-read', - 'energy', - 'tools', - 'visualizer', - 'point-to-point-layout', - 'csma-layout', - 'template', - ] -def set_options(opt): - opt.sub_options('core') - opt.sub_options('click') - opt.sub_options('openflow') +all_modules = [] +for dirname in os.listdir('src'): + if dirname.startswith('.') or dir == 'CVS': + continue + path = os.path.join('src', dirname) + if not os.path.isdir(path): + continue + if os.path.exists(os.path.join(path, 'wscript')): + all_modules.append(dirname) +all_modules.sort() + + +def options(opt): opt.add_option('--enable-rpath', help=("Link programs with rpath" " (normally not needed, see " @@ -81,20 +47,15 @@ def set_options(opt): help=("Build only these modules (and dependencies)"), dest='enable_modules') -def configure(conf): - conf.sub_config('core') - conf.sub_config('emu') - conf.sub_config('tap-bridge') - conf.sub_config('config-store') - conf.sub_config('internet') - conf.sub_config('netanim') - conf.sub_config('test') - conf.sub_config('click') - conf.sub_config('openflow') - conf.sub_config('stats') - conf.sub_config('visualizer') + for module in all_modules: + opt.sub_options(module, mandatory=False) - blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant())) + +def configure(conf): + for module in all_modules: + conf.sub_config(module, mandatory=False) + + blddir = os.path.abspath(os.path.join(conf.bldnode.abspath(), conf.variant)) conf.env.append_value('NS3_MODULE_PATH', blddir) if Options.options.enable_rpath: conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),)) @@ -103,177 +64,91 @@ def configure(conf): conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules] -class ns3module_taskgen(TaskGen.task_gen): - def __init__(self, *args, **kwargs): - super(ns3module_taskgen, self).__init__(*args, **kwargs) - self.libs = [] - def apply(self): - static_enabled = False - shared_enabled = True - bld = self.bld - if bld.env['ENABLE_STATIC_NS3']: - static_enabled = True - shared_enabled = False - if bld.env['ENABLE_SHARED_AND_STATIC_NS3']: - static_enabled = True - shared_enabled = True - - assert self.name.startswith("ns3-") - name = self.name.split("ns3-")[1] - - if static_enabled: - static = self._create_ns3_module(self.bld, name, self.dependencies, True) - self.libs.append(static) - else: - static = None - - if shared_enabled: - shared = self._create_ns3_module(self.bld, name, self.dependencies, False) - self.libs.append(shared) - else: - shared = None - - if static is not None and shared is None: - static.name = self.name + "--lib" - static.uselib_local = ['ns3-%s--lib' % (dep,) for dep in self.dependencies] - - elif shared is not None and static is None: - shared.name = self.name + "--lib" - shared.uselib_local = ['ns3-%s--lib' % (dep,) for dep in self.dependencies] - else: - shared.name = self.name + "--lib" - shared.uselib_local = ['ns3-%s--lib' % (dep,) for dep in self.dependencies] - static.name = self.name + "--static" - static.uselib_local = ['ns3-%s--static' % (dep,) for dep in self.dependencies] - - if not self.test: - pcfile = bld.new_task_gen('ns3pcfile') - pcfile.module = self - - def _create_ns3_module(self, bld, name, dependencies, static): - - # FIXME: env modifications are overwritten by parent caller - - # Create a separate library for this module. - if static: - module = bld.new_task_gen('cxx', 'cstaticlib') - else: - module = bld.new_task_gen('cxx', 'cshlib') - - module.source = self.source - module.env = self.env.copy() - features = list(self.features) - features.remove("ns3module") - module.features.extend(features) - module.path = self.path - module.uselib = self.uselib - module.target = 'ns3-' + name - if hasattr(self, 'includes'): - module.includes = self.includes - if hasattr(self, 'defines'): - module.defines = self.defines - else: - module.defines = [] - if hasattr(self, 'add_objects'): - module.add_objects = self.add_objects - else: - module.add_objects = [] - if hasattr(self, "is_ns3_module"): - module.is_ns3_module = self.is_ns3_module - if hasattr(self, 'add_objects'): - module.add_objects = self.add_objects - - linkflags = [] - cxxflags = [] - ccflags = [] - if not static: - cxxflags = module.env['shlib_CXXFLAGS'] - ccflags = module.env['shlib_CXXFLAGS'] - # Turn on the link flags for shared libraries if we have the - # proper compiler and platform. - if module.env['CXX_NAME'] in ['gcc', 'icc'] and module.env['WL_SONAME_SUPPORTED']: - # Get the module library name without any relative paths - # at its beginning because all of the libraries will end - # up in the same directory. - module_library_name = os.path.basename(ccroot.get_target_name(module)) - linkflags = '-Wl,--soname=%s' % module_library_name - elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \ - os.uname()[4] == 'x86_64' and \ - sys.platform != 'darwin' and \ - module.env['ENABLE_PYTHON_BINDINGS']: - # enable that flag for static builds only on x86-64 platforms - # when gcc is present and only when we want python bindings - # (it's more efficient to not use this option if we can avoid it) - cxxflags = ['-mcmodel=large'] - ccflags = ['-mcmodel=large'] - cxxdefines = ["NS3_MODULE_COMPILATION"] - ccdefines = ["NS3_MODULE_COMPILATION"] - - module.env.append_value('CXXFLAGS', cxxflags) - module.env.append_value('CCFLAGS', ccflags) - module.env.append_value('LINKFLAGS', linkflags) - module.env.append_value('CXXDEFINES', cxxdefines) - module.env.append_value('CCDEFINES', ccdefines) - - if len(module.source) > 0 and hasattr(self, 'ns3_dir_location'): - uselib_cpppath = [] - for lib in module.uselib.split(): - if 'CPPPATH_%s' % lib in module.env: - uselib_cpppath.extend(module.env['CPPPATH_%s' % lib]) - objects = [] - for src in module.source[0:-1]: - full_src = os.path.join(self.ns3_dir_location, src) - path = os.path.dirname(full_src) - target = '%s_object' % src - # XXX: calculate the features correctly here. - obj = bld (source=[full_src], target=target, features='cxx cc', - defines=['NS_TEST_SOURCEDIR="%s"' % path], - includes=' '.join(uselib_cpppath), - env = module.env) - objects.append(target) - last = module.source[-1] - full_src = os.path.join(self.ns3_dir_location, last) - path = os.path.dirname(full_src) - module.defines.append('NS_TEST_SOURCEDIR="%s"' % path) - module.source = [last] - module.add_objects.extend(objects) - - - module.is_static = static - module.vnum = wutils.VNUM - # Add the proper path to the module's name. - module.target = '%s/ns3-%s' % (bld.srcnode.relpath_gen(self.path), name) - # Set the libraries this module depends on. - module.module_deps = list(dependencies) - - module.install_path = "${LIBDIR}" - - return module +# we need the 'ns3module' waf "feature" to be created because code +# elsewhere looks for it to find the ns3 module objects. +@TaskGen.feature('ns3module') +def _add_test_code(module): + pass def create_ns3_module(bld, name, dependencies=(), test=False): - module = bld.new_task_gen('ns3module') - module.bld = bld + static = bool(bld.env.ENABLE_STATIC_NS3) + # Create a separate library for this module. + if static: + module = bld.new_task_gen(features=['cxx', 'cxxstlib', 'ns3module']) + else: + module = bld.new_task_gen(features=['cxx', 'cxxshlib', 'ns3module']) + module.target = '%s/ns3-%s' % (bld.srcnode.relpath_gen(module.path), name) + linkflags = [] + cxxflags = [] + ccflags = [] + if not static: + cxxflags = module.env['shlib_CXXFLAGS'] + ccflags = module.env['shlib_CXXFLAGS'] + # Turn on the link flags for shared libraries if we have the + # proper compiler and platform. + if module.env['CXX_NAME'] in ['gcc', 'icc'] and module.env['WL_SONAME_SUPPORTED']: + # Get the module library name without any relative paths + # at its beginning because all of the libraries will end + # up in the same directory. + module_library_name = module.env.cshlib_PATTERN % (os.path.basename(module.target),) + linkflags = '-Wl,--soname=' + module_library_name + elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \ + os.uname()[4] == 'x86_64' and \ + sys.platform != 'darwin' and \ + module.env['ENABLE_PYTHON_BINDINGS']: + # enable that flag for static builds only on x86-64 platforms + # when gcc is present and only when we want python bindings + # (it's more efficient to not use this option if we can avoid it) + cxxflags = ['-mcmodel=large'] + ccflags = ['-mcmodel=large'] + cxxdefines = ["NS3_MODULE_COMPILATION"] + ccdefines = ["NS3_MODULE_COMPILATION"] + + module.env.append_value('CXXFLAGS', cxxflags) + module.env.append_value('CCFLAGS', ccflags) + module.env.append_value('LINKFLAGS', linkflags) + module.env.append_value('CXXDEFINES', cxxdefines) + module.env.append_value('CCDEFINES', ccdefines) + + module.is_static = static + module.vnum = wutils.VNUM + # Add the proper path to the module's name. + # Set the libraries this module depends on. + module.module_deps = list(dependencies) + + module.install_path = "${LIBDIR}" + module.name = "ns3-" + name module.dependencies = dependencies # Initially create an empty value for this because the pcfile # writing task assumes every module has a uselib attribute. module.uselib = '' - module.uselib_local = ['ns3-' + dep for dep in dependencies] - module.module_deps = list(dependencies) + module.use = ['ns3-' + dep for dep in dependencies] module.test = test module.is_ns3_module = True module.ns3_dir_location = bld.path.relpath_gen(bld.srcnode) + module.env.append_value("INCLUDES", '#') + return module +@TaskGen.feature("ns3testlib") +@TaskGen.before_method("apply_incpaths") +def apply_incpaths_ns3testlib(self): + if not self.source: + return + testdir = self.source[-1].parent.relpath_gen(self.bld.srcnode) + self.env.append_value("DEFINES", 'NS_TEST_SOURCEDIR="%s"' % (testdir,)) + def create_ns3_module_test_library(bld, name): # Create an ns3 module for the test library that depends only on # the module being tested. library_name = name + "-test" - library = bld.create_ns3_module(library_name, [name], test = True) + library = bld.create_ns3_module(library_name, [name], test=True) + library.features.append("ns3testlib") # Modify attributes for the test library that are different from a # normal module. @@ -282,7 +157,7 @@ def create_ns3_module_test_library(bld, name): library.module_name = 'ns3-' + name # Add this module and test library to the list. - bld.env.append_value('NS3_MODULES_WITH_TEST_LIBRARIES', (library.module_name, library.name)) + bld.env.append_value('NS3_MODULES_WITH_TEST_LIBRARIES', [(library.module_name, library.name)]) # Set the include path from the build directory to modules. relative_path_from_build_to_here = bld.path.relpath_gen(bld.bldnode) @@ -299,6 +174,9 @@ def create_obj(bld, *args): def ns3_python_bindings(bld): + if Options.options.apiscan: + return + # this method is called from a module wscript, so remember bld.path is not bindings/python! module_abs_src_path = bld.path.abspath() module = os.path.basename(module_abs_src_path) @@ -367,40 +245,40 @@ def ns3_python_bindings(bld): if was_enabled: features.append(name) - bindgen = bld.new_task_gen('command', source=source, target=target, command=argv) + bindgen = bld.new_task_gen(features=['command'], source=source, target=target, command=argv) bindgen.env['FEATURES'] = ','.join(features) bindgen.dep_vars = ['FEATURES', "GCC_RTTI_ABI_COMPLETE"] bindgen.before = 'cxx' - bindgen.after = 'gen_ns3_module_header_task' + bindgen.after = 'gen_ns3_module_header' bindgen.name = "pybindgen(ns3 module %s)" % module # generate the extension module - pymod = bld.new_task_gen(features='cxx cshlib pyext') + pymod = bld.new_task_gen(features='cxx cxxshlib pyext') pymod.source = ['bindings/ns3module.cc'] pymod.target = '%s/%s' % (module_target_dir, extension_name) pymod.name = 'ns3module_%s' % module - pymod.uselib_local = ["%s--lib" % mod for mod in pymod.env['NS3_ENABLED_MODULES']] # Should be '"ns3-"+module', but see bug 1117 + pymod.use = ["%s" % mod for mod in pymod.env['NS3_ENABLED_MODULES']] # Should be '"ns3-"+module', but see bug 1117 if pymod.env['ENABLE_STATIC_NS3']: if sys.platform == 'darwin': pymod.env.append_value('LINKFLAGS', '-Wl,-all_load') - for mod in pymod.uselib_local: - mod = mod.split("--lib")[0] + for mod in pymod.usel: + #mod = mod.split("--lib")[0] pymod.env.append_value('LINKFLAGS', '-l' + mod) else: pymod.env.append_value('LINKFLAGS', '-Wl,--whole-archive,-Bstatic') - for mod in pymod.uselib_local: - mod = mod.split("--lib")[0] + for mod in pymod.use: + #mod = mod.split("--lib")[0] pymod.env.append_value('LINKFLAGS', '-l' + mod) pymod.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archive') - defines = list(pymod.env['CXXDEFINES']) + defines = list(pymod.env['DEFINES']) defines.extend(['NS_DEPRECATED=', 'NS3_DEPRECATED_H']) if Options.platform == 'win32': try: defines.remove('_DEBUG') # causes undefined symbols on win32 except ValueError: pass - pymod.env['CXXDEFINES'] = defines - pymod.includes = 'bindings' + pymod.env['DEFINES'] = defines + pymod.includes = '# bindings' pymod.install_path = '${PYTHONDIR}/ns' return pymod @@ -427,7 +305,7 @@ def build(bld): bld.add_subdirs(list(all_modules)) for module in all_modules: - modheader = bld.new_task_gen('ns3moduleheader') + modheader = bld.new_task_gen(features=['ns3moduleheader']) modheader.module = module.split('/')[-1] class ns3pcfile_task(Task.Task): @@ -480,7 +358,7 @@ class ns3pcfile_task(Task.Task): includes = self.env['CPPPATH_%s' % dep] return [self.env['CPPPATH_ST'] % include for include in includes] - def _generate_pcfile(self, name, use, uselib_local, env, outfilename): + def _generate_pcfile(self, name, uselib, use, env, outfilename): outfile = open(outfilename, 'w') prefix = env.PREFIX includedir = env.INCLUDEDIR @@ -488,7 +366,7 @@ class ns3pcfile_task(Task.Task): libs = self._self_libs(self.env, name, '${libdir}') for dep in use: libs = libs + self._lib(self.env, dep) - for dep in uselib_local: + for dep in uselib: libs = libs + [self.env['LIB_ST'] % dep] cflags = [self.env['CPPPATH_ST'] % '${includedir}'] for dep in use: @@ -511,7 +389,7 @@ Cflags: %s def run(self): output_filename = self.outputs[0].bldpath(self.env) self._generate_pcfile(self.module.name, self.module.uselib, - self.module.uselib_local, + self.module.use, self.env, output_filename) class ns3pcfile_taskgen(TaskGen.task_gen): @@ -527,41 +405,33 @@ class ns3pcfile_taskgen(TaskGen.task_gen): task.module = self.module -class ns3header_taskgen(TaskGen.task_gen): - """A set of NS-3 header files""" - COLOR = 'BLUE' - def __init__(self, *args, **kwargs): - super(ns3header_taskgen, self).__init__(*args, **kwargs) - self.install_path = None - self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h - self.module = None # module name - self.mode = 'install' - def apply(self): - for filename in set(self.to_list(self.source)): - src_node = self.path.find_resource(filename) - if self.module is None: - raise Utils.WafError("'module' missing on ns3headers object %s" % self) - ns3_dir_node = self.bld.path.find_dir("ns3") - if self.sub_dir is not None: - ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir) - for filename in set(self.to_list(self.source)): - src_node = self.path.find_resource(filename) - if src_node is None: - raise Utils.WafError("source ns3 header file %s not found" % (filename,)) - dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename)) - assert dst_node is not None - task = self.create_task('ns3header', env=self.env) - task.mode = self.mode - if self.mode == 'install': - self.bld.install_files('${PREFIX}/include/ns3', [src_node]) - task.set_inputs([src_node]) - task.set_outputs([dst_node]) - else: - task.header_to_remove = dst_node +@TaskGen.feature('ns3header') +@TaskGen.after_method('process_rule') +def apply_ns3header(self): + if self.module is None: + raise WafError("'module' missing on ns3headers object %s" % self) + ns3_dir_node = self.bld.path.find_dir("ns3") + for filename in set(self.to_list(self.source)): + src_node = self.path.find_resource(filename) + if src_node is None: + raise WafError("source ns3 header file %s not found" % (filename,)) + dst_node = ns3_dir_node.find_or_declare(src_node.name) + assert dst_node is not None + task = self.create_task('ns3header') + task.mode = getattr(self, 'mode', 'install') + if task.mode == 'install': + self.bld.install_files('${PREFIX}/include/ns3', [src_node]) + task.set_inputs([src_node]) + task.set_outputs([dst_node]) + else: + task.header_to_remove = dst_node + self.headers = set(self.to_list(self.source)) + self.source = '' # tell WAF not to process these files further + class ns3header_task(Task.Task): - before = 'cc cxx gen_ns3_module_header_task' + before = 'cc cxx gen_ns3_module_header' color = 'BLUE' def __str__(self): @@ -572,23 +442,41 @@ class ns3header_task(Task.Task): if self.outputs: sep = ' -> ' else: sep = '' if self.mode == 'remove': - return 'rm-ns3-header %s\n' % (self.header_to_remove.bldpath(self.env),) + return 'rm-ns3-header %s\n' % (self.header_to_remove.abspath(),) return 'install-ns3-header: %s%s%s\n' % (src_str, sep, tgt_str) + def __repr__(self): + return str(self) + + def uid(self): + try: + return self.uid_ + except AttributeError: + m = Utils.md5() + up = m.update + up(self.__class__.__name__.encode()) + for x in self.inputs + self.outputs: + up(x.abspath().encode()) + up(self.mode) + if self.mode == 'remove': + up(self.header_to_remove.abspath().encode()) + self.uid_ = m.digest() + return self.uid_ + def runnable_status(self): if self.mode == 'remove': - if os.path.exists(self.header_to_remove.bldpath(self.env)): - return Constants.RUN_ME + if os.path.exists(self.header_to_remove.abspath()): + return Task.RUN_ME else: - return Constants.SKIP_ME + return Task.SKIP_ME else: return super(ns3header_task, self).runnable_status() def run(self): if self.mode == 'install': assert len(self.inputs) == len(self.outputs) - inputs = [node.srcpath(self.env) for node in self.inputs] - outputs = [node.bldpath(self.env) for node in self.outputs] + inputs = [node.abspath() for node in self.inputs] + outputs = [node.abspath() for node in self.outputs] for src, dst in zip(inputs, outputs): try: os.chmod(dst, 0600) @@ -602,7 +490,7 @@ class ns3header_task(Task.Task): else: assert len(self.inputs) == 0 assert len(self.outputs) == 0 - out_file_name = self.header_to_remove.bldpath(self.env) + out_file_name = self.header_to_remove.abspath() try: os.unlink(out_file_name) except OSError, ex: @@ -613,15 +501,15 @@ class ns3header_task(Task.Task): class gen_ns3_module_header_task(Task.Task): before = 'cc cxx' - after = 'ns3header_task' + after = 'ns3header' color = 'BLUE' def runnable_status(self): if self.mode == 'remove': - if os.path.exists(self.header_to_remove.bldpath(self.env)): - return Constants.RUN_ME + if os.path.exists(self.header_to_remove.abspath()): + return Task.RUN_ME else: - return Constants.SKIP_ME + return Task.SKIP_ME else: return super(gen_ns3_module_header_task, self).runnable_status() @@ -633,24 +521,23 @@ class gen_ns3_module_header_task(Task.Task): if self.outputs: sep = ' -> ' else: sep = '' if self.mode == 'remove': - return 'rm-module-header %s\n' % (self.header_to_remove.bldpath(self.env),) + return 'rm-module-header %s\n' % (self.header_to_remove.abspath(),) return 'gen-module-header: %s%s%s\n' % (src_str, sep, tgt_str) def run(self): if self.mode == 'remove': assert len(self.inputs) == 0 assert len(self.outputs) == 0 - out_file_name = self.header_to_remove.bldpath(self.env) + out_file_name = self.header_to_remove.abspath() try: os.unlink(out_file_name) except OSError, ex: if ex.errno != 2: raise return 0 - assert len(self.outputs) == 1 - out_file_name = self.outputs[0].bldpath(self.env) - header_files = [os.path.basename(node.abspath(self.env)) for node in self.inputs] + out_file_name = self.outputs[0].get_bld().abspath()#self.env) + header_files = [os.path.basename(node.abspath()) for node in self.inputs] outfile = file(out_file_name, "w") header_files.sort() @@ -678,7 +565,7 @@ class gen_ns3_module_header_task(Task.Task): return 0 def sig_explicit_deps(self): - self.m.update('\n'.join([node.abspath(self.env) for node in self.inputs])) + self.m.update('\n'.join([node.abspath() for node in self.inputs])) return self.m.digest() def unique_id(self): @@ -692,50 +579,46 @@ class gen_ns3_module_header_task(Task.Task): return self.uid -class ns3moduleheader_taskgen(TaskGen.task_gen): - """ - Generates a 'ns3/foo-module.h' header file that includes all - public ns3 headers of a certain module. - """ - COLOR = 'BLUE' - def __init__(self, *args, **kwargs): - super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs) - self.mode = 'install' +# Generates a 'ns3/foo-module.h' header file that includes all public +# ns3 headers of a certain module. +@TaskGen.feature('ns3moduleheader') +@TaskGen.after_method('process_rule') +def apply_ns3moduleheader(self): + ## get all of the ns3 headers + ns3_dir_node = self.bld.path.find_dir("ns3") + all_headers_inputs = [] + found_the_module = False + for ns3headers in self.bld.all_task_gen: + if 'ns3header' in getattr(ns3headers, "features", []): + if ns3headers.module != self.module: + continue + found_the_module = True + for source in ns3headers.headers: + source = os.path.basename(source) + node = ns3_dir_node.find_or_declare(os.path.basename(source)) + if node is None: + fatal("missing header file %s" % (source,)) + all_headers_inputs.append(node) + if not found_the_module: + raise WafError("error finding headers for module %s" % self.module) + if not all_headers_inputs: + return - def apply(self): - ## get all of the ns3 headers - ns3_dir_node = self.bld.path.find_dir("ns3") - all_headers_inputs = [] - found_the_module = False - for ns3headers in self.bld.all_task_gen: - if isinstance(ns3headers, ns3header_taskgen): - if ns3headers.module != self.module: - continue - found_the_module = True - for source in set(ns3headers.to_list(ns3headers.source)): - source = os.path.basename(source) - node = ns3_dir_node.find_or_declare(os.path.basename(source)) - if node is None: - fatal("missing header file %s" % (source,)) - all_headers_inputs.append(node) - if not found_the_module: - raise Utils.WscriptError("error finding headers for module %s" % self.module) - if not all_headers_inputs: - return - all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)] - task = self.create_task('gen_ns3_module_header', env=self.env) - task.module = self.module - task.mode = self.mode - if self.mode == 'install': - self.bld.install_files('${PREFIX}/include/ns3', - ns3_dir_node.find_or_declare("%s-module.h" % self.module)) - task.set_inputs(all_headers_inputs) - task.set_outputs(all_headers_outputs) - module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env) - assert module_obj is not None, self.module - task.module_deps = module_obj.module_deps - else: - task.header_to_remove = all_headers_outputs[0] + try: + module_obj = self.bld.get_tgen_by_name("ns3-" + self.module) + except WafError: # maybe the module was disabled, and therefore removed + return - def install(self): - pass + all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)] + task = self.create_task('gen_ns3_module_header') + task.module = self.module + task.mode = getattr(self, "mode", "install") + if task.mode == 'install': + assert module_obj is not None, self.module + self.bld.install_files('${PREFIX}/include/ns3', + ns3_dir_node.find_or_declare("%s-module.h" % self.module)) + task.set_inputs(all_headers_inputs) + task.set_outputs(all_headers_outputs) + task.module_deps = module_obj.module_deps + else: + task.header_to_remove = all_headers_outputs[0] diff --git a/test.py b/test.py index f4c2433ca..7fee5e8fb 100755 --- a/test.py +++ b/test.py @@ -42,7 +42,6 @@ from utils import get_list_from_file # found in the associated subdirectory wscript files. # interesting_config_items = [ - "NS3_BUILDDIR", "NS3_ENABLED_MODULES", "NS3_MODULE_PATH", "NSC_ENABLED", @@ -483,24 +482,6 @@ def sigint_hook(signal, frame): thread_exit = True return 0 -# -# Waf can be configured to compile in debug or optimized modes. In each -# case, the resulting built goes into a different directory. If we want -# test tests to run from the correct code-base, we have to figure out which -# mode waf is running in. This is called its active variant. -# -# XXX This function pokes around in the waf internal state file. To be a -# little less hacky, we should add a commmand to waf to return this info -# and use that result. -# -def read_waf_active_variant(): - for line in open("build/c4che/default.cache.py").readlines(): - if line.startswith("NS3_ACTIVE_VARIANT"): - exec(line, globals()) - break - - if options.verbose: - print "NS3_ACTIVE_VARIANT == %s" % NS3_ACTIVE_VARIANT # # In general, the build process itself naturally takes care of figuring out @@ -519,7 +500,13 @@ def read_waf_active_variant(): # and use that result. # def read_waf_config(): - for line in open("build/c4che/%s.cache.py" % NS3_ACTIVE_VARIANT).readlines(): + for line in open(".lock-wafbuild", "rt"): + if line.startswith("out_dir ="): + key, val = line.split('=') + out_dir = eval(val.strip()) + global NS3_BUILDDIR + NS3_BUILDDIR = out_dir + for line in open("%s/c4che/_cache.py" % out_dir).readlines(): for item in interesting_config_items: if line.startswith(item): exec(line, globals()) @@ -555,7 +542,7 @@ def make_paths(): if key == "PYTHONPATH": have_PYTHONPATH = True - pypath = os.environ["PYTHONPATH"] = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, "bindings", "python") + pypath = os.environ["PYTHONPATH"] = os.path.join (NS3_BUILDDIR, "bindings", "python") if not have_PYTHONPATH: os.environ["PYTHONPATH"] = pypath @@ -684,7 +671,7 @@ def run_job_synchronously(shell_command, directory, valgrind, is_python, build_p if len(build_path): path_cmd = os.path.join (build_path, shell_command) else: - path_cmd = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command) + path_cmd = os.path.join (NS3_BUILDDIR, shell_command) if valgrind: cmd = "valgrind --suppressions=%s --leak-check=full --show-reachable=yes --error-exitcode=2 %s" % (suppressions_path, @@ -991,12 +978,11 @@ def run_tests(): # pieces of the system have been built. This will tell us what examples # are runnable. # - read_waf_active_variant() read_waf_config() make_paths() # Get the information from the build status file. - build_status_file = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, 'build-status.py') + build_status_file = os.path.join (NS3_BUILDDIR, 'build-status.py') if os.path.exists(build_status_file): ns3_runnable_programs = get_list_from_file(build_status_file, "ns3_runnable_programs") ns3_runnable_scripts = get_list_from_file(build_status_file, "ns3_runnable_scripts") @@ -1013,7 +999,7 @@ def run_tests(): # Set the directories and paths for this example. example_directory = os.path.join("examples", directory) examples_to_run_path = os.path.join(example_directory, "examples-to-run.py") - cpp_executable_dir = os.path.join(NS3_BUILDDIR, NS3_ACTIVE_VARIANT, example_directory) + cpp_executable_dir = os.path.join(NS3_BUILDDIR, example_directory) python_script_dir = os.path.join(example_directory) # Parse this example directory's file. @@ -1032,7 +1018,7 @@ def run_tests(): module_directory = os.path.join("src", module) example_directory = os.path.join(module_directory, "examples") examples_to_run_path = os.path.join(module_directory, "test", "examples-to-run.py") - cpp_executable_dir = os.path.join(NS3_BUILDDIR, NS3_ACTIVE_VARIANT, example_directory) + cpp_executable_dir = os.path.join(NS3_BUILDDIR, example_directory) python_script_dir = os.path.join(example_directory) # Parse this module's file. diff --git a/utils/wscript b/utils/wscript index fb49a7712..a1addf860 100644 --- a/utils/wscript +++ b/utils/wscript @@ -10,7 +10,7 @@ def build(bld): # Set the libraries the testrunner depends on equal to the list of # enabled modules plus the list of enabled module test libraries. - test_runner.uselib_local = [mod+"--lib" for mod in (env['NS3_ENABLED_MODULES'] + env['NS3_ENABLED_MODULE_TEST_LIBRARIES'])] + test_runner.use = [mod for mod in (env['NS3_ENABLED_MODULES'] + env['NS3_ENABLED_MODULE_TEST_LIBRARIES'])] obj = bld.create_ns3_program('bench-simulator', ['core']) obj.source = 'bench-simulator.cc' @@ -28,5 +28,5 @@ def build(bld): obj = bld.create_ns3_program('print-introspected-doxygen', ['network']) obj.source = 'print-introspected-doxygen.cc' - obj.uselib_local = [mod+"--lib" for mod in env['NS3_ENABLED_MODULES']] + obj.use = [mod for mod in env['NS3_ENABLED_MODULES']] diff --git a/waf b/waf index 22d00ed29..f7c97d6a8 100755 Binary files a/waf and b/waf differ diff --git a/waf-tools/boost.py b/waf-tools/boost.py new file mode 100644 index 000000000..ea25d803f --- /dev/null +++ b/waf-tools/boost.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python +# encoding: utf-8 +# +# partially based on boost.py written by Gernot Vormayr +# written by Ruediger Sonderfeld , 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 + +''' +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 + +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', mt=True, static=True) + +def build(bld): + bld(source='main.cpp', target='app', use='BOOST') +''' + +import sys +import re +from waflib import Utils, Logs +from waflib.Configure import conf + +BOOST_LIBS = ('/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 +#include +int main() { std::cout << BOOST_LIB_VERSION << std::endl; } +''' + +# 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 directory where the includes are + e.g. /boost_1_45_0/include''') + opt.add_option('--boost-libs', type='string', + default='', dest='boost_libs', + help='''path to the directory where the boost libs are + e.g. /boost_1_45_0/stage/lib''') + opt.add_option('--boost-static', action='store_true', + default=False, dest='boost_static', + help='link static libraries') + 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 (dgsyp, d for debug), + see doc Boost, Getting Started, chapter 6.1''') + 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, dir): + try: + return self.root.find_dir(dir).find_node(BOOST_VERSION_FILE) + except: + return None + + +@conf +def boost_get_version(self, dir): + """silently retrieve the boost version number""" + re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"$', re.M) + try: + val = re_but.search(self.__boost_get_version_file(dir).read()).group(1) + except: + val = self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[dir], + execute=True, define_ret=True) + return val + + +@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 dir in BOOST_INCLUDES: + if self.__boost_get_version_file(dir): + return dir + if includes: + self.fatal('headers not found in %s' % includes) + else: + self.fatal('headers not found, use --boost-includes=/path/to/boost') + + +@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 dir in BOOST_LIBS: + try: + path = self.root.find_dir(dir) + files = path.ant_glob('*boost_*') + if files: + break + path = self.root.find_dir(dir + '64') + files = path.ant_glob('*boost_*') + if files: + break + except: + path = None + if not path: + if libs: + self.fatal('libs not found in %s' % libs) + else: + self.fatal('libs not found, \ + use --boost-includes=/path/to/boost/lib') + 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) + t = [] + if kw.get('mt', False): + t.append('mt') + if kw.get('abi', None): + t.append(kw['abi']) + tags = t and '(-%s)+' % '-'.join(t) or '' + toolset = '(-%s[0-9]{0,3})+' % self.boost_get_toolset(kw.get('toolset', '')) + version = '(-%s)+' % self.env.BOOST_VERSION + + def find_lib(re_lib, files): + for file in files: + if re_lib.search(file.name): + return file + return None + + def format_lib_name(name): + if name.startswith('lib'): + name = name[3:] + return name.split('.')[0] + + libs = [] + for lib in Utils.to_list(k and k[0] or kw.get('lib', None)): + py = (lib == 'python') and '(-py%s)+' % kw['python'] or '' + # Trying libraries, from most strict match to least one + for pattern in ['boost_%s%s%s%s%s' % (lib, toolset, tags, py, version), + 'boost_%s%s%s%s' % (lib, tags, py, version), + 'boost_%s%s%s' % (lib, tags, version), + # Give up trying to find the right version + 'boost_%s%s%s%s' % (lib, toolset, tags, py), + 'boost_%s%s%s' % (lib, tags, py), + 'boost_%s%s' % (lib, tags)]: + file = find_lib(re.compile(pattern), files) + if file: + libs.append(format_lib_name(file.name)) + break + else: + self.fatal('lib %s not found in %s' % (lib, path)) + + return path.abspath(), libs + + +@conf +def check_boost(self, *k, **kw): + """ + initialize boost + + You can pass the same parameters as the command line (without "--boost-"), + but the command line has the priority. + """ + 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)} + 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] = self.boost_get_includes(**params) + self.env.BOOST_VERSION = self.boost_get_version(self.env['INCLUDES_%s' % var]) + self.end_msg(self.env.BOOST_VERSION) + if Logs.verbose: + Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var]) + + if not params['lib']: + return + self.start_msg('Checking boost libs') + suffix = params.get('static', 'ST') or '' + path, libs = self.boost_get_libs(**params) + self.env['%sLIBPATH_%s' % (suffix, var)] = [path] + self.env['%sLIB_%s' % (suffix, var)] = libs + self.end_msg('ok') + if Logs.verbose: + Logs.pprint('CYAN', ' path : %s' % path) + Logs.pprint('CYAN', ' libs : %s' % libs) + diff --git a/waf-tools/cflags.py b/waf-tools/cflags.py index 1738c88f9..cf9c93c46 100644 --- a/waf-tools/cflags.py +++ b/waf-tools/cflags.py @@ -144,7 +144,7 @@ profiles = { default_profile = 'default' -def set_options(opt): +def options(opt): assert default_profile in profiles opt.add_option('-d', '--build-profile', action='store', @@ -157,7 +157,7 @@ def set_options(opt): choices=profiles.keys(), dest='build_profile') -def detect(conf): +def configure(conf): cc = conf.env['COMPILER_CC'] or None cxx = conf.env['COMPILER_CXX'] or None if not (cc or cxx): diff --git a/waf-tools/command.py b/waf-tools/command.py index 5034acf3c..9066e0abb 100644 --- a/waf-tools/command.py +++ b/waf-tools/command.py @@ -1,9 +1,10 @@ -from TaskGen import feature, taskgen, before, task_gen -import Node, Task, Utils, Build, pproc, Constants +import TaskGen# import feature, taskgen_method, before_method, task_gen +import Node, Task, Utils, Build +import subprocess import Options import shellcmd -shellcmd.subprocess = pproc # the WAF version of the subprocess module is supposedly less buggy +#shellcmd.subprocess = pproc # the WAF version of the subprocess module is supposedly less buggy from Logs import debug, error shellcmd.debug = debug @@ -18,7 +19,7 @@ arg_rx = re.compile(r"(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\} class command_task(Task.Task): color = "BLUE" def __init__(self, env, generator): - Task.Task.__init__(self, env, normal=1, generator=generator) + Task.Task.__init__(self, env=env, normal=1, generator=generator) def __str__(self): "string to display to the user" @@ -33,7 +34,6 @@ class command_task(Task.Task): 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): @@ -50,21 +50,24 @@ class command_task(Task.Task): result = eval(var+code, namespace) if isinstance(result, Node.Node): if var == 'TGT': - return result.bldpath(self.env) + return result.get_bld().abspath() elif var == 'SRC': - return result.srcpath(self.env) + 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(self.env) + 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].bldpath(self.env) + 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 @@ -95,40 +98,37 @@ class command_task(Task.Task): 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 -@feature('command') +@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) + # other variables that can be used in the command: ${VARIABLE} + variables = None, + rule='') -@taskgen -@feature('command') -@before('apply_core') +@TaskGen.feature('command') +@TaskGen.after_method('process_rule') def apply_command(self): - self.meths.remove('apply_core') + #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 src in self.to_list(self.source): - node = self.path.find_resource(src) - if node is None: - raise Utils.WafError("source %s not found" % src) - inputs.append(node) + 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') +# class command_taskgen(task_gen): +# def __init__(self, *k, **kw): +# task_gen.__init__(self, *k, **kw) +# self.features.append('command') diff --git a/waf-tools/misc.py b/waf-tools/misc.py new file mode 100644 index 000000000..e8620fb14 --- /dev/null +++ b/waf-tools/misc.py @@ -0,0 +1,416 @@ +#!/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 (OSError, IOError): + 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 + else: + assert isinstance(cwd, CmdDirArg) + self.cwd.find_node(self.path) + + 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) + diff --git a/waf-tools/pkgconfig.py b/waf-tools/pkgconfig.py index 95d7cf587..e01012ba6 100644 --- a/waf-tools/pkgconfig.py +++ b/waf-tools/pkgconfig.py @@ -3,10 +3,11 @@ import Options import Configure -import pproc as subprocess +import subprocess import config_c +import sys -def detect(conf): +def configure(conf): pkg_config = conf.find_program('pkg-config', var='PKG_CONFIG') if not pkg_config: return @@ -19,25 +20,31 @@ def pkg_check_modules(conf, uselib_name, expression, mandatory=True): else: return False + if Options.options.verbose: + extra_msg = ' (%s)' % expression + else: + extra_msg = '' + + conf.start_msg('pkg-config flags for %s%s' % (uselib_name, extra_msg)) + argv = [pkg_config, '--cflags', '--libs', expression] - cmd = subprocess.Popen(argv, stdout=subprocess.PIPE) - out, dummy = cmd.communicate() + cmd = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = cmd.communicate() retval = cmd.wait() - msg_checking = ("pkg-config flags for %s" % (uselib_name,)) - if Options.options.verbose: - if retval == 0: - conf.check_message_custom(msg_checking, - ('(%s)' % expression), out) - else: - conf.check_message(msg_checking, ('(%s)' % expression), False) + conf.to_log('%r: %r (exit code %i)\n%s' % (argv, out, retval, err)) + + if retval != 0: + conf.end_msg(False) + sys.stderr.write(err) else: - conf.check_message(msg_checking, '', (retval == 0), '') - conf.log.write('%r: %r (exit code %i)\n' % (argv, out, retval)) + if Options.options.verbose: + conf.end_msg(out) + else: + conf.end_msg(True) if retval == 0: - - config_c.parse_flags(out, uselib_name, conf.env) + conf.parse_flags(out, uselib_name, conf.env) conf.env[uselib_name] = True return True diff --git a/wscript b/wscript index 8c319ef08..e94d3eba8 100644 --- a/wscript +++ b/wscript @@ -11,24 +11,21 @@ import shlex import textwrap # WAF modules -import pproc as subprocess +import subprocess import Options import Logs import TaskGen -import Constants - -import ccroot -ccroot.USE_TOP_LEVEL = True import Task -Task.algotype = Constants.JOBCONTROL # so that Task.maxjobs=1 takes effect import Utils import Build import Configure import Scripting +from waflib.Errors import WafError + from utils import read_config_file # By default, all modules will be enabled, examples will be disabled, @@ -58,7 +55,7 @@ cflags.default_profile = 'debug' # local modules import wutils -Configure.autoconfig = 1 +Configure.autoconfig = 0 # the following two variables are used by the target "waf dist" VERSION = file("VERSION", "rt").read().strip() @@ -73,8 +70,8 @@ if sys.platform != 'darwin' and re.match(r"^\d+\.\d+(\.\d+)?$", VERSION) is not wutils.VNUM = VERSION # these variables are mandatory ('/' are converted automatically) -srcdir = '.' -blddir = 'build' +top = '.' +out = 'build' def load_env(): bld_cls = getattr(Utils.g_module, 'build_context', Utils.Context) @@ -124,12 +121,12 @@ def print_module_names(names): if i != 1: print -def set_options(opt): +def options(opt): # options provided by the modules - opt.tool_options('compiler_cc') - opt.tool_options('compiler_cxx') - opt.tool_options('cflags') - opt.tool_options('gnu_dirs') + opt.load('compiler_c') + opt.load('compiler_cxx') + opt.load('cflags') + opt.load('gnu_dirs') opt.add_option('--cwd', help=('Set the working directory for a program.'), @@ -208,10 +205,6 @@ def set_options(opt): help=('Compile NS-3 statically: works only on linux, without python'), dest='enable_static', action='store_true', default=False) - opt.add_option('--enable-shared-and-static', - help=('Compile NS-3 both shared and static libraries at the same time: static works only on linux'), - dest='enable_shared_and_static', action='store_true', - default=False) opt.add_option('--enable-mpi', help=('Compile NS-3 with MPI and distributed simulation support'), dest='enable_mpi', action='store_true', @@ -234,6 +227,7 @@ def _check_compilation_flag(conf, flag, mode='cxx'): flag: can be a string or a list of strings """ + conf.start_msg('Checking for compilation flag %r support' % (flag,)) env = conf.env.copy() if mode == 'cxx': fname = 'test.cc' @@ -244,26 +238,36 @@ def _check_compilation_flag(conf, flag, mode='cxx'): try: retval = conf.run_c_code(code='#include \nint main() { return 0; }\n', env=env, compile_filename=fname, - compile_mode=mode, type='cprogram', execute=False) + compile_mode=mode, features='c cprogram', execute=False) except Configure.ConfigurationError: ok = False else: ok = (retval == 0) - conf.check_message_custom(flag, 'support', (ok and 'yes' or 'no')) + conf.end_msg(ok) return ok def report_optional_feature(conf, name, caption, was_enabled, reason_not_enabled): - conf.env.append_value('NS3_OPTIONAL_FEATURES', (name, caption, was_enabled, reason_not_enabled)) + conf.env.append_value('NS3_OPTIONAL_FEATURES', [(name, caption, was_enabled, reason_not_enabled)]) + + +# starting with waf 1.6, conf.check() becomes fatal by default if the +# test fails, this alternative method makes the test non-fatal, as it +# was in waf <= 1.5 +def _check_nonfatal(conf, *args, **kwargs): + try: + return conf.check(*args, **kwargs) + except conf.errors.ConfigurationError: + return None def configure(conf): # attach some extra methods + conf.check_nonfatal = types.MethodType(_check_nonfatal, conf) conf.check_compilation_flag = types.MethodType(_check_compilation_flag, conf) conf.report_optional_feature = types.MethodType(report_optional_feature, conf) conf.env['NS3_OPTIONAL_FEATURES'] = [] - conf.env['NS3_BUILDDIR'] = conf.blddir - conf.check_tool('compiler_cc') + conf.check_tool('compiler_c') conf.check_tool('compiler_cxx') conf.check_tool('cflags', ['waf-tools']) try: @@ -273,31 +277,19 @@ def configure(conf): conf.check_tool('command', ['waf-tools']) conf.check_tool('gnu_dirs') - #if os.path.exists('/usr/lib64'): - # conf.env.LIBDIR = os.path.join(conf.env.PREFIX, "lib64") - - # create the second environment, set the variant and set its name - variant_env = conf.env.copy() - variant_name = Options.options.build_profile + env = conf.env if Options.options.enable_gcov: - variant_name += '-gcov' - variant_env.append_value('CCFLAGS', '-fprofile-arcs') - variant_env.append_value('CCFLAGS', '-ftest-coverage') - variant_env.append_value('CXXFLAGS', '-fprofile-arcs') - variant_env.append_value('CXXFLAGS', '-ftest-coverage') - variant_env.append_value('LINKFLAGS', '-fprofile-arcs') - - conf.env['NS3_ACTIVE_VARIANT'] = variant_name - variant_env['NS3_ACTIVE_VARIANT'] = variant_name - variant_env.set_variant(variant_name) - conf.set_env_name(variant_name, variant_env) - conf.setenv(variant_name) - env = variant_env + env['GCOV_ENABLED'] = True + env.append_value('CCFLAGS', '-fprofile-arcs') + env.append_value('CCFLAGS', '-ftest-coverage') + env.append_value('CXXFLAGS', '-fprofile-arcs') + env.append_value('CXXFLAGS', '-ftest-coverage') + env.append_value('LINKFLAGS', '-fprofile-arcs') if Options.options.build_profile == 'debug': - env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE') - env.append_value('CXXDEFINES', 'NS3_LOG_ENABLE') + env.append_value('DEFINES', 'NS3_ASSERT_ENABLE') + env.append_value('DEFINES', 'NS3_LOG_ENABLE') env['PLATFORM'] = sys.platform @@ -325,15 +317,13 @@ def configure(conf): env['WL_SONAME_SUPPORTED'] = True env['ENABLE_STATIC_NS3'] = False - if Options.options.enable_static or Options.options.enable_shared_and_static: + if Options.options.enable_static: if env['PLATFORM'].startswith('linux') and \ env['CXX_NAME'] in ['gcc', 'icc']: if re.match('i[3-6]86', os.uname()[4]): conf.report_optional_feature("static", "Static build", True, '') if Options.options.enable_static: env['ENABLE_STATIC_NS3'] = True - if Options.options.enable_shared_and_static: - env['ENABLE_SHARED_AND_STATIC_NS3'] = True elif os.uname()[4] == 'x86_64': if env['ENABLE_PYTHON_BINDINGS'] and \ not conf.check_compilation_flag('-mcmodel=large'): @@ -346,16 +336,12 @@ def configure(conf): conf.report_optional_feature("static", "Static build", True, '') if Options.options.enable_static: env['ENABLE_STATIC_NS3'] = True - if Options.options.enable_shared_and_static: - env['ENABLE_SHARED_AND_STATIC_NS3'] = True elif env['CXX_NAME'] == 'gcc' and \ (env['PLATFORM'].startswith('darwin') or \ env['PLATFORM'].startswith('cygwin')): conf.report_optional_feature("static", "Static build", True, '') if Options.options.enable_static: env['ENABLE_STATIC_NS3'] = True - if Options.options.enable_shared_and_static: - env['ENABLE_SHARED_AND_STATIC_NS3'] = True else: conf.report_optional_feature("static", "Static build", False, "Unsupported platform") @@ -395,7 +381,7 @@ def configure(conf): if not_built_name in conf.env['NS3_ENABLED_MODULES']: conf.env['NS3_ENABLED_MODULES'].remove(not_built_name) if not conf.env['NS3_ENABLED_MODULES']: - raise Utils.WafError('Exiting because the ' + not_built + ' module can not be built and it was the only one enabled.') + raise WafError('Exiting because the ' + not_built + ' module can not be built and it was the only one enabled.') conf.sub_config('bindings/python') @@ -483,12 +469,10 @@ def configure(conf): conf.env['ENABLE_GSL'], "GSL not found") if have_gsl: - conf.env.append_value('CXXDEFINES', "ENABLE_GSL") - conf.env.append_value('CCDEFINES', "ENABLE_GSL") + conf.env.append_value('DEFINES', "ENABLE_GSL") # for compiling C code, copy over the CXX* flags conf.env.append_value('CCFLAGS', conf.env['CXXFLAGS']) - conf.env.append_value('CCDEFINES', conf.env['CXXDEFINES']) def add_gcc_flag(flag): if env['COMPILER_CXX'] == 'g++' and 'CXXFLAGS' not in os.environ: @@ -502,7 +486,10 @@ def configure(conf): add_gcc_flag('-fstrict-aliasing') add_gcc_flag('-Wstrict-aliasing') - conf.find_program('doxygen', var='DOXYGEN') + try: + conf.find_program('doxygen', var='DOXYGEN') + except WafError: + pass # append user defined flags after all our ones for (confvar, envvar) in [['CCFLAGS', 'CCFLAGS_EXTRA'], @@ -522,23 +509,20 @@ def configure(conf): status = 'not enabled (%s)' % reason_not_enabled print "%-30s: %s" % (caption, status) -class SuidBuildTask(Task.TaskBase): + +class SuidBuild_task(Task.TaskBase): """task that makes a binary Suid """ - after = 'cxx_link cc_link' - maxjobs = 1 - def __init__(self, bld, program): - self.bld = bld + after = 'link' + def __init__(self, *args, **kwargs): + super(SuidBuild_task, self).__init__(*args, **kwargs) self.m_display = 'build-suid' - self.__program = program - self.__env = bld.env.copy () - super(SuidBuildTask, self).__init__(generator=self) try: - program_obj = wutils.find_program(self.__program.target, self.__env) + program_obj = wutils.find_program(self.generator.target, self.generator.env) except ValueError, ex: - raise Utils.WafError(str(ex)) - program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)) - self.filename = program_node.abspath(self.__env) + raise WafError(str(ex)) + program_node = program_obj.path.find_or_declare(program_obj.target) + self.filename = program_node.abspath() def run(self): @@ -553,38 +537,49 @@ class SuidBuildTask(Task.TaskBase): "RUN_ME SKIP_ME or ASK_LATER" st = os.stat(self.filename) if st.st_uid == 0: - return Constants.SKIP_ME + return Task.SKIP_ME else: - return Constants.RUN_ME - + return Task.RUN_ME def create_suid_program(bld, name): - program = bld.new_task_gen('cxx', 'program') + grp = bld.current_group + bld.add_group() # this to make sure no two sudo tasks run at the same time + program = bld.new_task_gen(features=['cxx', 'cxxprogram']) program.is_ns3_program = True program.module_deps = list() program.name = name program.target = name if bld.env['ENABLE_SUDO']: - SuidBuildTask(bld, program) + program.create_task("SuidBuild") + + bld.set_group(grp) return program def create_ns3_program(bld, name, dependencies=('core',)): - program = bld.new_task_gen('cxx', 'program') + program = bld.new_task_gen(features=['cxx', 'cxxprogram']) program.is_ns3_program = True program.name = name program.target = program.name # Each of the modules this program depends on has its own library. program.ns3_module_dependencies = ['ns3-'+dep for dep in dependencies] + program.includes = "# #/.." + program.use = program.ns3_module_dependencies + if program.env['ENABLE_STATIC_NS3']: + if sys.platform == 'darwin': + program.env.STLIB_MARKER = '-Wl,-all_load' + else: + program.env.STLIB_MARKER = '-Wl,--whole-archive,-Bstatic' + program.env.SHLIB_MARKER = '-Wl,-Bdynamic,--no-whole-archive' return program def register_ns3_script(bld, name, dependencies=('core',)): ns3_module_dependencies = ['ns3-'+dep for dep in dependencies] - bld.env.append_value('NS3_SCRIPT_DEPENDENCIES', (name, ns3_module_dependencies)) + bld.env.append_value('NS3_SCRIPT_DEPENDENCIES', [(name, ns3_module_dependencies)]) def add_examples_programs(bld): - env = bld.env_of_name('default') + env = bld.env if env['ENABLE_EXAMPLES']: for dir in os.listdir('examples'): if dir.startswith('.') or dir == 'CVS': @@ -613,23 +608,30 @@ def add_scratch_programs(bld): obj.name = obj.target -def _add_ns3_program_missing_deps(bld, program): - deps_found = program.ns3_module_dependencies - program.uselib_local = getattr(program, "uselib_local", []) + [dep + "--lib" for dep in deps_found] - if program.env['ENABLE_STATIC_NS3'] and not program.env['ENABLE_SHARED_AND_STATIC_NS3']: - if sys.platform == 'darwin': - program.env.append_value('LINKFLAGS', '-Wl,-all_load') - for dep in deps_found: - program.env.append_value('LINKFLAGS', '-l' + dep) - else: - program.env.append_value('LINKFLAGS', '-Wl,--whole-archive,-Bstatic') - for dep in deps_found: - program.env.append_value('LINKFLAGS', '-l' + dep) - program.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archive') +def _get_all_task_gen(self): + for group in self.groups: + for taskgen in group: + yield taskgen +# ok, so WAF does not provide an API to prevent an +# arbitrary taskgen from running; we have to muck around with +# WAF internal state, something that might stop working if +# WAF is upgraded... +def _exclude_taskgen(self, taskgen): + for group in self.groups: + for tg1 in group: + if tg1 is taskgen: + group.remove(tg1) + break + else: + continue + break + def build(bld): + env = bld.env + # If --enabled-modules option was given, then print a warning # message and exit this function. if Options.options.enable_modules: @@ -653,17 +655,12 @@ def build(bld): bld.create_ns3_program = types.MethodType(create_ns3_program, bld) bld.register_ns3_script = types.MethodType(register_ns3_script, bld) bld.create_suid_program = types.MethodType(create_suid_program, bld) - - # switch default variant to the one matching our debug level - variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT'] - variant_env = bld.env_of_name(variant_name) - bld.all_envs['default'] = variant_env + bld.__class__.all_task_gen = property(_get_all_task_gen) + bld.exclude_taskgen = types.MethodType(_exclude_taskgen, bld) # process subfolders from here bld.add_subdirs('src') - env = bld.env - # If modules have been enabled, then set lists of enabled modules # and enabled module test libraries. if env['NS3_ENABLED_MODULES']: @@ -675,11 +672,11 @@ def build(bld): while changed: changed = False for module in modules: - module_obj = bld.name_to_obj(module, env) + module_obj = bld.get_tgen_by_name(module) if module_obj is None: raise ValueError("module %s not found" % module) # Each enabled module has its own library. - for dep in module_obj.uselib_local: + for dep in module_obj.use: if not dep.startswith('ns3-'): continue if dep not in modules: @@ -701,25 +698,11 @@ def build(bld): if env['NS3_ENABLED_MODULES']: modules = env['NS3_ENABLED_MODULES'] - def exclude_taskgen(bld, taskgen): - # ok, so WAF does not provide an API to prevent an - # arbitrary taskgen from running; we have to muck around with - # WAF internal state, something that might stop working if - # WAF is upgraded... - bld.all_task_gen.remove(taskgen) - for group in bld.task_manager.groups: - try: - group.tasks_gen.remove(taskgen) - except ValueError: - pass - else: - break - # Exclude the programs other misc task gens that depend on disabled modules for obj in list(bld.all_task_gen): # check for ns3moduleheader_taskgen - if type(obj).__name__ == 'ns3moduleheader_taskgen': + if 'ns3moduleheader' in getattr(obj, "features", []): if ("ns3-%s" % obj.module) not in modules: obj.mode = 'remove' # tell it to remove headers instead of installing @@ -729,7 +712,7 @@ def build(bld): program_built = True for dep in obj.ns3_module_dependencies: if dep not in modules: # prog. depends on a module that isn't enabled? - exclude_taskgen(bld, obj) + bld.exclude_taskgen(obj) program_built = False break @@ -740,15 +723,15 @@ def build(bld): # disable the modules themselves if hasattr(obj, "is_ns3_module") and obj.name not in modules: - exclude_taskgen(bld, obj) # kill the module + bld.exclude_taskgen(obj) # kill the module # disable the module test libraries if hasattr(obj, "is_ns3_module_test_library"): if not env['ENABLE_TESTS'] or (obj.module_name not in modules): - exclude_taskgen(bld, obj) # kill the module test library + bld.exclude_taskgen(obj) # kill the module test library # disable the ns3header_taskgen - if type(obj).__name__ == 'ns3header_taskgen': + if 'ns3header' in getattr(obj, "features", []): if ("ns3-%s" % obj.module) not in modules: obj.mode = 'remove' # tell it to remove headers instead of installing @@ -770,35 +753,10 @@ def build(bld): bld.add_subdirs('bindings/python') - ## do a topological sort on the modules graph - dep_graph = [] - for gen in bld.all_task_gen: - if type(gen).__name__ in ['ns3module_taskgen']: - for dep in gen.dependencies: - dep_graph.append(("ns3-"+dep, gen.name)) - dep_graph.sort() - sys.path.insert(0, "bindings/python") - from topsort import topsort - sorted_ns3_modules = topsort(dep_graph) - #print sorted_ns3_modules - - # we need to post() the ns3 modules, so they create libraries underneath, and programs can list them in uselib_local - for module in sorted_ns3_modules: - gen = bld.name_to_obj(module, bld.env) - if type(gen).__name__ in ['ns3module_taskgen']: - gen.post() - for lib in gen.libs: - lib.post() - # Process this subfolder here after the lists of enabled modules # and module test libraries have been set. bld.add_subdirs('utils') - for gen in bld.all_task_gen: - if not getattr(gen, "is_ns3_program", False) or not hasattr(gen, "ns3_module_dependencies"): - continue - _add_ns3_program_missing_deps(bld, gen) - if Options.options.run: # Check that the requested program name is valid program_name, dummy_program_argv = wutils.get_run_program(Options.options.run, wutils.get_command_template(env)) @@ -806,7 +764,7 @@ def build(bld): # When --run'ing a program, tell WAF to only build that program, # nothing more; this greatly speeds up compilation when all you # want to do is run a test program. - Options.options.compile_targets += ',' + os.path.basename(program_name) + Options.options.targets += ',' + os.path.basename(program_name) for gen in bld.all_task_gen: if type(gen).__name__ in ['ns3header_taskgen', 'ns3moduleheader_taskgen']: gen.post() @@ -815,6 +773,8 @@ def build(bld): _doxygen(bld) raise SystemExit(0) + + def shutdown(ctx): bld = wutils.bld if wutils.bld is None: @@ -826,9 +786,9 @@ def shutdown(ctx): # clean. if ((not Options.options.run) and (not Options.options.pyrun) - and ('clean' not in Options.arg_line) - and ('distclean' not in Options.arg_line) - and ('shell' not in Options.arg_line)): + and ('clean' not in Options.commands) + and ('distclean' not in Options.commands) + and ('shell' not in Options.commands)): # Print the list of built modules. print @@ -844,7 +804,7 @@ def shutdown(ctx): print # Write the build status file. - build_status_file = os.path.join (env['NS3_BUILDDIR'], env['NS3_ACTIVE_VARIANT'], 'build-status.py') + build_status_file = os.path.join(bld.out_dir, 'build-status.py') out = open(build_status_file, 'w') out.write('#! /usr/bin/env python\n') out.write('\n') @@ -857,7 +817,7 @@ def shutdown(ctx): out.close() if Options.options.lcov_report: - lcov_report() + lcov_report(bld) if Options.options.run: wutils.run_program(Options.options.run, env, wutils.get_command_template(env), @@ -870,22 +830,23 @@ def shutdown(ctx): raise SystemExit(0) if Options.options.shell: - raise Utils.WafError("Please run `./waf shell' now, instead of `./waf --shell'") + raise WafError("Please run `./waf shell' now, instead of `./waf --shell'") if Options.options.check: - raise Utils.WafError("Please run `./test.py' now, instead of `./waf --check'") + raise WafError("Please run `./test.py' now, instead of `./waf --check'") check_shell(bld) -check_context = Build.BuildContext +check_context = Build.BuildContext def check(bld): """run the equivalent of the old ns-3 unit tests using test.py""" env = wutils.bld.env wutils.run_python_program("test.py -n -c core", env) + class print_introspected_doxygen_task(Task.TaskBase): - after = 'cc cxx cc_link cxx_link' + after = 'cc cxx link' color = 'BLUE' def __init__(self, bld): @@ -916,7 +877,7 @@ class print_introspected_doxygen_task(Task.TaskBase): out.close() class run_python_unit_tests_task(Task.TaskBase): - after = 'cc cxx cc_link cxx_link' + after = 'cc cxx link' color = 'BLUE' def __init__(self, bld): @@ -952,24 +913,34 @@ def check_shell(bld): "You should correct this situation before running any program. Possible solutions:\n" " 1. Exit this shell, and start a new one\n" " 2. Run a new nested shell") - raise Utils.WafError(msg) + raise WafError(msg) -shell_context = Build.BuildContext -def shell(ctx): +from waflib import Context, Build +class Ns3ShellContext(Context.Context): """run a shell with an environment suitably modified to run locally built programs""" + cmd = 'shell' - #make sure we build first" - Scripting.build(ctx) + def execute(self): - if sys.platform == 'win32': - shell = os.environ.get("COMSPEC", "cmd.exe") - else: - shell = os.environ.get("SHELL", "/bin/sh") + # first we execute the build + bld = Context.create_context("build") + bld.options = Options.options # provided for convenience + bld.cmd = "build" + bld.execute() + + if sys.platform == 'win32': + shell = os.environ.get("COMSPEC", "cmd.exe") + else: + shell = os.environ.get("SHELL", "/bin/sh") + + env = bld.env + os_env = { + 'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH']), + 'NS3_EXECUTABLE_PATH': os.pathsep.join(env['NS3_EXECUTABLE_PATH']), + } + wutils.run_argv([shell], env, os_env) - env = wutils.bld.env - os_env = {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH']), 'NS3_EXECUTABLE_PATH': os.pathsep.join(env['NS3_EXECUTABLE_PATH'])} - wutils.run_argv([shell], env, os_env) def _doxygen(bld): env = wutils.bld.env @@ -1010,28 +981,26 @@ def doxygen(bld): Scripting.build(bld) _doxygen(bld) -def lcov_report(): - env = Build.bld.env - variant_name = env['NS3_ACTIVE_VARIANT'] +def lcov_report(bld): + env = bld.env - if 'gcov' not in variant_name: - raise Utils.WafError("project not configured for code coverage;" - " reconfigure with --enable-gcov") + if not env['GCOV_ENABLED']: + raise WafError("project not configured for code coverage;" + " reconfigure with --enable-gcov") - os.chdir(blddir) + os.chdir(out) try: - lcov_report_dir = os.path.join(variant_name, 'lcov-report') + lcov_report_dir = 'lcov-report' create_dir_command = "rm -rf " + lcov_report_dir create_dir_command += " && mkdir " + lcov_report_dir + ";" if subprocess.Popen(create_dir_command, shell=True).wait(): raise SystemExit(1) - info_file = os.path.join(lcov_report_dir, variant_name + '.info') + info_file = os.path.join(lcov_report_dir, 'report.info') lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file lcov_command += " --source-dirs=" + os.getcwd() - lcov_command += ":" + os.path.join( - os.getcwd(), variant_name, 'include') + lcov_command += ":" + os.path.join(os.getcwd(), 'include') if subprocess.Popen(lcov_command, shell=True).wait(): raise SystemExit(1) @@ -1042,116 +1011,3 @@ def lcov_report(): finally: os.chdir("..") -## -## The default WAF DistDir implementation is rather slow, because it -## first copies everything and only later removes unwanted files and -## directories; this means that it needless copies the full build dir -## and the .hg repository tree. Here we provide a replacement DistDir -## implementation that is more efficient. -## -import Scripting -from Scripting import dist_exts, excludes, BLDDIR -import Utils -import os - -def _copytree(src, dst, symlinks=False, excludes=(), build_dir=None): - """Recursively copy a directory tree using copy2(). - - The destination directory must not already exist. - If exception(s) occur, an Error is raised with a list of reasons. - - If the optional symlinks flag is true, symbolic links in the - source tree result in symbolic links in the destination tree; if - it is false, the contents of the files pointed to by symbolic - links are copied. - - XXX Consider this example code rather than the ultimate tool. - - Note: this is a modified version of shutil.copytree from python - 2.5.2 library; modified for WAF purposes to exclude dot dirs and - another list of files. - """ - names = os.listdir(src) - os.makedirs(dst) - errors = [] - for name in names: - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if symlinks and os.path.islink(srcname): - linkto = os.readlink(srcname) - os.symlink(linkto, dstname) - elif os.path.isdir(srcname): - if name in excludes: - continue - elif name.startswith('.') or name.startswith(',,') or name.startswith('++') or name.startswith('CVS'): - continue - elif name == build_dir: - continue - else: - ## build_dir is not passed into the recursive - ## copytree, but that is intentional; it is a - ## directory name valid only at the top level. - copytree(srcname, dstname, symlinks, excludes) - else: - ends = name.endswith - to_remove = False - if name.startswith('.') or name.startswith('++'): - to_remove = True - else: - for x in dist_exts: - if ends(x): - to_remove = True - break - if not to_remove: - shutil.copy2(srcname, dstname) - # XXX What about devices, sockets etc.? - except (IOError, os.error), why: - errors.append((srcname, dstname, str(why))) - # catch the Error from the recursive copytree so that we can - # continue with other files - except shutil.Error, err: - errors.extend(err.args[0]) - try: - shutil.copystat(src, dst) - except WindowsError: - # can't copy file access times on Windows - pass - except OSError, why: - errors.extend((src, dst, str(why))) - if errors: - raise shutil.Error, errors - - -def DistDir(appname, version): - #"make a distribution directory with all the sources in it" - import shutil - - # Our temporary folder where to put our files - TMPFOLDER=appname+'-'+version - - # Remove an old package directory - if os.path.exists(TMPFOLDER): shutil.rmtree(TMPFOLDER) - - global g_dist_exts, g_excludes - - # Remove the Build dir - build_dir = getattr(Utils.g_module, BLDDIR, None) - - # Copy everything into the new folder - _copytree('.', TMPFOLDER, excludes=excludes, build_dir=build_dir) - - # TODO undocumented hook - dist_hook = getattr(Utils.g_module, 'dist_hook', None) - if dist_hook: - os.chdir(TMPFOLDER) - try: - dist_hook() - finally: - # go back to the root directory - os.chdir('..') - return TMPFOLDER - -Scripting.DistDir = DistDir - - diff --git a/wutils.py b/wutils.py index 6d16fac95..b4210e7d7 100644 --- a/wutils.py +++ b/wutils.py @@ -1,18 +1,17 @@ import os import os.path import sys -import pproc as subprocess +import subprocess import shlex # WAF modules -import ccroot import Options import Utils import Logs import TaskGen import Build import re - +from waflib.Errors import WafError # these are set from the main wscript file APPNAME=None @@ -48,10 +47,10 @@ else: return os.path.curdir return os.path.join(*rel_list) - +from waflib import Context def find_program(program_name, env): - launch_dir = os.path.abspath(Options.cwd_launch) - top_dir = os.path.abspath(Options.launch_dir) + launch_dir = os.path.abspath(Context.launch_dir) + #top_dir = os.path.abspath(Options.cwd_launch) found_programs = [] for obj in bld.all_task_gen: if not getattr(obj, 'is_ns3_program', False): @@ -63,7 +62,7 @@ def find_program(program_name, env): continue name1 = obj.target - name2 = os.path.join(relpath(obj.path.abspath(), top_dir), obj.target) + name2 = os.path.join(relpath(obj.path.abspath(), launch_dir), obj.target) names = [name1, name2] found_programs.extend(names) if program_name in names: @@ -99,7 +98,7 @@ def get_proc_env(os_env=None): else: proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH'])) - pymoddir = bld.path.find_dir('bindings/python').abspath(env) + pymoddir = bld.path.find_dir('bindings/python').get_bld().abspath() pyvizdir = bld.path.find_dir('src/visualizer').abspath() if 'PYTHONPATH' in proc_env: proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir, pyvizdir] + [proc_env['PYTHONPATH']]) @@ -117,9 +116,9 @@ def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False): proc_env = get_proc_env(os_env) if Options.options.valgrind and not force_no_valgrind: if Options.options.command_template: - raise Utils.WafError("Options --command-template and --valgrind are conflicting") + raise WafError("Options --command-template and --valgrind are conflicting") if not env['VALGRIND']: - raise Utils.WafError("valgrind is not installed") + raise WafError("valgrind is not installed") argv = [env['VALGRIND'], "--leak-check=full", "--show-reachable=yes", "--error-exitcode=1"] + argv proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE) error = False @@ -139,7 +138,7 @@ def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False): try: retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait() except WindowsError, ex: - raise Utils.WafError("Command %s raised exception %s" % (argv, ex)) + raise WafError("Command %s raised exception %s" % (argv, ex)) if retval: signame = None if retval < 0: # signal? @@ -150,11 +149,11 @@ def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False): signame = name break if signame: - raise Utils.WafError("Command %s terminated with signal %s." + raise WafError("Command %s terminated with signal %s." " Run it under a debugger to get more information " "(./waf --run --command-template=\"gdb --args %%s \")." % (argv, signame)) else: - raise Utils.WafError("Command %s exited with code %i" % (argv, retval)) + raise WafError("Command %s exited with code %i" % (argv, retval)) return retval def get_run_program(program_string, command_template=None): @@ -173,15 +172,15 @@ def get_run_program(program_string, command_template=None): try: program_obj = find_program(program_name, env) except ValueError, ex: - raise Utils.WafError(str(ex)) + raise WafError(str(ex)) - program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)) + program_node = program_obj.path.find_or_declare(program_obj.target) #try: # program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj)) #except AttributeError: # raise Utils.WafError("%s does not appear to be a program" % (program_name,)) - execvec = [program_node.abspath(env)] + argv[1:] + execvec = [program_node.abspath()] + argv[1:] else: @@ -189,9 +188,9 @@ def get_run_program(program_string, command_template=None): try: program_obj = find_program(program_name, env) except ValueError, ex: - raise Utils.WafError(str(ex)) + raise WafError(str(ex)) - program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)) + program_node = program_obj.path.find_or_declare(program_obj.target) #try: # program_node = program_obj.path.find_build(ccroot.get_target_name(program_obj)) #except AttributeError: