README.developer
----------------

Developer Notes
---------------

* You need to have relatively new versions of autoconf and automake
    installed and available in your path.  We have tested with and
    recommend using autoconf-2.59 and automake-1.9.6.

* If you are working from a CVS checkout, keep the following in mind:

    - As general policy, files which are generated from other files
	should not be checked into CVS.

    - Because file generated by autoconf/automake are not checked in,
	these need to be created with every new CVS checkout.  To do this,
	run the script:
		Build/setup-developer
	in the top level source directory.

    - Before checking in, make sure copyright information is added to all
	source files.  This can be automatically done for all files of
	specific types (*.cpp, *.h, Makefile.am, *.dox (Doxygen input))
	found in the source tree.  Go to the top level source directory
	and run the script:
		Build/fix-copyright
	You should probably check to make sure the modifications made
	by this script are okay.  Backup copies are created for all
	modified files; these are named by appending a tilde (~) to the
	end of the original filename.

* If you are adding/editing a source file, try to remember to add an
    "Author" comment somewhere near the top, and use "Changelog"
    comments for major updates.

* Please be aware of where your code comes from.  Do not use code you
    are not licensed or authorized to use.  Be aware of copyrights.

-------------------------------------------------------------------------------

Coding Style Guidelines
-----------------------

OA Gear should generally follow the OpenAccess coding style guidelines
(see doc/oa/html/styleguide/index.html in the OA documentation).  The
following changes/clarifications should be noted:

- All OA Gear objects must reside in an appropriate C++ namespace:
	- Bazaar Objects: oagBazaar
	- Decision Diagram Objects: oagDd
	- Functional Representation Objects: oagFunc
	- Placement Objects: oagPlace
	- Redundancy Remover: oagRedun
	- Timer Objects: oagTimer
	- Tools Objects: oagTools
	- Utility Objects: oagUtil
    Change: Was unspecified in original OA guidelines.
    Rationale: This minimizes namespace collisions between packages.

- Each class in the oaGear namespace must reside in its own file, named
    using the naming convention from the original OA guidelines.
    Change: Was unspecified in original OA guidelines.
    Rationale: This allows code readers to find the right files easily.

- Inner classes and structs (i.e. nested classes within classes) are
    allowed.
    Change: Was prohibited in original OA guidelines.
    Rationale: If small helper classes were declared in the oaGear
    namespace, they would have to be given their own files (see previous
    guideline), cluttering up the namespace and directory.  This will
    allow such helper classes to reside in the file of their containing
    class.

- Tabs should not appear in code.
    Change: Was ambiguous in original OA guidelines.
    Rationale: Some editors use tabs for indentation.  As tabs can be
    represented by variable numbers of spaces, they should be avoided
    so that files may have a uniform appearance in any editor.

- Code must compile with no warnings using the g++ flags:
		-W -Wall -Wno-non-virtual-dtor -Wno-ctor-dtor-privacy
    Change: Was unspecified in original OA guidelines.
    Rationale: Compiler warnings are often signs of buggy or poorly
    written code.  The exceptions to -Wall avoid problems in OA itself.

- External APIs must be documented using Doxygen.  Doxygen markup for a
    class must appear in the .h file and not the .cpp file for that class.
    Change: Was unspecified in original OA guidelines.
    Rationale: Standardizing the location of Doxygen markup makes it easier
    to find it.

- Use C++ static_cast<> instead of traditional C casts.
    Change: Was unspecified in original OA guidelines.
    Rationale: This makes casting easier to find when reading code.

- Protect header files from multiple inclusion with the following:
    If the filename is oagFooBar.h, use
                #if !defined(oagFooBar_P)
		#define oagFooBar_P
		...
		#endif
    Change: Was ambiguous in original OA guidelines.
    Rationale: Header file protection should be standardized in order to
    avoid mistaken exclusion of unrelated headers.

- Lex files must be named with a .lxx suffix.  Yacc files must be named
    with a .ypp suffix.
    Change: Was unspecified in original OA guidelines.
    Rationale: Standard naming allows common Makefile stubs to be written.

-------------------------------------------------------------------------------

OA Gear Build System (new)
--------------------------

The build system uses a wrapper on top of the standard autoconf/automake
tools.  The purpose of wrapping autoconf/automake is to avoid duplicating
information between the various Makefile.am files throughout the build
tree and configure.ac.

Summery
-------

Before the different parts of the OAGear Build System are described in
detail, this should give a short abstract about the whole system.

In order to create a 'Makefile' for a new tool you have just added, you
will have to run 'Build/setup-developer'. This controls the process of
creating the 'Makefile' by using the tools 'metamake', 'automake' and 'autoconf'.
First 'metamake' generates 'configure.ac' and 'Makefile.am' from 'Makefile.mm',
which is the only file you will have to write. After that, 'automake'
creates 'Makefile.in' from 'Makefile.am' before 'autoconf' generates the
'configure' script from 'configure.ac' and 'Makefile.in'. After these
automated steps you can call configure with the options you need, which
creates the actual Makefile.


Makefile.mm
-----------

The files which control the build system are named "Makefile.mm".
Developers should not touch Makefile.am, as these are automatically
generated by the autoconf/automake wrapper.

Makefile.mm files contain zero or more lines of the form
    keyword [name1] [name2] ...
where keyword is a directive for the autoconf/automake wrapper which
controls the creation of the actual Makefiles, and the [names] are zero
or more arguments for the keyword.  More details on keywords and their
arguments can be found below.

Lines in Makefile.mm which start with the '#' character are ignored.
Blank lines are also ignored.  Note that backspace continuation (i.e.
terminating a line with a backspace to join multiple lines) is not
supported.

Packages
--------

The build system uses the notion of a "package".  A package is a
collection of related source files which compiles to a single target
(either a library or an executable program).  The one-to-one relation
between a package and a single target is strict;  to create more than
one executable, for example, one package per executable must be created.

Each package is associated with a directory.  All the source files for a
package must be contained in the package directory or its subdirectories.

Package directories may contain subdirectories which are themselves
associated with some other package.  Typically this is used to create
executable packages which are closely related to library packages;
the executable package directory becomes a subdirectory of the the
library package directory.

The name of a package is the same as the name of its associated directory.
Package names must be unique across OA Gear.

Each package must have a Makefile.mm in its associated directory which
controls the compilation of that package.

Library Packages
----------------

The Makefile.mm for a library package should start with the keyword
    type library
to indicate the type of the package.  This should be followed by one or
more lines of the form
    source [file1] [file2] ...
which list the source files to be included in the library.  *.cpp, *.h,
*.lxx and *.yxx files should be listed.  *.cxx and *.hxx files generated
by lex/yacc should not be listed.

If the package uses another package (i.e. requires header files from
another package) the keyword
    requires [packageName]
should be used.  If more than one package is required this keyword
can be repeated for each required package.  Note that the order that
the packages are listed is used to determine the order the libraries
are passed to the linker.  If package A requires packages B and C, and
package B requires package C in turn, then the Makefile.mm for package
A should list package B before package C.

If the package uses an external package the keyword
    external [externalPackageName]
should be used.  A list of the recognized external packages can be
found below.  If more than one external package is used, this keyword
should be repeated for each.

The name of the library file created for a library package is
lib[packageName].a, where [packageName] is the name of the package.

Program Packages
----------------

The Makefile.mm for a program package should start with the keyword
    type program
The source, requires and external keywords can be used as with library
packages.

The name of the executable created for a program package is the same
as the name of the package itself.

Unit Test Subdirectories
------------------------

Libraries should have subdirectories named "UnitTest".  These should
contain the files related to the unit tests for that library.  The
UnitTest subdirectory should contain a Makefile.mm which is identical
to that of a program package, but the type directive should instead be
    type unittest

Documentation Subdirectories
----------------------------

Libraries should have subdirectories named "Documentation".  These
should have a Makefile.mm where the type directive is
    type documentation

Additional directives of the form
    source [file1] [file2] ...
should be used to indicate *.fig files used for figures.

Currently Doxyfile.in is not automatically created;  this will have to
be created by hand (or copied from an existing Doxyfile.in and modified).

setup-developer
---------------

The setup-developer script in the Build/ directory should be run whenever
a Makefile.mm is deleted from or added to the source tree (changing
a directory's name or moving a directory can be considered a deletion
followed by an addition).  cd to the top level directory and execute
    Build/setup-developer
Note that ./configure should also be run after setup-developer.

If Makefile.mm files are simply edited, it is not necessary to rerun
setup-developer.  "make" will regenerate the appropriate files.

autoconf/automake Files
-----------------------

Normally developers should only need to edit Makefile.mm in the
appropriate (sub)directories.

Makefile.am is now generated automatically from Makefile.mm.
While hand-generated Makefile.am files are now deprecated, they may
still be used with the wrapper (and are still currently being used,
where conversion to the new Makefile.mm format has not been done yet).
Note that, in a directory which contains both Makefile.am and Makefile.mm,
Makefile.am should never be modified by hand, as any changes will be
overwritten by the automake wrapper.

Developers should never modify configure.ac by hand.  The autoconf wrapper
scans for subdirectories and modifies configure.ac automatically using
the template file Build/configure.mm.

-------------------------------------------------------------------------------

OA Gear Build System (deprecated)
---------------------------------

Information in this section is considered deprecated.  This section is
kept here only for reference purposes.

The build system for OA Gear uses autoconf and automake.  It may be
helpful to familiarize yourself with these tools before trying to add
a new package.

configure.ac
------------

Adding a new package or directory requires modification of the file
configure.ac in the top level directory.  configure.ac controls the
configuration process (what happens when the end-user runs ./configure).
Keep in mind configure.ac follows general POSIX shell syntax, with the
inclusion of M4 macros.  The file has several sections:

The "Compilation Features" section lists the internal OA Gear features
which the user may turn on/off at configuration time (just before
compiling OA Gear).  For example, if you have a new package named Foo
and want to add an option for its compilation, you will need to add some
lines which look like the following:

AC_ARG_ENABLE([foo], AC_HELP_STRING([--enable-foo],
    [build OA Gear Foo (default: yes)]),
    [test "$enable_foo" = "yes" || enable_foo=""],
    [enable_foo="yes"])

This defines a shell variable $enable_foo which is set to the empty string
"" if the user explicitly disables this feature with --disable-foo at
configure time, otherwise $enable_foo is set to "yes".

The "External Packages" section lists the external packages or libraries
which may be used by OA Gear.  This provides the user the ability
to specify where the external package is located at configure time.
For example, an external package named Bar could be specified as:

AC_ARG_WITH([bar], AC_HELP_STRING([--with-bar=DIR],
    [look for Bar in DIR (default: ../Bar)]), ,
    [with_bar="../Bar"])

This defines a shell variable $with_bar which is set to the path to the
Bar package.  The default value is "../Bar" if this is not explicitly
set by the user at configure time.

The "Fix Relative Paths" section adjusts the paths to the external
packages to be absolute paths, in case they are specified by the user
as relative paths.  If you've added an external package in the "External
packages" section you should add a path fix here which looks like:

case "$with_bar" in
    [[\\/]*|?:[\\/]*]) ;;
    *) with_bar="$PWD/$with_bar" ;;
esac

The "Check Configuration Consistency" section ensures that all
dependencies between the user configuration options from the "Compilation
features" section are satisfied.  POSIX shell code should be written
here to verify consistency, and the AC_MSG_ERROR() macro used if an
inconsistent configuration is discovered.

Each external package option should be explicitly checked for in its
own section in configure.ac.  These checks will need to be specifically
written for each package, but the "External Package: Check for TCL"
section can serve as a template as to how this should be done.
The external package check should be guarded with the $enable_check
variable and the $enable_foo variable, if the OA Gear Foo package is
the package which requires the external package, like this:

if test "$enable_check" ; then
    if test "$enable_foo" ; then
        # check here
    fi
fi

This prevents the external package from being checked if it is not
actually used because the user provided --disable-foo at configure time.

The "Set Automake Conditional Flags" section indicates the flags which
control what is enabled for compilation in the Makefiles.  For example,
to set a flag for the OA Gear Foo package to be compiled if OA Gear Foo
is enabled in the "Compilation Features" section:

AM_CONDITIONAL([OAG_COND_FOO], [test "$enable_foo"])

Then the Makefile can check this conditional flag to see if Foo should
be built or not.  In OA Gear conditional flags should be of the form
OAG_COND_* to avoid naming conflicts.

The "Construct Makefile Substitutions" section defines symbols to be
substituted in the final Makefiles.  For instance, the line

AC_SUBST([OAG_BAR], ["$with_bar"])

substitutes the value of the shell variable $with_bar (presumably set
in the "External Packages" section into the Makefile symbol @OAG_BAR@.
Note that with AC_SUBST(), if the second argument is omitted, the
shell variable with the same name as the first argument is used.
OA Gear Makefile substitutions should have the form OAG_* to avoid
naming conflicts.  Further, substitutions associated with a package
should also include the package name, e.g. OAG_TCL_LIBS.

The "Generate Output Files" section lists all the Makefiles which should
be generated.  If the new package requires a new Makefile, this should
be added here.

Makefile.am
-----------

Each directory contains a Makefile.am file which is eventually converted
to a usable Makefile.  Writing Makefile.am can be tricky, and reading
the automake documentation is highly recommended.  However, Makefile.am
can be written for simple packages by copying and modifying an existing
Makefile.am.

Bazaar Build System
-------------------

The Makefile.am for Bazaar has a somewhat different format.  As this
package uses QT, qmake is necessary to build the package.  There are
therefore two Makefiles.  The primary Makefile is generated from
Makefile.am through the normal automake process.  However, in this
Makefile.am the target "bazaar" has a special explicit rule:

bazaar$(EXEEXT): Makefile.qmake
	$(MAKE) -f $<

This says that make should use the file Makefile.qmake to build bazaar.
Makefile.qmake is generated by qmake from the source qmake.pro .
qmake.pro is written as an ordinary qmake file.

Both Makefile.am and qmake.pro require sharing of variables.  Variables
common to both (e.g. SOURCES_LOCAL) should be placed in the file named
build.variables .  This file is "include"d in both Makefile.am and
qmake.pro.  Values which come from Makefile substitutions generated at
configure time (see "Construct Makefile Substitutions" in configure.ac)
need to be "export"ed from Makefile.am so that they are available in
Makefile.qmake .

To ensure Makefile.qmake is rebuilt using qmake whenever its dependencies
have changed, a rule with target "Makefile.qmake" is added to Makefile.am.
Note that the dependencies for bazaar (SOURCES_LOCAL, etc.) are actually
listed as dependencies for Makefile.qmake.  This ensures that, should
the sources change to include a new dependency, Makefile.qmake is also
updated along with the normal automake dependency tracking.  This also
means the bazaar dependencies need not be explicitly listed in the rule
to make bazaar itself, since they are indirectly included through the
Makefile.qmake target rule.

-------------------------------------------------------------------------------

Documentation
-------------

Packages should have a subdirectory named "Documentation" to hold the output
from Doxygen.  Currently documentation is not automatically regenerated.  To
rebuild docs, cd into the Documentation directory and do "make doc".

When creating a Documentation directory, create Makefile.am and
Doxyfile.in .  These can be copied from an existing Documentation
directory and modified appropriately.  An additional file oagFoo.dox
(assuming the package is named OA Gear Foo) should also be added to the
Documentation subdirectory.  This file contains the documentation for
the package which is not specific to any particular class or function.
At the very least this should contain a copyright notice which is copied
into the Doxygen-generated documentation.

-------------------------------------------------------------------------------

Unit Testing
------------

Packages should have a subdirectory named "UnitTest" which contains the
unit tests for that package's classes.  Unit tests are classes derived
from the class oagUtil::UnitTest .  See the Doxygen documentation for
oagUtil::UnitTest for more information on how to create unit tests.

All the unit tests for a package should be called from main.cpp in
the UnitTest directory.  See the oagUtil::UnitTest documentation for
more details.

The UnitTest directory should contain a Makefile.am which builds an
executable named oagFooUnitTest (assuming the package is named OA
Gear Foo) from main.cpp .  The Makefile.am should set the variable
CPPFLAGS to add the Utility source directory, and set the variable
oagFooUnitTest_LDADD to add liboagUtil.a to the link, so that the compiler
and linker can properly find the class oagUtil::UnitTest.  See the file
Utility/UnitTest/Makefile.am for an example of how this is done.

Unit tests can be run by doing "make check" in the UnitTest directory.
"make check" in any parent directory will run all tests, descending
recursively into subdirectories.

-------------------------------------------------------------------------------

Regression Testing
------------------

Packages should have a subdirectory named "RegressionTest" which contains the
regression tests for that package's classes.  More information on regression
testing is forthcoming.

-------------------------------------------------------------------------------

Valgrind
--------

Even though all unit and regression tests might PASS, there could still be some
hidden ERRORS.  To identify these problems (e.g. memory allocation), it is often
helpful to run the regression tests with the debugging tool valgrind.

For further information: http://www.valgrind.org/docs/manual/quick-start.html

In order to use valgrind you can set the environment variable OAG_VALGRIND like
so:

(setenv OAG_VALGRIND "valgrind --trace-children=yes --quiet")
or
(export OAG_VALGRIND="valgrind --trace-children=yes --quiet")

Then run "make check" in the top-level directory or the subdirectory of
interest.  Valgrind tests all child processes and prints details about the
occurring ERRORS.

In the existing regression tests the variable OAG_VALGRIND is included in the
call to each test program.  If you have written a new OAGear tool, you should
test it with valgrind too.  It should look like this.

${OAG_VALGRIND} ./new_oag_test_program -options ...

Using valgrind increases the runtime of the regression tests by 20 to 30 times.

-------------------------------------------------------------------------------

gcov
----

For testing and verifying your program, it is very helpful to see how many
lines and which lines of your code are actually executed.  This can be done with
gcov.

http://gcc.gnu.org/onlinedocs/gcc/Gcov.html

As gcov cannot handle the shared libraries of the standard OAGear configuration,
you must reconfigure OAGear.  You can do this by calling "configure".
You can use the same options as it is done at the end of the bootstrap script, 
but you will have to change the library options as follows:

./configure --... \
            --disable-shared \
            --enable-static \
            --...

To run gcov, the project must be compiled with the gcc options "-fprofile-arcs"
and "-ftest-coverage".  The easiest way to do this, is to set the environment
variables CFLAGS and CXXFLAGS to these values.

(setenv CFLAGS "-fprofile-arcs -ftest-coverage")
(setenv CXXFLAGS "-fprofile-arcs -ftest-coverage")
or
(export CFLAGS='-fprofile-arcs -ftest-coverage')
(export CXXFLAGS='-fprofile-arcs -ftest-coverage')

After recompiling with "make", you should find several files with the endings
.bb and .bbg in your directories.  These are used by gcov to determine how
many times a line of code is executed.  Now, run the program, which will
create a file with the suffix "da".  This file contains information about 
how many times a line is executed.  This information is cumulated when you 
rerun the program.  You can now call gcov followed by the source file you 
are interested in.

Example from oagear:

  Step 1: compile

    $ make

  Step 2: run test

    $ cd MiniSat/RegressionTest/
    $ ./check-sat
 
  Step 3: view results

    $ cd ../sat_main/
    $ gcov sat_main.cpp  
              
             100.00% of 2 source lines executed in file ../../MiniSat/Solver.h
             Creating Solver.h.gcov.
             100.00% of 13 source lines executed in file ../../MiniSat/SolverTypes.h
             Creating SolverTypes.h.gcov.
             100.00% of 13 source lines executed in file ../../MiniSat/Vec.h
             Creating Vec.h.gcov.
             67.80% of 177 source lines executed in file sat_main.cpp
             Creating sat_main.cpp.gcov.


If step 3 is done in the directory of the source file, gcov generates a file
ending with .gcov for the specified file and every file which is included by
the file.  In these files annotated to each line is the number of times the
line has been executed.

Simplified example (example.c.gcov):

          main()
          {
     1      int i, total;                  //executed 1 time

     1      total = 0;

    11      for (i = 0; i < 10; i++)       //executed 11 times
    10        total += i;

     1      if (total != 45)
######        printf ("Failure\n");        //not executed
            else
     1        printf ("Success\n");
     1    }


Once you are done with checking your code coverage, please reconfigure oagear
with the shared libraries.

-------------------------------------------------------------------------------

Tools to format code
--------------------

There are a number of tools that can help format code to comply with the
coding standards.

indent
------

The utility "indent" should be available on most Linux systems.
This indents C code well, and C++ code to a limited extent.

"indent" has many options to control its behavior.  The file
"Build/indent-sources" (from CVS) is a shell script wrapper which sets the
options which most closely meet the OA style guidelines.  Alternatively,
you can instead create a file $(HOME)/.indent.pro with the contents:

-nbad -bap -nbbb -sob
-br -ce -cdw -cli2 -ss -npcs -cs -saf -saw -saf -sai -saw
-di1 -nbc -bfda -psl -brs
-i4 -ci4 -lp -ts8 -ip20 -nut
-l80 -hnl

Note that you can run "indent" on a file, or use it as a filter
(useful with the vim filter command '!').

There are several common places where "indent" fails to do the right
thing, and some manual fixup will be required.  The <> symbols
for templates and variable declarations with initializers, e.g.
    MyClass x(42);
are usually confused for other constructs.

vi/vim
------

Configured using the file $(HOME)/.vimrc .  Example .vimrc file:

set shiftwidth=4 autoindent ruler nocompatible
autocmd BufEnter *.c,*.cc,*.cpp,*.h set cindent expandtab softtabstop=4
syntax on

shiftwidth=4 : Sets indentation levels to be 4 spaces, as required by the
    style standard.
expandtab : Tab characters are converted to spaces.
softtabstop=4 : Changes the behavior of the TAB key to move 4 spaces
    instead of the normal 8.  The "tabstop" option should be left to 8,
    in order to expand existing tabs to 8 spaces.
cindent : Turns on automatic C-style code indentation.

Note that some options are only turned on for *.{cpp,h} files.  This is
to prevent tabs from being expanded in Makefiles, a serious error.

The keystrokes >{motion} and <{motion} perform indentation (move the
text [shiftwidth] spaces to the right) and unindentation (move the
text [shiftwidth] spaces to the left) on the text defined by {motion}
(the standard vi motion sequences, e.g. >> indents a line, >} indents
a paragraph unit, etc.).

The keystroke ={motion} performs C-style re-indentation on the text
defined by {motion} (e.g. =} re-indents a paragraph unit).  shiftwidth
should be defined to be the desired indentation level.

Modelines are comments that can be added to files so that appropriate
vi settings are enabled when editing that file.  As an OA Gear standard,
*.{cpp,h} files are permitted to have the following modeline as the last
line in the file:

// vim: ci et sw=4 sts=4

emacs
-----

Example configuration using $(HOME)/.emacs :

(set-foreground-color "white")
(set-background-color "black")
(global-font-lock-mode t)

(require 'cc-mode)
(defun my-build-tab-stop-list (width)
  (let ((num-tab-stops (/ 80 width))
        (counter 1)
        (ls nil))
    (while (<= counter num-tab-stops)
      (setq ls (cons (* width counter) ls))
      (setq counter (1+ counter)))
    (set (make-local-variable 'tab-stop-list) (nreverse ls))))
(defun my-c-mode-common-hook ()
  (setq tab-width 5) ;; modify this
  (my-build-tab-stop-list tab-width)
  (setq c-basic-offset 4) ;; modify this
  (setq indent-tabs-mode nil)) ;; force only spaces for indentation
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

-------------------------------------------------------------------------------
