diff --git a/.hgignore b/.hgignore index 58c9dc78f..d5b25104e 100644 --- a/.hgignore +++ b/.hgignore @@ -2,6 +2,8 @@ .*\.o$ .*~$ build-dir +build .*\.sconsign doc/html.* doc/latex.* +.lock-wscript diff --git a/ns3/_placeholder_ b/ns3/_placeholder_ new file mode 100644 index 000000000..67cc5baa2 --- /dev/null +++ b/ns3/_placeholder_ @@ -0,0 +1 @@ +This is a placeholder file used only to keep the ns3 directory present (needed for the WAF build system). diff --git a/samples/wscript b/samples/wscript new file mode 100644 index 000000000..deda03941 --- /dev/null +++ b/samples/wscript @@ -0,0 +1,30 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import Params + +def build(bld): + def create_ns_prog(name, source, deps=['core', 'common', 'simulator']): + obj = bld.create_obj('cpp', 'program') + obj.target = name + obj.uselib_local = ' '.join(["ns3-%s" % dep for dep in deps]) + obj.source = source + for module in deps: + obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,)) + return obj + + obj = create_ns_prog('main-callback', 'main-callback.cc') + obj = create_ns_prog('main-simulator', 'main-simulator.cc') + obj = create_ns_prog('main-packet', 'main-packet.cc') + #obj = create_ns_prog('main-trace', 'main-trace.cc') + obj = create_ns_prog('main-test', 'main-test.cc') + obj = create_ns_prog('main-ptr', 'main-ptr.cc') + + #obj = create_ns_prog('main-p2p-net-device-if', 'main-p2p-net-device-if.cc', + # deps=['core', 'common', 'simulator', 'node', 'p2p']) + + obj = create_ns_prog('main-simple', 'main-simple.cc', + deps=['core', 'common', 'simulator', + 'node', 'internet-node', 'applications']) + + #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', + # deps=['core', 'common', 'simulator', 'node', 'p2p']) + diff --git a/src/applications/wscript b/src/applications/wscript new file mode 100644 index 000000000..5c7591ca5 --- /dev/null +++ b/src/applications/wscript @@ -0,0 +1,20 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_obj('cpp', 'shlib') + obj.name = 'ns3-applications' + obj.target = obj.name + obj.deps = ['ns3-node'] + obj.source = [ + 'application-list.cc', + 'application.cc', + 'onoff-application.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'application-list.h', + 'application.h', + 'onoff-application.h', + ] diff --git a/src/common/wscript b/src/common/wscript new file mode 100644 index 000000000..8120e772d --- /dev/null +++ b/src/common/wscript @@ -0,0 +1,49 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + common = bld.create_obj('cpp', 'shlib') + common.name = 'ns3-common' + common.target = common.name + common.deps = ['ns3-core', 'ns3-simulator'] + common.source = [ + 'buffer.cc', + 'header.cc', + 'chunk.cc', + 'trailer.cc', + 'packet.cc', + 'tags.cc', + 'pcap-writer.cc', + 'variable-tracer-test.cc', + 'trace-context.cc', + 'trace-resolver.cc', + 'callback-trace-source.cc', + 'empty-trace-resolver.cc', + 'composite-trace-resolver.cc', + 'trace-root.cc', + 'data-rate.cc', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'buffer.h', + 'header.h', + 'chunk.h', + 'trailer.h', + 'tags.h', + 'packet.h', + 'uv-trace-source.h', + 'sv-trace-source.h', + 'fv-trace-source.h', + 'pcap-writer.h', + 'callback-trace-source.h', + 'trace-context.h', + 'trace-resolver.h', + 'empty-trace-resolver.h', + 'composite-trace-resolver.h', + 'array-trace-resolver.h', + 'trace-root.h', + 'terminal-trace-resolver.h', + 'smartvector.h', + 'smartset.h', + 'data-rate.h', + ] diff --git a/src/core/wscript b/src/core/wscript new file mode 100644 index 000000000..fdd95507b --- /dev/null +++ b/src/core/wscript @@ -0,0 +1,74 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys + + +def configure(conf): + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdlib.h' + e.define = 'HAVE_STDLIB_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdlib.h' + e.define = 'HAVE_GETENV' + e.run() + + conf.write_config_header('ns3/core-config.h') + + + +def build(bld): + core = bld.create_obj('cpp', 'shlib') + core.name = 'ns3-core' + core.target = core.name + core.deps = 'ns3-core-headers' + core.source = [ + 'reference-list-test.cc', + 'callback-test.cc', + 'debug.cc', + 'assert.cc', + 'ptr.cc', + 'object.cc', + 'test.cc', + 'random-variable.cc', + 'rng-stream.cc', + 'ns-unknown.cc', + 'uid-manager.cc', + 'default-value.cc', + 'command-line.cc', + 'type-name.cc', + 'ns-unknown-manager.cc', + ] + + if sys.platform == 'win32': + core.source.extend([ + 'win32-system-wall-clock-ms.cc', + ]) + else: + core.source.extend([ + 'unix-system-wall-clock-ms.cc', + ]) + + headers = bld.create_obj('ns3header') + headers.name = 'ns3-core-headers' + headers.source = [ + 'system-wall-clock-ms.h', + 'reference-list.h', + 'callback.h', + 'ptr.h', + 'object.h', + 'debug.h', + 'assert.h', + 'fatal-error.h', + 'test.h', + 'random-variable.h', + 'rng-stream.h', + 'ns-unknown.h', + 'default-value.h', + 'command-line.h', + 'type-name.h', + 'ns-unknown-manager.h', + ] + diff --git a/src/devices/p2p-gfr/wscript b/src/devices/p2p-gfr/wscript new file mode 100644 index 000000000..8b92512bf --- /dev/null +++ b/src/devices/p2p-gfr/wscript @@ -0,0 +1,23 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + p2p = bld.create_obj('cpp', 'objects') + p2p.name = 'ns3-p2p-gfr' + p2p.source = [ + 'p2p-net-device.cc', + 'p2p-channel.cc', + 'p2p-topology.cc', + 'p2p-phy.cc', + 'layer-connector.cc', + ] + headers = bld.create_obj('ns3header') + headers.name = 'ns3-p2p-gfr-headers' + headers.source = [ + 'p2p-net-device.h', + 'p2p-channel.h', + 'p2p-topology.h', + 'p2p-phy.h', + 'layer-connector.h', + ] + diff --git a/src/devices/p2p/wscript b/src/devices/p2p/wscript new file mode 100644 index 000000000..528594085 --- /dev/null +++ b/src/devices/p2p/wscript @@ -0,0 +1,18 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + p2p = bld.create_obj('cpp', 'shlib') + p2p.name = 'ns3-p2p' + p2p.target = p2p.name + p2p.deps = ['ns3-node'] + p2p.source = [ + 'p2p-net-device.cc', + 'p2p-channel.cc', + ] + headers = bld.create_obj('ns3header') + headers.source = [ + 'p2p-net-device.h', + 'p2p-channel.h', + ] + diff --git a/src/devices/wscript b/src/devices/wscript new file mode 100644 index 000000000..e8c8a659e --- /dev/null +++ b/src/devices/wscript @@ -0,0 +1,6 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + bld.add_subdirs('p2p') + #bld.add_subdirs('p2p-gfr') + diff --git a/src/internet-node/wscript b/src/internet-node/wscript new file mode 100644 index 000000000..baeaaef87 --- /dev/null +++ b/src/internet-node/wscript @@ -0,0 +1,43 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_obj('cpp', 'shlib') + obj.name = 'ns3-internet-node' + obj.target = obj.name + obj.deps = ['ns3-node', 'ns3-applications'] + obj.source = [ + 'internet-node.cc', + 'l3-demux.cc', + 'l3-protocol.cc', + 'ipv4-l4-demux.cc', + 'ipv4-l4-protocol.cc', + 'ipv4-header.cc', + 'udp-header.cc', + 'ipv4-checksum.cc', + 'ipv4-interface.cc', + 'ipv4.cc', + 'ipv4-end-point.cc', + 'udp.cc', + 'arp-header.cc', + 'arp-cache.cc', + 'arp-ipv4-interface.cc', + 'arp.cc', + 'ipv4-loopback-interface.cc', + 'header-utils.cc', + 'udp-socket.cc', + 'ipv4-end-point-demux.cc', + 'i-udp-impl.cc', + 'i-arp-private.cc', + 'i-ipv4-impl.cc', + 'i-ipv4-private.cc', + 'ascii-trace.cc', + 'pcap-trace.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'internet-node.h', + 'ascii-trace.h', + 'pcap-trace.h', + ] diff --git a/src/node/wscript b/src/node/wscript new file mode 100644 index 000000000..d3f0c5bfc --- /dev/null +++ b/src/node/wscript @@ -0,0 +1,40 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + node = bld.create_obj('cpp', 'shlib') + node.name = 'ns3-node' + node.target = node.name + node.deps = ['ns3-core', 'ns3-common', 'ns3-simulator'] + node.source = [ + 'node.cc', + 'ipv4-address.cc', + 'net-device.cc', + 'mac-address.cc', + 'llc-snap-header.cc', + 'ipv4-route.cc', + 'queue.cc', + 'drop-tail.cc', + 'channel.cc', + 'node-list.cc', + 'socket.cc', + 'i-udp.cc', + 'i-ipv4.cc', + ] + + headers = bld.create_obj('ns3header') + headers.source = [ + 'node.h', + 'ipv4-address.h', + 'net-device.h', + 'mac-address.h', + 'ipv4-route.h', + 'queue.h', + 'drop-tail.h', + 'llc-snap-header.h', + 'channel.h', + 'node-list.h', + 'socket.h', + 'i-udp.h', + 'i-ipv4.h', + ] diff --git a/src/simulator/wscript b/src/simulator/wscript new file mode 100644 index 000000000..4bf989b44 --- /dev/null +++ b/src/simulator/wscript @@ -0,0 +1,95 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys + +import Params + + +def set_options(opt): + opt.add_option('--high-precision-as-double', + help=('Whether to use a double floating point' + ' type for high precision time values'), + action="store_true", default=False, + dest='high_precision_as_double') + + +def configure(conf): + if Params.g_options.high_precision_as_double: + conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1) + conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1 + highprec = 'long double' + else: + conf.env['USE_HIGH_PRECISION_DOUBLE'] = 0 + highprec = '128-bit integer' + conf.check_message_custom('high precision time', 'implementation', highprec) + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'stdint.h' + e.define = 'HAVE_STDINT_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'inttypes.h' + e.define = 'HAVE_INTTYPES_H' + e.run() + + e = conf.create_header_configurator() + e.mandatory = False + e.name = 'sys/inttypes.h' + e.define = 'HAVE_SYS_INT_TYPES_H' + e.run() + + conf.write_config_header('ns3/simulator-config.h') + + + +def build(bld): + sim = bld.create_obj('cpp', 'shlib') + sim.name = 'ns3-simulator' + sim.target = sim.name + sim.deps = 'ns3-simulator-headers ns3-core-headers' + + sim.source = [ + 'high-precision.cc', + 'time.cc', + 'event-id.cc', + 'scheduler.cc', + 'scheduler-factory.cc', + 'scheduler-list.cc', + 'scheduler-heap.cc', + 'scheduler-map.cc', + 'event-impl.cc', + 'simulator.cc', + ] + headers = bld.create_obj('ns3header') + headers.name = 'ns3-simulator-headers' + headers.source = [ + 'high-precision.h', + 'nstime.h', + 'event-id.h', + 'event-impl.h', + 'simulator.h', + 'scheduler.h', + 'scheduler-factory.h', + 'simulation-singleton.h', + ] + + env = bld.env_of_name('default') + if env['USE_HIGH_PRECISION_DOUBLE']: + sim.source.extend([ + 'high-precision-double.cc', + ]) + headers.source.extend([ + 'high-precision-double.h', + ]) + else: + sim.source.extend([ + 'high-precision-128.cc', + 'cairo-wideint.c', + ]) + headers.source.extend([ + 'high-precision-128.h', + 'cairo-wideint-private.h', + ]) + diff --git a/src/wscript b/src/wscript new file mode 100644 index 000000000..d47b86401 --- /dev/null +++ b/src/wscript @@ -0,0 +1,13 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def set_options(opt): + opt.sub_options('simulator') + +def configure(conf): + conf.sub_config('core') + conf.sub_config('simulator') + +def build(bld): + bld.add_subdirs('core common simulator') + bld.add_subdirs('node internet-node devices applications') + diff --git a/utils/wscript b/utils/wscript new file mode 100644 index 000000000..5b2e13e89 --- /dev/null +++ b/utils/wscript @@ -0,0 +1,25 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import sys +import Params + +def build(bld): + + def create_ns_prog(name, source): + obj = bld.create_obj('cpp', 'program') + obj.target = name + obj.deps = "ns3-core ns3-common ns3-simulator" + obj.uselib_local = "ns3-core ns3-common ns3-simulator" + obj.source = source + for module in ['core', 'common', 'simulator']: + obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,)) + return obj + + unit_tests = create_ns_prog('run-tests', 'run-tests.cc') + unit_tests.install_var = 0 #do not install + unit_tests.unit_test = 1 + + #if sys.platform != 'win32': + obj = create_ns_prog('bench-simulator', 'bench-simulator.cc') + obj = create_ns_prog('replay-simulation', 'replay-simulation.cc') + ## bench-packets requires missing header files + #obj = create_ns_prog('bench-packets', 'bench-packets.cc') diff --git a/wscript b/wscript new file mode 100644 index 000000000..f7dabf762 --- /dev/null +++ b/wscript @@ -0,0 +1,183 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- +import os + +import Params +import Object +import Action +import Common +import shutil +import subprocess + +Params.g_autoconfig = 1 + +# the following two variables are used by the target "waf dist" +VERSION = '3.0.1' +APPNAME = 'ns-3-waf' + +# these variables are mandatory ('/' are converted automatically) +srcdir = '.' +blddir = 'build' + +class Ns3Header(Object.genobj): + """A public NS-3 header file""" + def __init__(self, env=None): + Object.genobj.__init__(self, 'other') + self.inst_var = 'INCLUDEDIR' + self.inst_dir = 'ns3' + self.env = env + if not self.env: + self.env = Params.g_build.m_allenvs['default'] + + def apply(self): + ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3") + inputs = [] + outputs = [] + 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 + inputs.append(src_node) + outputs.append(dst_node) + task = self.create_task('ns3_headers', self.env, 1) + task.set_inputs(inputs) + task.set_outputs(outputs) + + def install(self): + 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, self.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): + try: + os.chmod(dst, 0600) + except OSError: + pass + shutil.copy2(src, dst) + ## make the headers in builddir read-only, to prevent + ## accidental modification + os.chmod(dst, 0400) + return 0 + +def init(): + Object.register('ns3header', Ns3Header) + Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE') + +def set_options(opt): + # options provided by the modules + if not opt.tool_options('msvc'): + opt.tool_options('g++') + + opt.add_option('--enable-gcov', + help=('Enable code coverage analysis'), + action="store_true", default=False, + dest='enable_gcov') + + opt.add_option('--lcov-report', + help=('Generate a code coverage report ' + '(use this option at build time, not in configure)'), + action="store_true", default=False, + dest='lcov_report') + + opt.add_option('--doxygen', + help=('Run doxygen to generate html documentation from source comments'), + action="store_true", default=False, + dest='doxygen') + + # options provided in a script in a subdirectory named "src" + opt.sub_options('src') + + +def configure(conf): + if not conf.check_tool('msvc'): + if not conf.check_tool('g++'): + Params.fatal("No suitable compiler found") + + + # create the second environment, set the variant and set its name + variant_env = conf.env.copy() + variant_name = Params.g_options.debug_level.lower() + + if Params.g_options.enable_gcov: + variant_name += '-gcov' + variant_env.append_value('CCFLAGS', '-fprofile-arcs') + variant_env.append_value('CCFLAGS', '-ftest-coverage') + variant_env.append_value('CXXFLAGS', '-fprofile-arcs') + variant_env.append_value('CXXFLAGS', '-ftest-coverage') + variant_env.append_value('LINKFLAGS', '-fprofile-arcs') + + conf.env['NS3_ACTIVE_VARIANT'] = variant_name + variant_env['NS3_ACTIVE_VARIANT'] = variant_name + variant_env.set_variant(variant_name) + conf.set_env_name(variant_name, variant_env) + conf.setenv(variant_name) + + variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS') + if 'debug' in Params.g_options.debug_level.lower(): + variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE') + variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE') + + conf.sub_config('src') + + +def build(bld): + variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT'] + variant_env = bld.env_of_name(variant_name) + bld.m_allenvs['default'] = variant_env # switch to the active variant + # process subfolders from here + bld.add_subdirs('src') + bld.add_subdirs('samples utils') + + +def shutdown(): + import UnitTest + ut = UnitTest.unit_test() + ut.change_to_testfile_dir = True + ut.want_to_see_test_output = True + ut.want_to_see_test_error = True + ut.run() + #ut.print_results() + + if Params.g_options.lcov_report: + env = Params.g_build.env_of_name('default') + variant_name = env['NS3_ACTIVE_VARIANT'] + + if 'gcov' not in variant_name: + Params.fatal("project not configured for code coverage;" + " reconfigure with --enable-gcov") + + os.chdir(blddir) + try: + lcov_report_dir = os.path.join(variant_name, 'lcov-report') + create_dir_command = "rm -rf " + lcov_report_dir + create_dir_command += " && mkdir " + lcov_report_dir + ";" + + if subprocess.Popen(create_dir_command, shell=True).wait(): + raise SystemExit(1) + + info_file = os.path.join(lcov_report_dir, variant_name + '.info') + lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file + lcov_command += " --source-dirs=" + os.getcwd() + lcov_command += ":" + os.path.join( + os.getcwd(), variant_name, 'include') + if subprocess.Popen(lcov_command, shell=True).wait(): + raise SystemExit(1) + + genhtml_command = "../utils/lcov/genhtml -o " + lcov_report_dir + genhtml_command += " " + info_file + if subprocess.Popen(genhtml_command, shell=True).wait(): + raise SystemExit(1) + finally: + os.chdir("..") + + if Params.g_options.doxygen: + doxygen_config = os.path.join('doc', 'doxygen.conf') + if subprocess.Popen(['doxygen', doxygen_config]).wait(): + raise SystemExit(1) +