src/create-module.py
author Tom Henderson <tomh@tomh.org>
Tue, 22 May 2012 21:41:55 -0700
changeset 8792 8f15de62d18e
parent 7882 158f38cfe101
child 8836 a2fa1888133d
permissions -rwxr-xr-x
fix some logging code for optimized builds

#! /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))