src/wscript
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 4541 e943b94bf523
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
     2 
     3 import os, os.path
     4 import shutil
     5 import types
     6 import warnings
     7 
     8 import TaskGen
     9 import Task
    10 import Options
    11 import Build
    12 import Utils
    13 
    14 all_modules = (
    15     'core',
    16     'common',
    17     'simulator',
    18     'contrib',
    19     'node',
    20     'internet-stack',
    21     'devices/point-to-point',
    22     'devices/csma',
    23     'devices/emu',
    24     'devices/bridge',
    25     'devices/tap-bridge',
    26     'devices/virtual-net-device',
    27     'applications/onoff',
    28     'applications/packet-sink',
    29     'applications/udp-echo',
    30     'routing/olsr',
    31     'routing/global-routing',
    32     'routing/static-routing',
    33     'routing/list-routing',
    34     'mobility',
    35     'devices/wifi',
    36     'helper',
    37     'contrib/stats',
    38     'applications/v4ping',
    39     )
    40 
    41 def set_options(opt):
    42     opt.sub_options('simulator')
    43 
    44     opt.add_option('--enable-rpath',
    45                    help=("Link programs with rpath"
    46                          " (normally not needed, see "
    47                          " --run and --shell; moreover, only works in some"
    48                          " specific platforms, such as Linux and Solaris)"),
    49                    action="store_true", dest='enable_rpath', default=False)
    50     
    51     opt.add_option('--enable-modules',
    52                    help=("Build only these modules (and dependencies)"),
    53                    dest='enable_modules')
    54 
    55 def configure(conf):
    56     conf.sub_config('core')
    57     conf.sub_config('simulator')
    58     conf.sub_config('devices/emu')
    59     conf.sub_config('devices/wifi')
    60     conf.sub_config('devices/tap-bridge')
    61     conf.sub_config('contrib')
    62     conf.sub_config('internet-stack')
    63 
    64     blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant()))
    65     conf.env.append_value('NS3_MODULE_PATH', blddir)
    66     if Options.options.enable_rpath:
    67         conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),))
    68 
    69     ## Used to link the 'run-tests' program with all of ns-3 code
    70     conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
    71 
    72 
    73 def create_ns3_module(bld, name, dependencies=()):
    74     module = bld.new_task_gen('cxx')
    75     module.name = 'ns3-' + name
    76     module.target = module.name
    77     module.add_objects = ['ns3-' + dep for dep in dependencies]
    78     module.module_deps = list(dependencies)
    79     if not module.env['ENABLE_STATIC_NS3']:
    80         module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
    81     elif module.env['CXX_NAME'] == 'gcc' and \
    82             os.uname()[4] == 'x86_64' and \
    83             module.env['ENABLE_PYTHON_BINDINGS']:
    84         # enable that flag for static builds only on x86-64 platforms
    85         # when gcc is present and only when we want python bindings
    86         # (it's more efficient to not use this option if we can avoid it)
    87         module.env.append_value('CXXFLAGS', '-mcmodel=large')
    88         
    89     module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
    90     return module
    91 
    92 def create_obj(bld, *args):
    93     warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_obj(...)" % str(bld.path),
    94                   DeprecationWarning, stacklevel=2)
    95     return bld.new_task_gen(*args)
    96 
    97 def build(bld):
    98     bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
    99     bld.create_obj = types.MethodType(create_obj, bld)
   100     
   101     bld.add_subdirs(list(all_modules))
   102 
   103     for module in all_modules:
   104         modheader = bld.new_task_gen('ns3moduleheader')
   105         modheader.module = module.split('/')[-1]
   106 
   107 
   108 class ns3header_taskgen(TaskGen.task_gen):
   109     """A set of NS-3 header files"""
   110     COLOR = 'BLUE'
   111     def __init__(self, *args, **kwargs):
   112         super(ns3header_taskgen, self).__init__(*args, **kwargs)
   113         self.install_path = None
   114         self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h
   115         self.module = None # module name
   116 
   117     def apply(self):
   118         if self.module is None:
   119             raise Utils.WafError("'module' missing on ns3headers object %s" % self)
   120         ns3_dir_node = self.bld.path.find_dir("ns3")
   121         if self.sub_dir is not None:
   122             ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
   123         for filename in self.to_list(self.source):
   124             src_node = self.path.find_resource(filename)
   125             if src_node is None:
   126                 raise Utils.WafError("source ns3 header file %s not found" % (filename,))
   127             dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename))
   128             assert dst_node is not None
   129             task = self.create_task('ns3header', self.env)
   130             task.set_inputs([src_node])
   131             task.set_outputs([dst_node])
   132 
   133 class ns3header_task(Task.Task):
   134     before = 'cc cxx gen_ns3_module_header_task'
   135     color = 'BLUE'
   136     def run(self):
   137         assert len(self.inputs) == len(self.outputs)
   138         inputs = [node.srcpath(self.env) for node in self.inputs]
   139         outputs = [node.bldpath(self.env) for node in self.outputs]
   140         for src, dst in zip(inputs, outputs):
   141             try:
   142                 os.chmod(dst, 0600)
   143             except OSError:
   144                 pass
   145             shutil.copy2(src, dst)
   146             ## make the headers in builddir read-only, to prevent
   147             ## accidental modification
   148             os.chmod(dst, 0400)
   149         return 0
   150 
   151 
   152 
   153 class gen_ns3_module_header_task(Task.Task):
   154     before = 'cc cxx'
   155     after = 'ns3header_task'
   156     color = 'BLUE'
   157     def run(self):
   158         assert len(self.outputs) == 1
   159         header_files = [os.path.basename(node.abspath(self.env)) for node in self.inputs]
   160         outfile = file(self.outputs[0].bldpath(self.env), "w")
   161         header_files.sort()
   162 
   163         print >> outfile, """
   164 #ifdef NS3_MODULE_COMPILATION
   165 # error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
   166 #endif
   167 
   168 #ifndef NS3_MODULE_%s
   169     """ % (self.module.upper().replace('-', '_'),)
   170 
   171     #     if self.module_deps:
   172     #         print >> outfile, "// Module dependencies:"
   173     #     for dep in self.module_deps:
   174     #         print >> outfile, "#include \"%s-module.h\"" % dep
   175 
   176         print >> outfile
   177         print >> outfile, "// Module headers:"
   178         for header in header_files:
   179             print >> outfile, "#include \"%s\"" % (header,)
   180 
   181         print >> outfile, "#endif"
   182 
   183         outfile.close()
   184         return 0
   185 
   186     def sig_explicit_deps(self):
   187         m = Utils.md5()
   188         m.update('\n'.join([node.abspath(self.env) for node in self.inputs]))
   189         return m.digest()
   190 
   191     def unique_id(self):
   192         try:
   193             return self.uid
   194         except AttributeError:
   195             "this is not a real hot zone, but we want to avoid surprizes here"
   196             m = Utils.md5()
   197             m.update("ns-3-module-header-%s" % self.module)
   198             self.uid = m.digest()
   199             return self.uid
   200 
   201 
   202 class ns3moduleheader_taskgen(TaskGen.task_gen):
   203     """
   204     Generates a 'ns3/foo-module.h' header file that includes all
   205     public ns3 headers of a certain module.
   206     """
   207     COLOR = 'BLUE'
   208     def __init__(self, *args, **kwargs):
   209         super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs)
   210 
   211     def apply(self):
   212         ## get all of the ns3 headers
   213         ns3_dir_node = self.bld.path.find_dir("ns3")
   214         all_headers_inputs = []
   215         for ns3headers in self.bld.all_task_gen:
   216             if isinstance(ns3headers, ns3header_taskgen):
   217                 if ns3headers.module != self.module:
   218                     continue
   219                 for source in ns3headers.to_list(ns3headers.source):
   220                     source = os.path.basename(source)
   221                     node = ns3_dir_node.find_or_declare(os.path.basename(source))
   222                     if node is None:
   223                         fatal("missing header file %s" % (source,))
   224                     all_headers_inputs.append(node)
   225         if not all_headers_inputs:
   226             raise Utils.WscriptError("error finding headers for module %s" % self.module)
   227         assert all_headers_inputs
   228         module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env)
   229         assert module_obj is not None
   230         all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
   231         task = self.create_task('gen_ns3_module_header', self.env)
   232         task.set_inputs(all_headers_inputs)
   233         task.set_outputs(all_headers_outputs)
   234         task.module = self.module
   235         task.module_deps = module_obj.module_deps
   236 
   237     def install(self):
   238         pass