If you are going to make any changes to MySQL++, this file has some
hints and commentary you may find helpful.


Subversion Access
~~~~~~~~~~~~~~~~~
    To check out the current development version from the Gna!
    Subversion repository, say:

        $ svn co svn://svn.gna.org/svn/mysqlpp/trunk mysqlpp

    If you're a MySQL++ committer, use svn over ssh instead:
    
        $ svn co svn+ssh://LOGIN@svn.gna.org/svn/mysqlpp/trunk mysqlpp

    where LOGIN is your Gna! login name.  You will have to have your
    ssh public key(s) registered with Gna! for this to work.


Bootstrapping the Library
~~~~~~~~~~~~~~~~~~~~~~~~~
    When you check out MySQL++ from svn, there are a lot of things
    "missing" as compared to a distributed tarball, because the
    svn repository contains only source files, no generated files.

    If you're using Windows, there is a simple batch file called
    bootstrap.bat which wraps up all the steps you need to build
    these "missing" files.  To run it, just say "bootstrap" from a
    command shell in the top MySQL++ source directory.  For it to run
    correctly, you will need Bakefile 0.2.5 (http://bakefile.org/) and
    a Perl 5 interpreter installed on your system, both in the PATH.
    The bootstrap script is smart enough to recognize when these
    tools are missing and stop processing so you can fix the problem.

    For all other platforms, there's a Bourne shell script called
    bootstrap.  It's quite a bit more complex than bootstrap.bat.
    It does more, and takes many optional arguments to control its
    behavior.  For many systems, it suffices to just run it without
    any arguments:

        $ ./bootstrap

    For more unusual situations, here's the complete usage:

        $ ./bootstrap [no{doc,ex,lib,opt}] [pedantic] [bat] \
                      [configure flags]

    Arguments:

    nodoc   The documentation won't be considered a prerequisite for
            building the distribution tarball.  This is useful on systems
            where the documentation doesn't build correctly, and you only
            need to make a binary RPM.  That process requires a tarball,
            but doesn't need the documentation.  Don't distribute the
            tarball or SRPM that results, as they are no good for any
            other purpose.

    noex    The generated Makefiles and project files won't try to build
            any of the examples.

    nolib   The generated Makefiles and project files won't try to build
            the MySQL++ library.

    nomaint Turn off "maintainer mode" stuff in the build.  These are
            features used only by those building MySQL++ from svn.  The
            'dist' build target uses this when creating the tarball.

    noopt   Compiler optimization will be turned off.  (This currently
            has no effect on MinGW or Visual C++.)

    pedantic
            Turns on all of GCC's warnings and portability checks.
            Good for checking changes before making a public release.

    bat     Asks cmd.exe to run bootstrap.bat for you.  This is useful
            when using Cygwin just as a command shell in preference
            to cmd.exe, as opposed to using Cygwin to build MySQL++
            using its native tools.  Passing 'bat' stops all command
            line processing in the bootstrap script, so if you
            also pass some of the other options, make 'bat' last.
            The only options that affect the built project files and
            Makefiles work are the no* ones.

    configure options
            As soon as the bootstrap script sees an option that it
            doesn't understand, it stops processing the command line.
            Any subsequent options are passed to the configure script.
            See README-Unix.txt for more on configure script options.

    In addition to Bakefile 0.2.5 and Perl 5, you'll also need autoconf
    1.59 or higher to run bootstrap successfully.


On Manipulating the Build System Source Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    One of the things the bootstrapping system described above
    does is produces various types of project and make files from a
    small number of source files.  This system lets us support many
    platforms without having to maintain separate build system files
    for each platform.

    Bakefile (http://bakefile.org/) produces most of these project
    and make files from a single source file called mysql++.bkl.

    Except for small local changes, it's best to change mysql++.bkl
    and "re-bake" the project and make files rather than change
    those files directly.  You can do this with the bootstrap scripts
    covered above.  On Windows, if all you've changed is mysql++.bkl,
    you can use rebake.bat instead, which doesn't try to do as much
    as bootstrap.bat.

    Bakefile produces finished project files for Visual C++ and Xcode
    and finished Makefiles for MinGW.  It also produces Makefile.in,
    which is input to GNU Autoconf along with configure.ac
    and config/*.  You may need to change these latter files in
    addition to or instead of mysql++.bkl to get the effect you want.
    Running bootstrap incorporates changes to all of these files in
    the GNU autoconf output.

    While Bakefile's documentation isn't as comprehensive as it
    ought to be, you can at least count on it to list all of the
    available features.  So, if you can't see a way to make Bakefile
    do something, it's likely it just can't do it.  Bakefile is a
    high-level abstraction of build systems in general, so it'll never
    support all the particulars of every odd build system out there.


Submitting Patches
~~~~~~~~~~~~~~~~~~
    If you wish to submit a patch to the library, please send it to
    the MySQL++ mailing list, or attach it to an entry in our bug
    tracker on Gna!  We want patches in unified diff format.

    The easiest way to get a unified diff is to check out a copy of the
    current MySQL++ tree as described above.  Then make your change,
    cd to the MySQL++ root directory, and ask Subversion to generate
    the diff for you:

        $ svn diff > mychange.patch

    If your patch adds new files to the distribution, you can say
    "svn add newfile" before you do the diff, which will include
    the contents of that file in the patch.  (You can do this even
    when you've checked out the tree anonymously.)  Then say "svn
    revert newfile" to make Subversion forget about the new file.

    If you're making a patch against a MySQL++ distribution tarball,
    then you can generate the diff this way:

        $ diff -ruN mysql++-olddir mysql++-newdir > mychange.patch

    The diff command is part of every Unix and Linux system, and
    should be installed by default.  If you're on a Windows machine,
    GNU diff is part of Cygwin (http://cygwin.com/).  Subversion is
    also available for all of these systems.  There are no excuses
    for not being able to make unified diffs.  :)


The MySQL++ Code Style
~~~~~~~~~~~~~~~~~~~~~~
    Every code base should have a common code style.  Love it or
    hate it, here are MySQL++'s current code style rules:

    Source Code
    ~~~~~~~~~~~
        File types: ac, cpp, h, in, m4, pl

        - Tabs for indents, size 4

        - Unix line endings.  Any decent programmer's editor can
          cope with this, even on Windows.

        - C/C++ rules:

            - Base whitespace style is AT&Tish: K&R/Stroustrup,
              plus a little local spice.  If you have the indent(1)
              program, the command is:

                indent -kr -nce -cli4 -ss -di1 -psl -ts4 FILES...

              That is, don't cuddle else, indent case statement labels,
              space before semicolon with empty loop body, no extra
              space between a variable type and name, return value
              of function on separate line from rest of definition.

            - Class names are in CamelCase, uppercased first letter

            - Method names are in all_lower_case_with_underscores();
              ditto most other global symbols.

            - Macro names are in ALL_UPPERCASE_WITH_UNDERSCORES

            - Doxygen comment for all public declarations, unless
              there is a very good reason to keep the thing
              undocumented.

        - Perl and shell script rules are more or less the same
          as for C/C++, to the extent this makes sense.


    XML/HTML Dialects
    ~~~~~~~~~~~~~~~~~
        File types: bkl, dbx, hta

        - Spaces for indents, size 2.  Shallow indents due to the
          high level of nesting occurring in such files, and spaces
          because they're not as annoying at shallow indent levels
          in editors that don't treat space indents like tabs.

        - Unix line endings.  Again, these are intended to be viewed
          in a programmer's text editor, which should work with Unix
          line endings no matter the platform.


    Plain Text Files
    ~~~~~~~~~~~~~~~~
        File types: txt

        - Spaces for indents, size 4.  Spaces because such files
          are often viewed in Notepad and similarly crippled text
          editors which use a default indent level of 8.

        - DOS line endings, again for the Notepad reason.  And on
          modern Unixy platforms, the tools cope with DOS line endings
          reasonably well.  Better than the converse, anyway.


    When in doubt, mimic what you see in the current code.  When still
    in doubt, ask on the mailing list.


Testing Your Proposed Change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ includes a self-test mechanism called dtest.  It's a
    Bourne shell script, run much like exrun:

        $ ./dtest [-s server_addr] [-u user] [-p password]

    This automatically runs most of the examples, captures the outputs
    to a file, and then compares that to a known-good run's outputs,
    stored in bmark.txt.  So, before you submit a patch, run dtest
    to see if anything has changed.  If something has and you can't
    account for it, it represents a problem that you'll have to fix
    before submitting the patch.  If it gives an expected change,
    remove bmark.txt, re-run dtest, and include the bmark.txt diffs in
    your patch.  This communicates to us the fact that you know there
    are differences and want the patch evaluated anyway.  Otherwise,
    we are likely to view the change as a bug.

    dtest also runs all of the unit tests in test/*.  The purpose of
    test/* is different from that of examples/*:

        - test/* are unit tests: each tests only one MySQL++ class,
          independent of everything else.  Because DB access requires
          several MySQL++ classes to cooperate, a unit test never
          accesses a database; hence, no unit test needs DB connection
          parameters.  We will never get 100% code coverage from
          test/* alone.

        - examples/* can be thought of as integration tests: they
          test many pieces of MySQL++ working together, accessing
          a real database server.  In addition to ensuring that all
          the pieces work together and give consistent results from
          platform to platform and run to run, it also fills in gaps
          in the code coverage where no suitable test/* module could
          be created.

        - test/* programs always run silently on success, writing
          output only to indicate test failures.  This is because
          they're usually only run via dtest.

        - examples/* are always "noisy," regardless of whether they
          succeed or fail, because they're also run interactively by
          people learning to use MySQL++.

    Patches should include tests if they introduce new functionality
    or fix a bug that the existing test coverage failed to catch.
    If the test is noisy, needs DB access, or tests multiple parts
    of the library at once, it goes in examples/*.  If your change
    affects only one class in MySQL++ and testing it can be done
    without instantiating other MySQL++ classes -- other than by
    composition, of course -- it should go in test/*.

    In general, prefer modifying an existing examples/* or test/*
    program.  Add a new one only if you're introducing brand new
    functionality or when a given feature currently has no test at all.

    Beware that the primary role the examples is to illustrate points
    in the user manual.  If an existing example does something similar
    to what a proper test would need to do and the test doesn't change
    the nature of the example, don't worry about changing the example
    code.  If your test would change the nature of the example, you
    either need to do the test another way, or also submit a change
    to doc/userman/*.dbx that incorporates the difference.


Adding Support for a Different Compiler
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    As described above, MySQL++ uses the Bakefile system for creating
    project files and makefiles.  This allows us to make changes
    to a single set of files, and have the proper changes be made
    to all generated project files and makefiles.  In the past, we
    used more ad-hoc systems, and we'd frequently forget to update
    individual project files and makefiles, so at any given time,
    at least one target was likely to be broken.

    If MySQL++ doesn't currently ship with project files or makefiles
    tuned for your compiler of choice, you need to work through the
    Bakefile mechanism to add support.  We're not willing to do ad-hoc
    platform support any more, so please don't ask if you can send
    us project files instead; we don't want them.

    If you want to port MySQL++ to another platform, we need to be
    confident that the entire library works on your platform before
    we'll accept patches.  In the past, we've had broken ports that
    were missing important library features, or that crashed when built
    in certain ways.  Few people will knowingly use a crippled version
    of MySQL++, since there are usually acceptable alternatives.
    Therefore, such ports become maintenance baggage with little
    compensating value.


Maintaining a Private CVS Repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You may find it helpful to maintain your own CVS repository.
    Whenever there is a new MySQL++ release, import it on the vendor
    branch like this:

        $ cvs import -m "Version 1.7.35" software/mysql++ mysql++ mysql++-1_7_35

    (This assumes that you have your CVSROOT environment variable
    set properly.)

    Update the HEAD branch like this:

        $ cd mysql++
        $ cvs update -PdA
        $ cvs update -j HEAD -j mysql++-1_7_35 -Pd
        $ cvs ci -m "merged 1.7.35 into HEAD"
        $ cvs tag mysql++-1_7_35-merged

    Then any changes you make can easily be tracked, and diffs can
    be produced with rdiff:

        $ cvs rdiff -ru mysql++-1_7_35 -r mysql++-1_7_35_equal_list \
            $(cat CVS/Repository) > equal_list.patch

