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