#! /usr/bin/env python
import sys
from optparse import OptionParser
import os
WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
# def options(opt):
# pass
# def configure(conf):
# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H')
def build(bld):
module = bld.create_ns3_module(%(MODULE)r, ['core'])
module.source = [
'model/%(MODULE)s.cc',
'helper/%(MODULE)s-helper.cc',
]
module_test = bld.create_ns3_module_test_library('%(MODULE)s')
module_test.source = [
'test/%(MODULE)s-test-suite.cc',
]
headers = bld.new_task_gen(features=['ns3header'])
headers.module = %(MODULE)r
headers.source = [
'model/%(MODULE)s.h',
'helper/%(MODULE)s-helper.h',
]
if bld.env.ENABLE_EXAMPLES:
bld.add_subdirs('examples')
# bld.ns3_python_bindings()
'''
MODEL_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "%(MODULE)s.h"
namespace ns3 {
/* ... */
}
'''
MODEL_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef %(INCLUDE_GUARD)s
#define %(INCLUDE_GUARD)s
namespace ns3 {
/* ... */
}
#endif /* %(INCLUDE_GUARD)s */
'''
HELPER_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "%(MODULE)s-helper.h"
namespace ns3 {
/* ... */
}
'''
HELPER_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef %(INCLUDE_GUARD)s
#define %(INCLUDE_GUARD)s
#include "ns3/%(MODULE)s.h"
namespace ns3 {
/* ... */
}
#endif /* %(INCLUDE_GUARD)s */
'''
EXAMPLES_WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
obj = bld.create_ns3_program('%(MODULE)s-example', [%(MODULE)r])
obj.source = '%(MODULE)s-example.cc'
'''
EXAMPLE_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/core-module.h"
#include "ns3/%(MODULE)s-helper.h"
using namespace ns3;
int
main (int argc, char *argv[])
{
bool verbose = true;
CommandLine cmd;
cmd.AddValue ("verbose", "Tell application to log if true", verbose);
cmd.Parse (argc,argv);
/* ... */
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
'''
TEST_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
// Include a header file from your module to test.
#include "ns3/%(MODULE)s.h"
// An essential include is test.h
#include "ns3/test.h"
// Do not put your test classes in namespace ns3. You may find it useful
// to use the using directive to access the ns3 namespace directly
using namespace ns3;
// This is an example TestCase.
class %(CAPITALIZED)sTestCase1 : public TestCase
{
public:
%(CAPITALIZED)sTestCase1 ();
virtual ~%(CAPITALIZED)sTestCase1 ();
private:
virtual void DoRun (void);
};
// Add some help text to this case to describe what it is intended to test
%(CAPITALIZED)sTestCase1::%(CAPITALIZED)sTestCase1 ()
: TestCase ("%(CAPITALIZED)s test case (does nothing)")
{
}
// This destructor does nothing but we include it as a reminder that
// the test case should clean up after itself
%(CAPITALIZED)sTestCase1::~%(CAPITALIZED)sTestCase1 ()
{
}
//
// This method is the pure virtual method from class TestCase that every
// TestCase must implement
//
void
%(CAPITALIZED)sTestCase1::DoRun (void)
{
// A wide variety of test macros are available in src/core/test.h
NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
// Use this one for floating point comparisons
NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
}
// The TestSuite class names the TestSuite, identifies what type of TestSuite,
// and enables the TestCases to be run. Typically, only the constructor for
// this class must be defined
//
class %(CAPITALIZED)sTestSuite : public TestSuite
{
public:
%(CAPITALIZED)sTestSuite ();
};
%(CAPITALIZED)sTestSuite::%(CAPITALIZED)sTestSuite ()
: TestSuite ("%(MODULE)s", UNIT)
{
AddTestCase (new %(CAPITALIZED)sTestCase1);
}
// Do not forget to allocate an instance of this TestSuite
static %(CAPITALIZED)sTestSuite %(MODULE)sTestSuite;
'''
DOC_RST_TEMPLATE = '''Example Module Documentation
----------------------------
.. heading hierarchy:
------------- Chapter
************* Section (#.#)
============= Subsection (#.#.#)
############# Paragraph (no number)
This is a suggested outline for adding new module documentation to ns-3.
See ``src/click/doc/click.rst`` for an example.
The introductory paragraph is for describing what this code is trying to
model.
Model Description
*****************
The source code for the new module lives in the directory ``src/%(MODULE)s``.
Design
======
Add here an overall description of the software design and how it fits
into the existing ns-3 architecture.
Scope and Limitations
=====================
What can the model do? What can it not do? Please use this section to
describe the scope and limitations of the model.
References
==========
Add academic citations here, such as if you published a paper on this
model, or if readers should read a particular specification or other work.
Usage
*****
This section is principally concerned with the usage of your model, using
the public API.
Building New Module
===================
Include this section if there are special build instructions.
Helper
======
What helper API will users typically use? Describe it here.
Advanced Usage
==============
Go into further details (such as using the API outside of the helpers)
in additional sections, as needed.
Examples
========
What examples using this new code are available? Describe them here.
Validation
**********
Describe how the model has been tested/validated. What tests run in the
test suite? How much API and code is covered by the tests? Again,
references to outside published work may help here.
'''
def main(argv):
parser = OptionParser(usage=("Usage: %prog [options] modulename\n"
"Utility script to create a basic template for a new ns-3 module"))
(options, args) = parser.parse_args()
if len(args) != 1:
parser.print_help()
return 1
modname = args[0]
assert os.path.sep not in modname
moduledir = os.path.join(os.path.dirname(__file__), modname)
if os.path.exists(moduledir):
print >> sys.stderr, "Module %r already exists" % (modname,)
return 2
os.mkdir(moduledir)
wscript = file(os.path.join(moduledir, "wscript"), "wt")
wscript.write(WSCRIPT_TEMPLATE % dict(MODULE=modname))
wscript.close()
#
# model
#
modeldir = os.path.join(moduledir, "model")
os.mkdir(modeldir)
model_cc = file(os.path.join(moduledir, "model", "%s.cc" % modname), "wt")
model_cc.write(MODEL_CC_TEMPLATE % dict(MODULE=modname))
model_cc.close()
model_h = file(os.path.join(moduledir, "model", "%s.h" % modname), "wt")
model_h.write(MODEL_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="__%s_H__" % (modname.upper()),))
model_h.close()
#
# test
#
testdir = os.path.join(moduledir, "test")
os.mkdir(testdir)
test_cc = file(os.path.join(moduledir, "test", "%s-test-suite.cc" % modname), "wt")
test_cc.write(TEST_CC_TEMPLATE % dict(MODULE=modname,CAPITALIZED=modname.capitalize()))
test_cc.close()
#
# helper
#
helperdir = os.path.join(moduledir, "helper")
os.mkdir(helperdir)
helper_cc = file(os.path.join(moduledir, "helper", "%s-helper.cc" % modname), "wt")
helper_cc.write(HELPER_CC_TEMPLATE % dict(MODULE=modname))
helper_cc.close()
helper_h = file(os.path.join(moduledir, "helper", "%s-helper.h" % modname), "wt")
helper_h.write(HELPER_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="__%s_HELPER_H__" % (modname.upper()),))
helper_h.close()
#
# examples
#
examplesdir = os.path.join(moduledir, "examples")
os.mkdir(examplesdir)
examples_wscript = file(os.path.join(examplesdir, "wscript"), "wt")
examples_wscript.write(EXAMPLES_WSCRIPT_TEMPLATE % dict(MODULE=modname))
examples_wscript.close()
example_cc = file(os.path.join(moduledir, "examples", "%s-example.cc" % modname), "wt")
example_cc.write(EXAMPLE_CC_TEMPLATE % dict(MODULE=modname))
example_cc.close()
#
# doc
#
docdir = os.path.join(moduledir, "doc")
os.mkdir(docdir)
doc_rst = file(os.path.join(moduledir, "doc", "%s.rst" % modname), "wt")
doc_rst.write(DOC_RST_TEMPLATE % dict(MODULE=modname))
doc_rst.close()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))