## -*- 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_contrib_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_contrib_modules.append(dirname) all_contrib_modules.sort() def options(opt): for module in all_contrib_modules: opt.recurse(module, mandatory=False) def configure(conf): for module in all_contrib_modules: conf.recurse(module, mandatory=False) ## 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_contrib_modules] # we need the 'ns3module' waf "feature" to be created because code # elsewhere looks for it to find the ns3 module objects. 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/lib/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 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/.py exists, it becomes the module frontend, and the C extension befomes _ 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']: if not_built in all_contrib_modules: all_contrib_modules.remove(not_built) bld.recurse(list(all_contrib_modules)) for module in all_contrib_modules: modheader = bld(features='ns3moduleheader') modheader.module = module.split('/')[-1]