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