Merge waf-1.6 branch

This commit is contained in:
Gustavo J. A. M. Carneiro
2011-09-18 12:23:17 +01:00
56 changed files with 1531 additions and 920 deletions

View File

@@ -7,7 +7,7 @@
^testpy-output
^doc/html
^doc/latex
^\.lock-wscript
^\.lock-wafbuild
^\.waf
^doc/introspected-doxygen\.h$
.*\.py[co]$

View File

@@ -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.h>
""" + 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.h>
""" + 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.

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -6,7 +6,7 @@
#include <stdint.h>
#include <math.h>
#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

View File

@@ -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'],
"<pthread.h> 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']:

207
src/create-module.py Executable file
View File

@@ -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))

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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'

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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')

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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'

View File

@@ -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',

View File

@@ -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.

View File

@@ -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',

View File

@@ -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',

View File

@@ -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')

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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]

38
test.py
View File

@@ -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.

View File

@@ -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']]

BIN
waf vendored

Binary file not shown.

269
waf-tools/boost.py Normal file
View File

@@ -0,0 +1,269 @@
#!/usr/bin/env python
# encoding: utf-8
#
# partially based on boost.py written by Gernot Vormayr
# written by Ruediger Sonderfeld <ruediger@c-plusplus.de>, 2008
# modified by Bjoern Michaelsen, 2008
# modified by Luca Fossati, 2008
# rewritten for waf 1.5.1, Thomas Nagy, 2008
# rewritten for waf 1.6.2, Sylvain Rouquette, 2011
'''
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 <iostream>
#include <boost/version.hpp>
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)

View File

@@ -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):

View File

@@ -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<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\}
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')

416
waf-tools/misc.py Normal file
View File

@@ -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)

View File

@@ -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

434
wscript
View File

@@ -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 <stdio.h>\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

View File

@@ -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 <program> --command-template=\"gdb --args %%s <args>\")." % (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: