More waf 1.6.7 build fixes
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Mon, 12 Sep 2011 14:54:27 +0100
changeset 7488 72d0c878f3c7
parent 7487 82cd20da9650
child 7489 994360413f55
More waf 1.6.7 build fixes
bindings/python/wscript
src/click/wscript
src/core/wscript
src/internet/wscript
src/openflow/wscript
src/wscript
test.py
waf-tools/cflags.py
wscript
--- a/bindings/python/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/bindings/python/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -46,7 +46,7 @@
         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."),
--- a/src/click/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/src/click/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -4,7 +4,7 @@
 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)
--- a/src/core/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/src/core/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -3,7 +3,7 @@
 
 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'
--- a/src/internet/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/src/internet/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -11,7 +11,7 @@
 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'),
--- a/src/openflow/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/src/openflow/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -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')
--- a/src/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/src/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -6,6 +6,8 @@
 import types
 import warnings
 
+from waflib.Errors import WafError
+
 import TaskGen
 import Task
 import Options
@@ -65,7 +67,7 @@
     'template',
     ]
 
-def set_options(opt):
+def options(opt):
     opt.sub_options('core')
     opt.sub_options('click')
     opt.sub_options('openflow')
@@ -157,14 +159,42 @@
 #         # 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 @@
     module.ns3_dir_location = bld.path.relpath_gen(bld.srcnode)
 
     module.env.append_value("INCLUDES", '#')
+    
+    return module
 
-    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 @@
     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 @@
     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 @@
         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 @@
         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 @@
 
     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 @@
         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 @@
         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)]
--- a/test.py	Thu Sep 08 16:13:40 2011 +0100
+++ b/test.py	Mon Sep 12 14:54:27 2011 +0100
@@ -42,7 +42,6 @@
 # found in the associated subdirectory wscript files.
 #
 interesting_config_items = [
-    "NS3_BUILDDIR",
     "NS3_ENABLED_MODULES",
     "NS3_MODULE_PATH",
     "NSC_ENABLED",
@@ -483,24 +482,6 @@
     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 @@
 # 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 @@
         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 @@
         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 @@
     # 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 @@
         # 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 @@
         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.
--- a/waf-tools/cflags.py	Thu Sep 08 16:13:40 2011 +0100
+++ b/waf-tools/cflags.py	Mon Sep 12 14:54:27 2011 +0100
@@ -144,7 +144,7 @@
 
 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 @@
 		       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):
--- a/wscript	Thu Sep 08 16:13:40 2011 +0100
+++ b/wscript	Mon Sep 12 14:54:27 2011 +0100
@@ -73,8 +73,8 @@
     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 @@
             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 @@
             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 @@
     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 @@
             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 @@
     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 @@
         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 @@
         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 @@
                     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 @@
 
     # 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: