Development standards

From OpenCog

Jump to: navigation, search

Notes taken from the opencog/HACKING file. See also: BuildingOpenCog and Branches.

The OpenCog source code repository has moved from Launchpad (Bazaar) to Github, with a mirror on Launchpad.

Contents

Coding standards

Whitespace

Required for code consistency and patch acceptance:

  • use 4 spaces for indentation
  • never use tabs, only spaces (for instance 8 spaces instead of 2 tabs)
  • use 80 columns max
  • use unix-style end-of-lines (all decent win32 editors support it)
  • use definition-block brackets on a new line and command-block brackets on the same line
  • use spaces between expression operators ("i + 1" instead of "i+1")

Includes

When including source files from within OpenCog, you should use the following examples as a guide:

// For headers within the same directory:
#include "myheader.h" 
// For headers within a sub directory of the current:
#include "subdir/myheader.h"
// For headers in a parent directory, you should
// use the full opencog include path, and ensure that path
// is in the CMakeList.txt include directive...
#include <opencog/util/RandGen.h>

Documentation

We use Doxygen for generating code documentation.

This allows a variety of markup to be used, and developers of OpenCog should become familiar with the basic markup and types of comment available. Remember, the time spent on in depth documentation pays itself back multiple-folds when it comes to others (and yourself!) revisiting code you wrote a year earlier.

The basic way of documenting a function would be:

/** Brief description of foo.
 * 
 * An optional and more in depth description of foo
 *
 * @param bar A description of the bar parameter.
 * @param bar2 A description of the bar2 parameter.
 * @return A description of the return value.
 *
 * @bug A bug with foo (should really be in the Github issue tracker!)
 * @todo something missing from the implementation of foo (this gets
 *       added to a global todo list, very handy)
 */
int foo(string bar, bool bar2);

As you can see, we use the @ prefix for special commands.

For a full description of the commands available see the list of special commands. There are also various tutorials to be found on Google.

Checking with astyle

To check whether your code complies with our standard, you may use the tool "astyle". Make sure you use the following options:

prompt-$ astyle --indent=spaces=4 --brackets=linux --indent-labels \
          --pad=oper --one-line=keep-statements --convert-tabs \
          --indent-preprocessor file.cc
prompt-$ diff file.cc file.cc.orig

Vim

If you use the VIM editor, you may add the following line to your ".vimrc" configuration file to automatically setup your editor to use opencog's style when editing a source file from OpenCog's tree:

autocmd BufNewFile,BufReadPost * if match(expand("%:p:h"), "/opencog") >= 0 && &filetype == "cpp" | set ts=4 sw=4 tw=80 ff=unix cindent expandtab | endif

Emacs

If you use Emacs, you may add the following lines to your ".emacs" as well:

(setq-default indent-tabs-mode nil) ;; use spaces instead of tab
(setq-default c-basic-offset 4) ;; set c based language indent to 4
;; open cxxtest files in C++ mode
(setq auto-mode-alist (cons '("\\.cxxtest$" . c++-mode) auto-mode-alist))

If you want to use CEDET, here is some help. And if you want to use flymake, now part of emacs, here is some help.

Git HOWTO

In the instructions below, please note that upstream is the same thing as https://github.com/opencog/opencog -- its a synonym, and it means the same thing. Likewise, origin is a synonym for https://username@github.com/username/opencog. These two don't have to actually be called 'origin' and 'upstream', but, by convention, they often are. When you push to origin, you are pushing to your own fork of opencog. If you're trying to understand this workflow, read each numbered step along with the numbered notes below.

  1. Browse to https://github.com/opencog/opencog, login and click Fork.
  2. In a terminal:
    1. git clone https://username@github.com/username/opencog
    2. cd opencog
    3. git remote add upstream https://github.com/opencog/opencog
    4. git checkout master
    5. git pull upstream master
    6. git push origin master
    7. git branch my-latest-fix
    8. git checkout my-latest-fix
    9. hack hack hack
    10. git commit -a -m "commit message"
    11. git pull --rebase upstream master
    12. git push origin my-latest-fix
  3. Browse to your personal branch, click Pull Request and wait for your pull request to be reviewed. Create new branches or work with old branches at any time by returning to step 2.4.
  4. Optionally, after you've finished working with a branch, and after any pull request has been merged or otherwise closed, and you wish to completely delete the branch:
    1. git checkout master
    2. git branch -d my-latest-fix
    3. git push origin :my-latest-fix
  5. Optionally, to work with others' branches, e.g.:
    1. git remote add linas https://github.com/linas/opencog
    2. git fetch linas
    3. git branch compile linas/compile
    4. git checkout compile
  6. Optionally, to test pull requests of other contributors locally
    1. git config --global alias.pr '!f() { git fetch $1 refs/pull/$2/head:refs/remotes/pr/$2; }; f' (addition of system wide git alias)
    2. git pr upstream 804 (804 can be another pull request number)
    3. git checkout pr/804
    4. test test test
    5. git checkout master
    6. git branch -rd pr/804 (clean up)
  7. Optionally, for those who have write access to github repos, to prevent accidental pushs to upstream.
    1. git remote set-url --push upstream "to_prevent_accidental_push_to_upstream"


Notes (item numbers below correspond to item numbers above)

  1. Creating your personal fork, out of which you can manage numerous consecutive and/or parallel personal branches. This is a one-off step.
    1. A remote tracked repository in opencog/.git/config is created with the name origin (a git convention). This is a one-off step.
    2. ...
    3. A remote tracked repository in opencog/.git/config is created with the name upstream (a GitHub convention). This is a one-off step.
    4. Return to this step before creating new branches, and to update your GitHub fork's master branch with the OpenCog master (upstream) branch (next step). It is best to never make commits to your local master, but only ever to branches.
    5. Keeps your local 'master' branch in sync with OpenCog master branch.
    6. Push to keep the master branch of your github fork updated with the master branch of opencog/opencog.
    7. Creates a new local working branch
    8. Moves to the new branch
    9. ...
    10. Make as many commits as you like before going on to the next step.
    11. Pull commits from the master branch and play your changes over top. Run this command anytime you want to sync a local branch with the master branch.
    12. Push your work to your personal branch on Github
  2. Aka a GitHub PR.
  3. If you've finished working with a branch, including making changes suggested in Pull Request comments
    1. Return to this step before deleting branches.
    2. optionally delete your local copy of the branch.
    3. optionally delete your GitHub copy of the branch.

Now, you don't have to delete the branch, or wait for the merge; you can keep on working in that branch, and then issue new Github pull requests for new work. This could become a problem only if one of the series of Github pull request was denied for some reason -- then you've got a bunch of work depending on a patch that is being denied. Thus, if you have several logically unrelated tasks, its best to do each in a separate branch. But, if you have a long series of tasks all working on the same thing, and its all more-or-less your current project, it would be very unlikely that anything would be denied, so just keep working in the same branch, issue Github pull requests every now and then (to get your code upstream), and maybe pull from master every now and then, (if you really need to). And, in the meantime, if you spot some other completely unrelated bug that you want to fix, you can always make a new branch (locally, off of master), fix it, push it, and go back to your usual working branch like nothing happened.

Dependencies

All OpenCog dependencies are found in the standard Ubuntu software repositories. If you would like to develop new features and are unsure about your choices with respect to new dependencies (libraries, etc.) please discuss on the mailing list. The use of standard packages for dependencies is a great benefit to the ease of setting up new development environments and to the efficiency of deploying OpenCog. Contributions which do not meet these guidelines require special review and may not be accepted into the master mainline branch on Github.

Patches & Merges

Patches should generally follow LKML (Linux Kernel Mailing List) standards and acceptance criteria. Large or significant changes from new developers should be broken into small revisions, uploaded to a user branch on Github and a Pull Request made for discussion. Small patches may be emailed (ask for an email address to send patches at #opencog on IRC.freenode.net).

Please ensure your code conforms to the #Coding Standards.

Help review code changes

The more eyes we have glancing over the commits, the more likely people will conform to code style conventions and more importantly you may catch bugs before they become a problem later!