diff --git a/contrib/wscript b/contrib/wscript index 6744e1768..4bc99676d 100644 --- a/contrib/wscript +++ b/contrib/wscript @@ -1,4 +1,3 @@ - ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- from __future__ import print_function import os, os.path @@ -16,9 +15,7 @@ try: except NameError: from sets import Set as set # Python 2.3 fallback - - -all_modules = [] +all_contrib_modules = [] for dirname in os.listdir('contrib'): if dirname.startswith('.') or dirname == 'CVS': continue @@ -26,65 +23,23 @@ for dirname in os.listdir('contrib'): if not os.path.isdir(path): continue if os.path.exists(os.path.join(path, 'wscript')): - all_modules.append(dirname) -all_modules.sort() - - + all_contrib_modules.append(dirname) +all_contrib_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: + for module in all_contrib_modules: opt.recurse(module, mandatory=False) def configure(conf): - if not conf.env['REQUIRED_BOOST_LIBS']: - 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: + for module in all_contrib_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] - + 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. -@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) @@ -143,15 +98,6 @@ def create_ns3_module(bld, name, dependencies=(), test=False): 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. @@ -183,7 +129,6 @@ def create_obj(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) @@ -305,7 +250,6 @@ def ns3_python_bindings(bld): 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) @@ -315,439 +259,12 @@ def build(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_contrib_modules: + all_contrib_modules.remove(not_built) - if not_built in all_modules: - all_modules.remove(not_built) + bld.recurse(list(all_contrib_modules)) - bld.recurse(list(all_modules)) - - for module in all_modules: + for module in all_contrib_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]