build: (fixes #2630) Add contrib directory in parallel to src
This commit is contained in:
@@ -112,14 +112,16 @@ is now exported by WifiNetDevice.</li>
|
||||
</li>
|
||||
<li> The <b>DequeueAll</b> method of <b>Queue</b> has been renamed <b>Flush</b>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Changes to build system:</h2>
|
||||
<ul>
|
||||
<li>The attributes <b>WifiPhy::TxAntennas</b> and <b>WifiPhy::RxAntennas</b>,
|
||||
and the related accessor methods, were replaced by <b>WifiPhy::MaxSupportedTxSpatialStreams</b>
|
||||
and <b>WifiPhy::MaxSupportedRxSpatialStreams</b>. A new attribute <b>WifiPhy::Antennas</b>
|
||||
was added to allow users to define the number of physical antennas on the device.
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Changes to build system:</h2>
|
||||
<ul>
|
||||
<li> Modules can now be located in the 'contrib/' directory in addition to 'src/'
|
||||
</li>
|
||||
<li> Behavior for running Python programs was aligned with that of C++ programs; the list of modules built is no longer printed out.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
752
contrib/wscript
Normal file
752
contrib/wscript
Normal file
@@ -0,0 +1,752 @@
|
||||
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
from __future__ import print_function
|
||||
import os, os.path
|
||||
import sys
|
||||
import shutil
|
||||
import types
|
||||
import warnings
|
||||
|
||||
from waflib import TaskGen, Task, Options, Build, Utils
|
||||
from waflib.Errors import WafError
|
||||
import wutils
|
||||
|
||||
try:
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
|
||||
|
||||
all_modules = []
|
||||
for dirname in os.listdir('contrib'):
|
||||
if dirname.startswith('.') or dirname == 'CVS':
|
||||
continue
|
||||
path = os.path.join('contrib', 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 "
|
||||
" --run and --shell; moreover, only works in some"
|
||||
" specific platforms, such as Linux and Solaris)"),
|
||||
action="store_true", dest='enable_rpath', default=False)
|
||||
|
||||
opt.add_option('--enable-modules',
|
||||
help=("Build only these modules (and dependencies)"),
|
||||
dest='enable_modules')
|
||||
|
||||
opt.load('boost', tooldir=['waf-tools'])
|
||||
|
||||
for module in all_modules:
|
||||
opt.recurse(module, mandatory=False)
|
||||
|
||||
def configure(conf):
|
||||
conf.env['REQUIRED_BOOST_LIBS'] = []
|
||||
for module in all_modules:
|
||||
conf.recurse (module, name="required_boost_libs", mandatory=False)
|
||||
|
||||
if conf.env['REQUIRED_BOOST_LIBS'] is not []:
|
||||
conf.load('boost')
|
||||
conf.check_boost(lib=' '.join (conf.env['REQUIRED_BOOST_LIBS']), mandatory=False)
|
||||
if not conf.env['LIB_BOOST']:
|
||||
conf.check_boost(lib=' '.join (conf.env['REQUIRED_BOOST_LIBS']), libpath="/usr/lib64", mandatory=False)
|
||||
if not conf.env['LIB_BOOST']:
|
||||
conf.env['LIB_BOOST'] = []
|
||||
|
||||
# Append blddir to the module path before recursing into modules
|
||||
blddir = os.path.abspath(os.path.join(conf.bldnode.abspath(), conf.variant))
|
||||
conf.env.append_value('NS3_MODULE_PATH', blddir)
|
||||
|
||||
for module in all_modules:
|
||||
conf.recurse(module, mandatory=False)
|
||||
|
||||
# Remove duplicate path items
|
||||
conf.env['NS3_MODULE_PATH'] = wutils.uniquify_list(conf.env['NS3_MODULE_PATH'])
|
||||
|
||||
if Options.options.enable_rpath:
|
||||
conf.env.append_value('RPATH', '-Wl,-rpath,%s' % (os.path.join(blddir),))
|
||||
|
||||
## Used to link the 'test-runner' program with all of ns-3 code
|
||||
conf.env['NS3_CONTRIBUTED_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
|
||||
|
||||
|
||||
|
||||
# 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):
|
||||
static = bool(bld.env.ENABLE_STATIC_NS3)
|
||||
# Create a separate library for this module.
|
||||
if static:
|
||||
module = bld(features='cxx cxxstlib ns3module')
|
||||
else:
|
||||
module = bld(features='cxx cxxshlib ns3module')
|
||||
module.target = '%s/ns%s-%s%s' % (bld.srcnode.path_from(module.path), wutils.VERSION,
|
||||
name, bld.env.BUILD_SUFFIX)
|
||||
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
|
||||
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.use = ['ns3-' + dep for dep in dependencies]
|
||||
module.test = test
|
||||
module.is_ns3_module = True
|
||||
module.ns3_dir_location = bld.path.path_from(bld.srcnode)
|
||||
|
||||
module.env.append_value("INCLUDES", '#')
|
||||
|
||||
module.pcfilegen = bld(features='ns3pcfile')
|
||||
module.pcfilegen.module = module.name
|
||||
|
||||
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.path_from(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.features += " ns3testlib"
|
||||
|
||||
# Modify attributes for the test library that are different from a
|
||||
# normal module.
|
||||
del library.is_ns3_module
|
||||
library.is_ns3_module_test_library = True
|
||||
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)])
|
||||
|
||||
# Set the include path from the build directory to modules.
|
||||
relative_path_from_build_to_here = bld.path.path_from(bld.bldnode)
|
||||
include_flag = '-I' + relative_path_from_build_to_here
|
||||
library.env.append_value('CXXFLAGS', include_flag)
|
||||
library.env.append_value('CCFLAGS', include_flag)
|
||||
|
||||
return library
|
||||
|
||||
def create_obj(bld, *args):
|
||||
warnings.warn("(in %s) Use bld(...) call now, instead of bld.create_obj(...)" % str(bld.path),
|
||||
DeprecationWarning, stacklevel=2)
|
||||
return bld(*args)
|
||||
|
||||
|
||||
def ns3_python_bindings(bld):
|
||||
|
||||
# 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)
|
||||
env = bld.env
|
||||
env.append_value("MODULAR_BINDINGS_MODULES", "ns3-"+module)
|
||||
|
||||
if Options.options.apiscan:
|
||||
return
|
||||
|
||||
if not env['ENABLE_PYTHON_BINDINGS']:
|
||||
return
|
||||
|
||||
bindings_dir = bld.path.find_dir("bindings")
|
||||
if bindings_dir is None or not os.path.exists(bindings_dir.abspath()):
|
||||
warnings.warn("(in %s) Requested to build modular python bindings, but apidefs dir not found "
|
||||
"=> skipped the bindings." % str(bld.path),
|
||||
Warning, stacklevel=2)
|
||||
return
|
||||
|
||||
if ("ns3-%s" % (module,)) not in env.NS3_ENABLED_MODULES:
|
||||
#print "bindings for module %s which is not enabled, skip" % module
|
||||
return
|
||||
|
||||
env.append_value('PYTHON_MODULES_BUILT', module)
|
||||
try:
|
||||
apidefs = env['PYTHON_BINDINGS_APIDEFS'].replace("-", "_")
|
||||
except AttributeError:
|
||||
# we likely got an empty list for env['PYTHON_BINDINGS_APIDEFS']
|
||||
return
|
||||
|
||||
#debug = ('PYBINDGEN_DEBUG' in os.environ)
|
||||
debug = True # XXX
|
||||
source = [bld.srcnode.find_resource('bindings/python/ns3modulegen-modular.py'),
|
||||
bld.path.find_resource("bindings/modulegen__%s.py" % apidefs)]
|
||||
|
||||
modulegen_customizations = bindings_dir.find_resource("modulegen_customizations.py")
|
||||
if modulegen_customizations is not None:
|
||||
source.append(modulegen_customizations)
|
||||
|
||||
modulegen_local = bld.path.find_resource("bindings/modulegen_local.py")
|
||||
# the local customization file may or not exist
|
||||
if modulegen_local is not None:
|
||||
source.append("bindings/modulegen_local.py")
|
||||
|
||||
module_py_name = module.replace('-', '_')
|
||||
module_target_dir = bld.srcnode.find_dir("bindings/python/ns").path_from(bld.path)
|
||||
|
||||
# if bindings/<module>.py exists, it becomes the module frontend, and the C extension befomes _<module>
|
||||
if bld.path.find_resource("bindings/%s.py" % (module_py_name,)) is not None:
|
||||
bld(features='copy',
|
||||
source=("bindings/%s.py" % (module_py_name,)),
|
||||
target=('%s/%s.py' % (module_target_dir, module_py_name)))
|
||||
extension_name = '_%s' % (module_py_name,)
|
||||
bld.install_files('${PYTHONARCHDIR}/ns', ["bindings/%s.py" % (module_py_name,)])
|
||||
else:
|
||||
extension_name = module_py_name
|
||||
|
||||
target = ['bindings/ns3module.cc', 'bindings/ns3module.h', 'bindings/ns3modulegen.log']
|
||||
#if not debug:
|
||||
# target.append('ns3modulegen.log')
|
||||
|
||||
argv = ['NS3_ENABLED_FEATURES=${FEATURES}',
|
||||
'GCC_RTTI_ABI_COMPLETE=${GCC_RTTI_ABI_COMPLETE}',
|
||||
'${PYTHON}']
|
||||
#if debug:
|
||||
# argv.extend(["-m", "pdb"])
|
||||
|
||||
argv.extend(['${SRC[0]}', module_abs_src_path, apidefs, extension_name, '${TGT[0]}'])
|
||||
|
||||
argv.extend(['2>', '${TGT[2]}']) # 2> ns3modulegen.log
|
||||
|
||||
features = []
|
||||
for (name, caption, was_enabled, reason_not_enabled) in env['NS3_OPTIONAL_FEATURES']:
|
||||
if was_enabled:
|
||||
features.append(name)
|
||||
|
||||
bindgen = bld(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'
|
||||
bindgen.name = "pybindgen(ns3 module %s)" % module
|
||||
bindgen.install_path = None
|
||||
|
||||
# generate the extension module
|
||||
pymod = bld(features='cxx cxxshlib pyext')
|
||||
pymod.source = ['bindings/ns3module.cc']
|
||||
pymod.target = '%s/%s' % (module_target_dir, extension_name)
|
||||
pymod.name = 'ns3module_%s' % module
|
||||
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.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.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['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['DEFINES'] = defines
|
||||
pymod.includes = '# bindings'
|
||||
pymod.install_path = '${PYTHONARCHDIR}/ns'
|
||||
|
||||
# Workaround to a WAF bug, remove this when ns-3 upgrades to WAF > 1.6.10
|
||||
# https://www.nsnam.org/bugzilla/show_bug.cgi?id=1335
|
||||
# http://code.google.com/p/waf/issues/detail?id=1098
|
||||
if Utils.unversioned_sys_platform() == 'darwin':
|
||||
pymod.mac_bundle = True
|
||||
|
||||
return pymod
|
||||
|
||||
|
||||
def build(bld):
|
||||
bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
|
||||
bld.create_ns3_module_test_library = types.MethodType(create_ns3_module_test_library, bld)
|
||||
bld.create_obj = types.MethodType(create_obj, bld)
|
||||
bld.ns3_python_bindings = types.MethodType(ns3_python_bindings, bld)
|
||||
|
||||
# Remove these modules from the list of all modules.
|
||||
for not_built in bld.env['MODULES_NOT_BUILT']:
|
||||
|
||||
# XXX Because these modules are located in subdirectories of
|
||||
# test, their names in the all_modules list include the extra
|
||||
# relative path "test/". If these modules are moved into the
|
||||
# src directory, then this if block should be removed.
|
||||
if not_built == 'ns3tcp' or not_built == 'ns3wifi':
|
||||
not_built = 'test/' + not_built
|
||||
|
||||
if not_built in all_modules:
|
||||
all_modules.remove(not_built)
|
||||
|
||||
bld.recurse(list(all_modules))
|
||||
|
||||
for module in all_modules:
|
||||
modheader = bld(features='ns3moduleheader')
|
||||
modheader.module = module.split('/')[-1]
|
||||
|
||||
class ns3pcfile_task(Task.Task):
|
||||
after = 'cxx'
|
||||
|
||||
def __str__(self):
|
||||
"string to display to the user"
|
||||
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
|
||||
return 'pcfile: %s\n' % (tgt_str)
|
||||
|
||||
def runnable_status(self):
|
||||
return super(ns3pcfile_task, self).runnable_status()
|
||||
|
||||
def _self_libs(self, env, name, libdir):
|
||||
if env['ENABLE_STATIC_NS3']:
|
||||
path_st = 'STLIBPATH_ST'
|
||||
lib_st = 'STLIB_ST'
|
||||
lib_marker = 'STLIB_MARKER'
|
||||
else:
|
||||
path_st = 'LIBPATH_ST'
|
||||
lib_st = 'LIB_ST'
|
||||
lib_marker = 'SHLIB_MARKER'
|
||||
retval = [env[path_st] % libdir]
|
||||
if env[lib_marker]:
|
||||
retval.append(env[lib_marker])
|
||||
retval.append(env[lib_st] % name)
|
||||
return retval
|
||||
|
||||
def _lib(self, env, dep):
|
||||
libpath = env['LIBPATH_%s' % dep]
|
||||
linkflags = env['LINKFLAGS_%s' % dep]
|
||||
libs = env['LIB_%s' % dep]
|
||||
retval = []
|
||||
for path in libpath:
|
||||
retval.append(env['LIBPATH_ST'] % path)
|
||||
retval = retval + linkflags
|
||||
for lib in libs:
|
||||
retval.append(env['LIB_ST'] % lib)
|
||||
return retval
|
||||
|
||||
def _listify(self, v):
|
||||
if isinstance(v, list):
|
||||
return v
|
||||
else:
|
||||
return [v]
|
||||
|
||||
def _cflags(self, dep):
|
||||
flags = self.env['CFLAGS_%s' % dep]
|
||||
return self._listify(flags)
|
||||
|
||||
def _cxxflags(self, dep):
|
||||
return self._listify(self.env['CXXFLAGS_%s' % dep])
|
||||
|
||||
def _defines(self, dep):
|
||||
return [self.env['DEFINES_ST'] % define for define in self.env['DEFINES_%s' % dep]]
|
||||
|
||||
def _includes(self, dep):
|
||||
includes = self.env['INCLUDES_%s' % dep]
|
||||
return [self.env['CPPPATH_ST'] % include for include in includes]
|
||||
|
||||
def _generate_pcfile(self, name, use, env, outfilename):
|
||||
outfile = open(outfilename, 'wt')
|
||||
prefix = env.PREFIX
|
||||
includedir = Utils.subst_vars('${INCLUDEDIR}/%s%s' % (wutils.APPNAME, wutils.VERSION), env)
|
||||
libdir = env.LIBDIR
|
||||
libs = self._self_libs(env, "%s%s-%s%s" % (wutils.APPNAME, wutils.VERSION, name[4:], env.BUILD_SUFFIX), '${libdir}')
|
||||
for dep in use:
|
||||
libs += self._lib(env, dep)
|
||||
for dep in env.LIBS:
|
||||
libs += self.env['LIB_ST'] % dep
|
||||
cflags = [self.env['CPPPATH_ST'] % '${includedir}']
|
||||
requires = []
|
||||
for dep in use:
|
||||
cflags = cflags + self._cflags(dep) + self._cxxflags(dep) + \
|
||||
self._defines(dep) + self._includes(dep)
|
||||
if dep.startswith('ns3-'):
|
||||
dep_name = dep[4:]
|
||||
requires.append("libns%s-%s%s" % (wutils.VERSION, dep_name, env.BUILD_SUFFIX))
|
||||
print("""\
|
||||
prefix=%s
|
||||
libdir=%s
|
||||
includedir=%s
|
||||
|
||||
Name: lib%s
|
||||
Description: ns-3 module %s
|
||||
Version: %s
|
||||
Libs: %s
|
||||
Cflags: %s
|
||||
Requires: %s\
|
||||
""" % (prefix, libdir, includedir,
|
||||
name, name, wutils.VERSION, ' '.join(libs), ' '.join(cflags), ' '.join(requires)), file=outfile)
|
||||
outfile.close()
|
||||
|
||||
def run(self):
|
||||
output_filename = self.outputs[0].abspath()
|
||||
self._generate_pcfile(self.module.name,
|
||||
self.module.to_list(self.module.use),
|
||||
self.env, output_filename)
|
||||
|
||||
|
||||
@TaskGen.feature('ns3pcfile')
|
||||
@TaskGen.after_method('process_rule')
|
||||
def apply(self):
|
||||
module = self.bld.find_ns3_module(self.module)
|
||||
output_filename = 'lib%s.pc' % os.path.basename(module.target)
|
||||
output_node = self.path.find_or_declare(output_filename)
|
||||
assert output_node is not None, str(self)
|
||||
task = self.create_task('ns3pcfile')
|
||||
self.bld.install_files('${LIBDIR}/pkgconfig', output_node)
|
||||
task.set_outputs([output_node])
|
||||
task.module = module
|
||||
|
||||
|
||||
|
||||
@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_or_declare("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('${INCLUDEDIR}/%s%s/ns3' % (wutils.APPNAME, wutils.VERSION), [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 = 'cxx gen_ns3_module_header'
|
||||
color = 'BLUE'
|
||||
|
||||
def __str__(self):
|
||||
"string to display to the user"
|
||||
env = self.env
|
||||
src_str = ' '.join([a.bldpath() for a in self.inputs])
|
||||
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
|
||||
if self.outputs: sep = ' -> '
|
||||
else: sep = ''
|
||||
if self.mode == 'remove':
|
||||
return 'rm-ns3-header %s' % (self.header_to_remove.abspath(),)
|
||||
return 'install-ns3-header: %s' % (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.encode())
|
||||
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.abspath()):
|
||||
return Task.RUN_ME
|
||||
else:
|
||||
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.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, 0o600)
|
||||
except OSError:
|
||||
pass
|
||||
shutil.copy2(src, dst)
|
||||
## make the headers in builddir read-only, to prevent
|
||||
## accidental modification
|
||||
os.chmod(dst, 0o400)
|
||||
return 0
|
||||
else:
|
||||
assert len(self.inputs) == 0
|
||||
assert len(self.outputs) == 0
|
||||
out_file_name = self.header_to_remove.abspath()
|
||||
try:
|
||||
os.unlink(out_file_name)
|
||||
except OSError as ex:
|
||||
if ex.errno != 2:
|
||||
raise
|
||||
return 0
|
||||
|
||||
|
||||
@TaskGen.feature('ns3privateheader')
|
||||
@TaskGen.after_method('process_rule')
|
||||
def apply_ns3privateheader(self):
|
||||
if self.module is None:
|
||||
raise WafError("'module' missing on ns3headers object %s" % self)
|
||||
ns3_dir_node = self.bld.path.find_or_declare("ns3/private")
|
||||
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('ns3privateheader')
|
||||
task.mode = getattr(self, 'mode', 'install')
|
||||
if task.mode == 'install':
|
||||
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 ns3privateheader_task(Task.Task):
|
||||
before = 'cxx gen_ns3_module_header'
|
||||
after = 'ns3header'
|
||||
color = 'BLUE'
|
||||
|
||||
def __str__(self):
|
||||
"string to display to the user"
|
||||
env = self.env
|
||||
src_str = ' '.join([a.bldpath() for a in self.inputs])
|
||||
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
|
||||
if self.outputs: sep = ' -> '
|
||||
else: sep = ''
|
||||
if self.mode == 'remove':
|
||||
return 'rm-ns3-header %s' % (self.header_to_remove.abspath(),)
|
||||
return 'install-ns3-header: %s' % (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.encode())
|
||||
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.abspath()):
|
||||
return Task.RUN_ME
|
||||
else:
|
||||
return Task.SKIP_ME
|
||||
else:
|
||||
return super(ns3privateheader_task, self).runnable_status()
|
||||
|
||||
def run(self):
|
||||
if self.mode == 'install':
|
||||
assert len(self.inputs) == len(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, 0o600)
|
||||
except OSError:
|
||||
pass
|
||||
shutil.copy2(src, dst)
|
||||
## make the headers in builddir read-only, to prevent
|
||||
## accidental modification
|
||||
os.chmod(dst, 0o400)
|
||||
return 0
|
||||
else:
|
||||
assert len(self.inputs) == 0
|
||||
assert len(self.outputs) == 0
|
||||
out_file_name = self.header_to_remove.abspath()
|
||||
try:
|
||||
os.unlink(out_file_name)
|
||||
except OSError as ex:
|
||||
if ex.errno != 2:
|
||||
raise
|
||||
return 0
|
||||
|
||||
|
||||
class gen_ns3_module_header_task(Task.Task):
|
||||
before = 'cxx'
|
||||
after = 'ns3header'
|
||||
color = 'BLUE'
|
||||
|
||||
def runnable_status(self):
|
||||
if self.mode == 'remove':
|
||||
if os.path.exists(self.header_to_remove.abspath()):
|
||||
return Task.RUN_ME
|
||||
else:
|
||||
return Task.SKIP_ME
|
||||
else:
|
||||
return super(gen_ns3_module_header_task, self).runnable_status()
|
||||
|
||||
def __str__(self):
|
||||
"string to display to the user"
|
||||
env = self.env
|
||||
src_str = ' '.join([a.bldpath() for a in self.inputs])
|
||||
tgt_str = ' '.join([a.bldpath() for a in self.outputs])
|
||||
if self.outputs: sep = ' -> '
|
||||
else: sep = ''
|
||||
if self.mode == 'remove':
|
||||
return 'rm-module-header %s' % (self.header_to_remove.abspath(),)
|
||||
return 'gen-module-header: %s' % (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.abspath()
|
||||
try:
|
||||
os.unlink(out_file_name)
|
||||
except OSError as ex:
|
||||
if ex.errno != 2:
|
||||
raise
|
||||
return 0
|
||||
assert len(self.outputs) == 1
|
||||
out_file_name = self.outputs[0].get_bld().abspath()#self.env)
|
||||
header_files = [os.path.basename(node.abspath()) for node in self.inputs]
|
||||
outfile = open(out_file_name, "w")
|
||||
header_files.sort()
|
||||
|
||||
print("""
|
||||
#ifdef NS3_MODULE_COMPILATION
|
||||
# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
|
||||
#endif
|
||||
|
||||
#ifndef NS3_MODULE_%s
|
||||
""" % (self.module.upper().replace('-', '_'),), file=outfile)
|
||||
|
||||
# if self.module_deps:
|
||||
# print >> outfile, "// Module dependencies:"
|
||||
# for dep in self.module_deps:
|
||||
# print >> outfile, "#include \"%s-module.h\"" % dep
|
||||
|
||||
print(file=outfile)
|
||||
print("// Module headers:", file=outfile)
|
||||
for header in header_files:
|
||||
print("#include \"%s\"" % (header,), file=outfile)
|
||||
|
||||
print("#endif", file=outfile)
|
||||
|
||||
outfile.close()
|
||||
return 0
|
||||
|
||||
def sig_explicit_deps(self):
|
||||
self.m.update('\n'.join(sorted([node.abspath() for node in self.inputs])).encode('utf-8'))
|
||||
return self.m.digest()
|
||||
|
||||
def unique_id(self):
|
||||
try:
|
||||
return self.uid
|
||||
except AttributeError:
|
||||
"this is not a real hot zone, but we want to avoid surprizes here"
|
||||
m = Utils.md5()
|
||||
m.update("ns-3-module-header-%s" % self.module)
|
||||
self.uid = m.digest()
|
||||
return self.uid
|
||||
|
||||
|
||||
# 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_or_declare("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 sorted(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
|
||||
|
||||
try:
|
||||
module_obj = self.bld.get_tgen_by_name("ns3-" + self.module)
|
||||
except WafError: # maybe the module was disabled, and therefore removed
|
||||
return
|
||||
|
||||
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('${INCLUDEDIR}/%s%s/ns3' % (wutils.APPNAME, wutils.VERSION),
|
||||
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]
|
||||
@@ -788,7 +788,8 @@ INPUT = doc/modules \
|
||||
doc/introspected-doxygen.h \
|
||||
examples \
|
||||
utils \
|
||||
src
|
||||
src \
|
||||
contrib
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
||||
21
test.py
21
test.py
@@ -46,6 +46,7 @@ except ImportError:
|
||||
#
|
||||
interesting_config_items = [
|
||||
"NS3_ENABLED_MODULES",
|
||||
"NS3_ENABLED_CONTRIBUTED_MODULES",
|
||||
"NS3_MODULE_PATH",
|
||||
"NSC_ENABLED",
|
||||
"ENABLE_REAL_TIME",
|
||||
@@ -1153,6 +1154,26 @@ def run_tests():
|
||||
example_tests,
|
||||
example_names_original,
|
||||
python_tests)
|
||||
|
||||
for module in NS3_ENABLED_CONTRIBUTED_MODULES:
|
||||
# Remove the "ns3-" from the module name.
|
||||
module = module[len("ns3-"):]
|
||||
|
||||
# Set the directories and paths for this example.
|
||||
module_directory = os.path.join("contrib", 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, example_directory)
|
||||
python_script_dir = os.path.join(example_directory)
|
||||
|
||||
# Parse this module's file.
|
||||
parse_examples_to_run_file(
|
||||
examples_to_run_path,
|
||||
cpp_executable_dir,
|
||||
python_script_dir,
|
||||
example_tests,
|
||||
example_names_original,
|
||||
python_tests)
|
||||
|
||||
#
|
||||
# If lots of logging is enabled, we can crash Python when it tries to
|
||||
|
||||
81
wscript
81
wscript
@@ -246,7 +246,7 @@ def options(opt):
|
||||
opt.recurse('src')
|
||||
opt.recurse('bindings/python')
|
||||
opt.recurse('src/internet')
|
||||
|
||||
opt.recurse('contrib')
|
||||
|
||||
def _check_compilation_flag(conf, flag, mode='cxx', linkflags=None):
|
||||
"""
|
||||
@@ -457,21 +457,46 @@ def configure(conf):
|
||||
conf.recurse('bindings/python')
|
||||
|
||||
conf.recurse('src')
|
||||
conf.recurse('contrib')
|
||||
|
||||
# Set the list of enabled modules.
|
||||
if Options.options.enable_modules:
|
||||
# Use the modules explicitly enabled.
|
||||
conf.env['NS3_ENABLED_MODULES'] = ['ns3-'+mod for mod in
|
||||
Options.options.enable_modules.split(',')]
|
||||
_enabled_mods = []
|
||||
_enabled_contrib_mods = []
|
||||
for mod in Options.options.enable_modules.split(','):
|
||||
if mod in conf.env['NS3_MODULES'] and mod.startswith('ns3-'):
|
||||
_enabled_mods.append(mod)
|
||||
elif 'ns3-' + mod in conf.env['NS3_MODULES']:
|
||||
_enabled_mods.append('ns3-' + mod)
|
||||
elif mod in conf.env['NS3_CONTRIBUTED_MODULES'] and mod.startswith('ns3-'):
|
||||
_enabled_contrib_mods.append(mod)
|
||||
elif 'ns3-' + mod in conf.env['NS3_CONTRIBUTED_MODULES']:
|
||||
_enabled_contrib_mods.append('ns3-' + mod)
|
||||
conf.env['NS3_ENABLED_MODULES'] = _enabled_mods
|
||||
conf.env['NS3_ENABLED_CONTRIBUTED_MODULES'] = _enabled_contrib_mods
|
||||
|
||||
else:
|
||||
# Use the enabled modules list from the ns3 configuration file.
|
||||
if modules_enabled[0] == 'all_modules':
|
||||
# Enable all modules if requested.
|
||||
conf.env['NS3_ENABLED_MODULES'] = conf.env['NS3_MODULES']
|
||||
conf.env['NS3_ENABLED_CONTRIBUTED_MODULES'] = conf.env['NS3_CONTRIBUTED_MODULES']
|
||||
else:
|
||||
# Enable the modules from the list.
|
||||
conf.env['NS3_ENABLED_MODULES'] = ['ns3-'+mod for mod in
|
||||
modules_enabled]
|
||||
_enabled_mods = []
|
||||
_enabled_contrib_mods = []
|
||||
for mod in modules_enabled:
|
||||
if mod in conf.env['NS3_MODULES'] and mod.startswith('ns3-'):
|
||||
_enabled_mods.append(mod)
|
||||
elif 'ns3-' + mod in conf.env['NS3_MODULES']:
|
||||
_enabled_mods.append('ns3-' + mod)
|
||||
elif mod in conf.env['NS3_CONTRIBUTED_MODULES'] and mod.startswith('ns3-'):
|
||||
_enabled_contrib_mods.append(mod)
|
||||
elif 'ns3-' + mod in conf.env['NS3_CONTRIBUTED_MODULES']:
|
||||
_enabled_contrib_mods.append('ns3-' + mod)
|
||||
conf.env['NS3_ENABLED_MODULES'] = _enabled_mods
|
||||
conf.env['NS3_ENABLED_CONTRIBUTED_MODULES'] = _enabled_contrib_mods
|
||||
|
||||
# Add the template module to the list of enabled modules that
|
||||
# should not be built if this is a static build on Darwin. They
|
||||
@@ -487,6 +512,8 @@ def configure(conf):
|
||||
conf.env['NS3_ENABLED_MODULES'].remove(not_built_name)
|
||||
if not conf.env['NS3_ENABLED_MODULES']:
|
||||
raise WafError('Exiting because the ' + not_built + ' module can not be built and it was the only one enabled.')
|
||||
elif not_built_name in conf.env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
conf.env['NS3_ENABLED_CONTRIBUTED_MODULES'].remove(not_built_name)
|
||||
|
||||
conf.recurse('src/mpi')
|
||||
|
||||
@@ -719,7 +746,8 @@ def add_examples_programs(bld):
|
||||
return
|
||||
|
||||
def add_scratch_programs(bld):
|
||||
all_modules = [mod[len("ns3-"):] for mod in bld.env['NS3_ENABLED_MODULES']]
|
||||
all_modules = [mod[len("ns3-"):] for mod in bld.env['NS3_ENABLED_MODULES'] + bld.env['NS3_ENABLED_CONTRIBUTED_MODULES']]
|
||||
|
||||
try:
|
||||
for filename in os.listdir("scratch"):
|
||||
if filename.startswith('.') or filename == 'CVS':
|
||||
@@ -835,18 +863,21 @@ def build(bld):
|
||||
|
||||
# process subfolders from here
|
||||
bld.recurse('src')
|
||||
bld.recurse('contrib')
|
||||
|
||||
# If modules have been enabled, then set lists of enabled modules
|
||||
# and enabled module test libraries.
|
||||
if env['NS3_ENABLED_MODULES']:
|
||||
if env['NS3_ENABLED_MODULES'] or env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
|
||||
modules = env['NS3_ENABLED_MODULES']
|
||||
contribModules = env['NS3_ENABLED_CONTRIBUTED_MODULES']
|
||||
|
||||
# Find out about additional modules that need to be enabled
|
||||
# due to dependency constraints.
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
for module in modules:
|
||||
for module in modules + contribModules:
|
||||
module_obj = bld.get_tgen_by_name(module)
|
||||
if module_obj is None:
|
||||
raise ValueError("module %s not found" % module)
|
||||
@@ -854,31 +885,35 @@ def build(bld):
|
||||
for dep in module_obj.use:
|
||||
if not dep.startswith('ns3-'):
|
||||
continue
|
||||
if dep not in modules:
|
||||
modules.append(dep)
|
||||
if dep not in modules and dep not in contribModules:
|
||||
if dep in env['NS3_MODULES']: modules.append(dep)
|
||||
elif dep in env['NS3_CONTRIBUTED_MODULES']: contribModules.append(dep)
|
||||
changed = True
|
||||
|
||||
env['NS3_ENABLED_MODULES'] = modules
|
||||
|
||||
env['NS3_ENABLED_CONTRIBUTED_MODULES'] = contribModules
|
||||
|
||||
# If tests are being built, then set the list of the enabled
|
||||
# module test libraries.
|
||||
if env['ENABLE_TESTS']:
|
||||
for (mod, testlib) in bld.env['NS3_MODULES_WITH_TEST_LIBRARIES']:
|
||||
if mod in bld.env['NS3_ENABLED_MODULES']:
|
||||
if mod in bld.env['NS3_ENABLED_MODULES'] or mod in bld.env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
bld.env.append_value('NS3_ENABLED_MODULE_TEST_LIBRARIES', testlib)
|
||||
|
||||
add_examples_programs(bld)
|
||||
add_scratch_programs(bld)
|
||||
|
||||
if env['NS3_ENABLED_MODULES']:
|
||||
if env['NS3_ENABLED_MODULES'] or env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
modules = env['NS3_ENABLED_MODULES']
|
||||
contribModules = env['NS3_ENABLED_CONTRIBUTED_MODULES']
|
||||
|
||||
# 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 'ns3moduleheader' in getattr(obj, "features", []):
|
||||
if ("ns3-%s" % obj.module) not in modules:
|
||||
if ("ns3-%s" % obj.module) not in modules and ("ns3-%s" % obj.module) not in contribModules:
|
||||
obj.mode = 'remove' # tell it to remove headers instead of installing
|
||||
|
||||
# check for programs
|
||||
@@ -886,7 +921,7 @@ def build(bld):
|
||||
# this is an NS-3 program (bld.create_ns3_program)
|
||||
program_built = True
|
||||
for dep in obj.ns3_module_dependencies:
|
||||
if dep not in modules: # prog. depends on a module that isn't enabled?
|
||||
if dep not in modules and dep not in contribModules: # prog. depends on a module that isn't enabled?
|
||||
bld.exclude_taskgen(obj)
|
||||
program_built = False
|
||||
break
|
||||
@@ -907,38 +942,42 @@ def build(bld):
|
||||
bld.env.append_value('NS3_RUNNABLE_PROGRAMS', object_relative_path)
|
||||
|
||||
# disable the modules themselves
|
||||
if hasattr(obj, "is_ns3_module") and obj.name not in modules:
|
||||
if hasattr(obj, "is_ns3_module") and obj.name not in modules and obj.name not in contribModules:
|
||||
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):
|
||||
if not env['ENABLE_TESTS'] or ((obj.module_name not in modules) and (obj.module_name not in contribModules)) :
|
||||
bld.exclude_taskgen(obj) # kill the module test library
|
||||
|
||||
# disable the ns3header_taskgen
|
||||
if 'ns3header' in getattr(obj, "features", []):
|
||||
if ("ns3-%s" % obj.module) not in modules:
|
||||
if ("ns3-%s" % obj.module) not in modules and ("ns3-%s" % obj.module) not in contribModules:
|
||||
obj.mode = 'remove' # tell it to remove headers instead of installing
|
||||
|
||||
# disable the ns3privateheader_taskgen
|
||||
if 'ns3privateheader' in getattr(obj, "features", []):
|
||||
if ("ns3-%s" % obj.module) not in modules:
|
||||
if ("ns3-%s" % obj.module) not in modules and ("ns3-%s" % obj.module) not in contribModules:
|
||||
|
||||
obj.mode = 'remove' # tell it to remove headers instead of installing
|
||||
|
||||
# disable pcfile taskgens for disabled modules
|
||||
if 'ns3pcfile' in getattr(obj, "features", []):
|
||||
if obj.module not in bld.env.NS3_ENABLED_MODULES:
|
||||
if obj.module not in bld.env.NS3_ENABLED_MODULES and obj.module not in bld.env.NS3_ENABLED_CONTRIBUTED_MODULES:
|
||||
bld.exclude_taskgen(obj)
|
||||
|
||||
|
||||
if env['NS3_ENABLED_MODULES']:
|
||||
env['NS3_ENABLED_MODULES'] = list(modules)
|
||||
|
||||
if env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
env['NS3_ENABLED_CONTRIBUTED_MODULES'] = list(contribModules)
|
||||
|
||||
# Determine which scripts will be runnable.
|
||||
for (script, dependencies) in bld.env['NS3_SCRIPT_DEPENDENCIES']:
|
||||
script_runnable = True
|
||||
for dep in dependencies:
|
||||
if dep not in modules:
|
||||
if dep not in modules and dep not in contribModules:
|
||||
script_runnable = False
|
||||
break
|
||||
|
||||
@@ -1018,7 +1057,7 @@ def shutdown(ctx):
|
||||
print()
|
||||
print('Modules built:')
|
||||
names_without_prefix = []
|
||||
for name in env['NS3_ENABLED_MODULES']:
|
||||
for name in env['NS3_ENABLED_MODULES'] + env['NS3_ENABLED_CONTRIBUTED_MODULES']:
|
||||
name1 = name[len('ns3-'):]
|
||||
if name not in env.MODULAR_BINDINGS_MODULES:
|
||||
name1 += " (no Python)"
|
||||
|
||||
Reference in New Issue
Block a user