From 0536f2416f69bb2895f0fcfc5fe62dc360e4c8e3 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 12 Sep 2011 14:54:27 +0100 Subject: [PATCH] More waf 1.6.7 build fixes --- bindings/python/wscript | 2 +- src/click/wscript | 2 +- src/core/wscript | 2 +- src/internet/wscript | 2 +- src/openflow/wscript | 2 +- src/wscript | 109 ++++++++++++++++++++++++++-------------- test.py | 38 +++++--------- waf-tools/cflags.py | 4 +- wscript | 109 ++++++++++++++-------------------------- 9 files changed, 130 insertions(+), 140 deletions(-) diff --git a/bindings/python/wscript b/bindings/python/wscript index bcbb57b36..9f5a47e2c 100644 --- a/bindings/python/wscript +++ b/bindings/python/wscript @@ -46,7 +46,7 @@ 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."), diff --git a/src/click/wscript b/src/click/wscript index 955bb2637..e72a78d44 100644 --- a/src/click/wscript +++ b/src/click/wscript @@ -4,7 +4,7 @@ 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) diff --git a/src/core/wscript b/src/core/wscript index 0c6483ab5..07db59c19 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -3,7 +3,7 @@ import sys import Options -def set_options(opt): +def options(opt): opt.add_option('--int64x64-as-double', help=('Whether to use a double floating point' ' type for int64x64 values' diff --git a/src/internet/wscript b/src/internet/wscript index 6a699ea9a..65aeaa70a 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -11,7 +11,7 @@ import Task NSC_RELEASE_NAME = "nsc-0.5.2" -def set_options(opt): +def options(opt): opt.add_option('--with-nsc', help=('Use Network Simulation Cradle, given by the indicated path,' ' to allow the use of real-world network stacks'), diff --git a/src/openflow/wscript b/src/openflow/wscript index 99b8f959f..4a639f7d5 100644 --- a/src/openflow/wscript +++ b/src/openflow/wscript @@ -3,7 +3,7 @@ import os import Options -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') diff --git a/src/wscript b/src/wscript index e53a6cce1..7b9759c4b 100644 --- a/src/wscript +++ b/src/wscript @@ -6,6 +6,8 @@ import shutil import types import warnings +from waflib.Errors import WafError + import TaskGen import Task import Options @@ -65,7 +67,7 @@ all_modules = [ 'template', ] -def set_options(opt): +def options(opt): opt.sub_options('core') opt.sub_options('click') opt.sub_options('openflow') @@ -157,14 +159,42 @@ def configure(conf): # # FIXME: env modifications are overwritten by parent caller +@TaskGen.feature('ns3module') +@TaskGen.after_method('process_rule') +def _add_test_code(module): + bld = module.bld + if 0: #len(module.source) > 0 and hasattr(module, '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(module.ns3_dir_location, src) + path = os.path.dirname(full_src) + target = '%s_object' % src + # XXX: calculate the features correctly here. + obj = bld.objects(source=[full_src], target=target, features='cxx cc', + env = module.env.copy()) + obj.env.CXXDEFINES += 'NS_TEST_SOURCEDIR="%s"' % path + obj.env.INCLUDES += uselib_cpppath + obj.name = module.name + '--test' + objects.append(target) + last = module.source[-1] + full_src = os.path.join(module.ns3_dir_location, last) + path = os.path.dirname(full_src) + module.env.CXXDEFINES += 'NS_TEST_SOURCEDIR="%s"' % path + module.source = [last] + objects + #module.add_objects.extend(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.new_task_gen(features=['cxx', 'cxxstlib']) + module = bld.new_task_gen(features=['cxx', 'cxxstlib', 'ns3module']) else: - module = bld.new_task_gen(features=['cxx', 'cxxshlib']) + module = bld.new_task_gen(features=['cxx', 'cxxshlib', 'ns3module']) linkflags = [] cxxflags = [] ccflags = [] @@ -219,38 +249,24 @@ def create_ns3_module(bld, name, dependencies=(), test=False): module.ns3_dir_location = bld.path.relpath_gen(bld.srcnode) module.env.append_value("INCLUDES", '#') - - 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) - + 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. @@ -259,7 +275,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) @@ -528,6 +544,7 @@ def apply_ns3header(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: @@ -557,12 +574,30 @@ 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)): + if os.path.exists(self.header_to_remove.abspath()): return Task.RUN_ME else: return Task.SKIP_ME @@ -587,7 +622,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: @@ -603,7 +638,7 @@ class gen_ns3_module_header_task(Task.Task): def runnable_status(self): if self.mode == 'remove': - if os.path.exists(self.header_to_remove.bldpath(self.env)): + if os.path.exists(self.header_to_remove.abspath()): return Task.RUN_ME else: return Task.SKIP_ME @@ -618,14 +653,14 @@ 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: @@ -702,8 +737,8 @@ def apply_ns3moduleheader(self): return try: - module_obj = self.bld.get_taskgen("ns3-" + self.module) - except KeyError: # maybe the module was disabled, and therefore removed + 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)] diff --git a/test.py b/test.py index f4c2433ca..7fee5e8fb 100755 --- a/test.py +++ b/test.py @@ -42,7 +42,6 @@ from utils import get_list_from_file # found in the associated subdirectory wscript files. # interesting_config_items = [ - "NS3_BUILDDIR", "NS3_ENABLED_MODULES", "NS3_MODULE_PATH", "NSC_ENABLED", @@ -483,24 +482,6 @@ def sigint_hook(signal, frame): thread_exit = True return 0 -# -# Waf can be configured to compile in debug or optimized modes. In each -# case, the resulting built goes into a different directory. If we want -# test tests to run from the correct code-base, we have to figure out which -# mode waf is running in. This is called its active variant. -# -# XXX This function pokes around in the waf internal state file. To be a -# little less hacky, we should add a commmand to waf to return this info -# and use that result. -# -def read_waf_active_variant(): - for line in open("build/c4che/default.cache.py").readlines(): - if line.startswith("NS3_ACTIVE_VARIANT"): - exec(line, globals()) - break - - if options.verbose: - print "NS3_ACTIVE_VARIANT == %s" % NS3_ACTIVE_VARIANT # # In general, the build process itself naturally takes care of figuring out @@ -519,7 +500,13 @@ def read_waf_active_variant(): # and use that result. # def read_waf_config(): - for line in open("build/c4che/%s.cache.py" % NS3_ACTIVE_VARIANT).readlines(): + for line in open(".lock-wafbuild", "rt"): + if line.startswith("out_dir ="): + key, val = line.split('=') + out_dir = eval(val.strip()) + global NS3_BUILDDIR + NS3_BUILDDIR = out_dir + for line in open("%s/c4che/_cache.py" % out_dir).readlines(): for item in interesting_config_items: if line.startswith(item): exec(line, globals()) @@ -555,7 +542,7 @@ def make_paths(): if key == "PYTHONPATH": have_PYTHONPATH = True - pypath = os.environ["PYTHONPATH"] = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, "bindings", "python") + pypath = os.environ["PYTHONPATH"] = os.path.join (NS3_BUILDDIR, "bindings", "python") if not have_PYTHONPATH: os.environ["PYTHONPATH"] = pypath @@ -684,7 +671,7 @@ def run_job_synchronously(shell_command, directory, valgrind, is_python, build_p if len(build_path): path_cmd = os.path.join (build_path, shell_command) else: - path_cmd = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, shell_command) + path_cmd = os.path.join (NS3_BUILDDIR, shell_command) if valgrind: cmd = "valgrind --suppressions=%s --leak-check=full --show-reachable=yes --error-exitcode=2 %s" % (suppressions_path, @@ -991,12 +978,11 @@ def run_tests(): # pieces of the system have been built. This will tell us what examples # are runnable. # - read_waf_active_variant() read_waf_config() make_paths() # Get the information from the build status file. - build_status_file = os.path.join (NS3_BUILDDIR, NS3_ACTIVE_VARIANT, 'build-status.py') + build_status_file = os.path.join (NS3_BUILDDIR, 'build-status.py') if os.path.exists(build_status_file): ns3_runnable_programs = get_list_from_file(build_status_file, "ns3_runnable_programs") ns3_runnable_scripts = get_list_from_file(build_status_file, "ns3_runnable_scripts") @@ -1013,7 +999,7 @@ def run_tests(): # Set the directories and paths for this example. example_directory = os.path.join("examples", directory) examples_to_run_path = os.path.join(example_directory, "examples-to-run.py") - cpp_executable_dir = os.path.join(NS3_BUILDDIR, NS3_ACTIVE_VARIANT, example_directory) + cpp_executable_dir = os.path.join(NS3_BUILDDIR, example_directory) python_script_dir = os.path.join(example_directory) # Parse this example directory's file. @@ -1032,7 +1018,7 @@ def run_tests(): module_directory = os.path.join("src", module) example_directory = os.path.join(module_directory, "examples") examples_to_run_path = os.path.join(module_directory, "test", "examples-to-run.py") - cpp_executable_dir = os.path.join(NS3_BUILDDIR, NS3_ACTIVE_VARIANT, example_directory) + cpp_executable_dir = os.path.join(NS3_BUILDDIR, example_directory) python_script_dir = os.path.join(example_directory) # Parse this module's file. diff --git a/waf-tools/cflags.py b/waf-tools/cflags.py index 1738c88f9..cf9c93c46 100644 --- a/waf-tools/cflags.py +++ b/waf-tools/cflags.py @@ -144,7 +144,7 @@ profiles = { default_profile = 'default' -def set_options(opt): +def options(opt): assert default_profile in profiles opt.add_option('-d', '--build-profile', action='store', @@ -157,7 +157,7 @@ def set_options(opt): choices=profiles.keys(), dest='build_profile') -def detect(conf): +def configure(conf): cc = conf.env['COMPILER_CC'] or None cxx = conf.env['COMPILER_CXX'] or None if not (cc or cxx): diff --git a/wscript b/wscript index ce38fc0fc..8801483c6 100644 --- a/wscript +++ b/wscript @@ -73,8 +73,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) @@ -525,23 +525,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): @@ -561,6 +558,8 @@ class SuidBuildTask(Task.TaskBase): return Task.RUN_ME def create_suid_program(bld, name): + 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() @@ -568,7 +567,9 @@ def create_suid_program(bld, name): program.target = name if bld.env['ENABLE_SUDO']: - SuidBuildTask(bld, program) + program.create_task("SuidBuild") + + bld.set_group(grp) return program @@ -632,61 +633,29 @@ def _add_ns3_program_missing_deps(bld, program): program.env.append_value('LINKFLAGS', '-Wl,-Bdynamic,--no-whole-archive') -from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext -class Ns3BuildContext(BuildContext): - cmd = 'build' - #variant = 'debug' # FIXME +def _get_all_task_gen(self): + for group in self.groups: + for taskgen in group: + yield taskgen - # @property - # def variant(self): - # if not self.all_envs: - # self.load_envs() - # return self.all_envs[''].NS3_ACTIVE_VARIANT - def get_all_task_gen(self): - for group in self.groups: - for taskgen in group: - yield taskgen - all_task_gen = property(get_all_task_gen) - - def get_taskgen(self, name): - for group in self.groups: - for taskgen in group: - if taskgen.name == name: - return taskgen - raise KeyError(name) - - def exclude_taskgen(self, 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... - for group in self.groups: - for tg1 in group: - if tg1 is taskgen: - group.remove(tg1) - break - else: - continue - break +# 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): - - - # switch to the variant matching our debug level - #variant_name = bld.env['NS3_ACTIVE_VARIANT'] - #print variant_name - #bld.variant = variant_name - #variant_env = bld.env_of_name(variant_name) - #bld.all_envs['default'] = variant_env - env = bld.env - #bld.variant = bld.env.NS3_ACTIVE_VARIANT - #bld.init_dirs() - #env = bld.env - #print "-----------------------------------------------------------------------" - #print env # If --enabled-modules option was given, then print a warning # message and exit this function. @@ -711,12 +680,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) + 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']: @@ -728,7 +697,7 @@ 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. @@ -758,7 +727,7 @@ def build(bld): 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 @@ -787,7 +756,7 @@ def build(bld): 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 @@ -823,7 +792,7 @@ def build(bld): # 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) + gen = bld.get_tgen_by_name(module) if type(gen).__name__ in ['ns3module_taskgen']: gen.post() for lib in gen.libs: