author Gustavo J. A. M. Carneiro <>
Fri, 11 Jul 2008 18:39:19 +0100
changeset 3416 926ccb845111
parent 3260 8c0ab08144e6
child 3439 a64d1da0d6bf
permissions -rw-r--r--
Rescan APIs

## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-

import os, os.path
import shutil
import types

import Action
import Common
import Object
import Params

all_modules = (

def set_options(opt):

                   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)

                   help=("Build only these modules (and dependencies)"),

def configure(conf):

    blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
    conf.env['NS3_MODULE_PATH'] = [blddir]
    if Params.g_options.enable_rpath:
        conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),))

    ## Used to link the 'run-tests' program with all of ns-3 code
    conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]

def create_ns3_module(bld, name, dependencies=()):
    module = bld.create_obj('cpp', 'objects') = 'ns3-' + name =
    module.add_objects = ['ns3-' + dep for dep in dependencies]
    module.module_deps = list(dependencies)
    module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
    module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
    return module

def build(bld):
    #Object.register('ns3header', Ns3Header)
    Action.Action('ns3header', func=_ns3_headers_inst, color='BLUE')
    #Object.register('ns3-module-header', Ns3ModuleHeader)
    Action.Action('gen-ns3-module-header', func=gen_ns3_module_header, color='BLUE')
    bld.create_ns3_module = types.MethodType(create_ns3_module, bld)

    for module in all_modules:
        modheader = bld.create_obj('ns3moduleheader')
        modheader.module = module.split('/')[-1]

class ns3header_taskgen(Object.task_gen):
    """A set of NS-3 header files"""
    def __init__(self, *features):
        Object.task_gen.__init__(self, *features)
        self.inst_var = 'INCLUDEDIR'
        self.inst_dir = 'ns3'
        self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h
        self.module = None # module name

    def apply(self):
        if self.module is None:
            Params.fatal("'module' missing on ns3headers object %s" % self)
        ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
        if self.sub_dir is not None:
            ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
        for filename in self.to_list(self.source):
            src_node = self.path.find_source(filename)
            if src_node is None:
                Params.fatal("source ns3 header file %s not found" % (filename,))
            dst_node = ns3_dir_node.find_build(os.path.basename(filename))
            assert dst_node is not None
            task = self.create_task('ns3header', self.env, 1)

    def install(self):
        if self.sub_dir is None:
            inst_dir = self.inst_dir
            inst_dir = os.path.join(self.inst_dir, self.sub_dir)
        for i in self.m_tasks:
            current = Params.g_build.m_curdirnode
            lst = map(lambda a: a.relpath_gen(current), i.m_outputs)
            Common.install_files(self.inst_var, inst_dir, lst)

def _ns3_headers_inst(task):
    assert len(task.m_inputs) == len(task.m_outputs)
    inputs = [node.srcpath(task.m_env) for node in task.m_inputs]
    outputs = [node.bldpath(task.m_env) for node in task.m_outputs]
    for src, dst in zip(inputs, outputs):
            os.chmod(dst, 0600)
        except OSError:
        shutil.copy2(src, dst)
        ## make the headers in builddir read-only, to prevent
        ## accidental modification
        os.chmod(dst, 0400)
    return 0

def gen_ns3_module_header(task):
    assert len(task.m_outputs) == 1
    header_files = [os.path.basename(node.abspath(task.m_env)) for node in task.m_inputs]
    outfile = file(task.m_outputs[0].bldpath(task.m_env), "w")

    print >> outfile, """
# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."

#ifndef NS3_MODULE_%s
""" % (task.module.upper().replace('-', '_'),)

#     if task.module_deps:
#         print >> outfile, "// Module dependencies:"
#     for dep in task.module_deps:
#         print >> outfile, "#include \"%s-module.h\"" % dep

    print >> outfile
    print >> outfile, "// Module headers:"
    for header in header_files:
        print >> outfile, "#include \"%s\"" % (header,)

    print >> outfile, "#endif"

    return 0

class ns3moduleheader_taskgen(Object.task_gen):
    Generates a 'ns3/foo-module.h' header file that includes all
    public ns3 headers of a certain module.
    def __init__(self, *features):
        Object.task_gen.__init__(self, *features)
        self.module_name = None

    def apply(self):
        ## get all of the ns3 headers
        ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
        all_headers_inputs = []
        for ns3headers in Object.g_allobjs:
            if isinstance(ns3headers, ns3header_taskgen):
                if ns3headers.module != self.module:
                for source in ns3headers.to_list(ns3headers.source):
                    source = os.path.basename(source)
                    node = ns3_dir_node.find_build(os.path.basename(source))
                    if node is None:
                        fatal("missing header file %s" % (source,))
        assert all_headers_inputs
        module_obj = Object.name_to_obj("ns3-" + self.module)
        assert module_obj is not None
        all_headers_outputs = [ns3_dir_node.find_build("%s-module.h" % self.module)]
        task = self.create_task('gen-ns3-module-header', self.env, 4)
        task.module = self.module
        task.module_deps = module_obj.module_deps

    def install(self):