diff --git a/doc/contributing.rst b/doc/contributing.rst index c4ba7c73478aee3dbd85fa8a2bb3dec1036b1a79..869300d8702b2334086fa46095eebe7cfa8eac00 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -11,6 +11,9 @@ documented inline. One exception exists on the example-driven approach: following the :mod:`~promod3.core` module for your setup is not advisable. This one is a bit special and provides core functionality to everybody else. +In the end of this chapter you will find a little walk-through on how to get +started. + -------------------------------------------------------------------------------- |git| Branches -------------------------------------------------------------------------------- @@ -201,16 +204,17 @@ will provide you with a target ``test_awesome_feature.py_run``. -------------------------------------------------------------------------------- Writing Documentation -------------------------------------------------------------------------------- -To create documentation, we use |sphinx|_ to go from |restructuredtext|_ files -and API documentation in source files to HTML or man pages. - -For each module, at least one |restructuredtext| document exists, that gives an -idea of concepts and pulls in interfaces from source. Copying files to the -build directory, issuing the |sphinx| call and everything else that is needed -to create the actual documentation is done by |cmake| and its makefiles. Hence, -the :file:`CMakeLists.txt` of the :file:`doc` directory of a module is crucial. -For documentation which does not relate to a particular module, the repository -comes with a top-level :file:`doc` directory. +To create documentation, we use |sphinx|_ to go from |restructuredtext|_ +(|restructuredtext_abrv|) files and API documentation in source files to HTML +or man pages. + +For each module, at least one |restructuredtext_abrv| document exists, that +gives an idea of concepts and pulls in interfaces from source. Copying files to +the build directory, issuing the |sphinx| call and everything else that is +needed to create the actual documentation is done by |cmake| and its makefiles. +Hence, the :file:`CMakeLists.txt` of the :file:`doc` directory of a module is +crucial. For documentation which does not relate to a particular module, the +repository comes with a top-level :file:`doc` directory. While you should not spend to much time thinking about how to format documentation, here is a helpful list of standard formatters: @@ -219,8 +223,272 @@ http://sphinx-doc.org/markup/inline.html If you write new functionality for |project|, or fix bugs, feel free to extend the Changelog. It will be automatically pulled into the documentation. +-------------------------------------------------------------------------------- +How To Start Your Own Module +-------------------------------------------------------------------------------- +This is just a walk-through how the topics from above work together when you +start your own module. For the entry point, lets assume that you already cloned +the repository into a directory and just changed into it. + +All new features should take off from the ``develop`` branch. That way, they +work fine with all the other new fellows waiting for release right from the +beginning. Therefore you need to switch branches as a first step. |git| will +tell you for which branch you went, a story of failure otherwise. + +.. code-block:: console + + $ git checkout develop + Switched to branch 'develop' + $ + +Sitting on top of the right code basis, you should just spawn your own branch +from it. As an example, your feature will go by the name of 'sidechains'. + +.. code-block:: console + + $ git checkout -b sidechains + Switched to a new branch 'sidechains' + $ + +This time, |git| should tell you about going for **a new** branch. + +Now create the directory structure where your project will live. Here is the +list of directories which are likely to be used in every project. + +.. code-block:: console + + $ mkdir -p sidechains/doc + $ mkdir -p sidechains/pymod + $ mkdir -p sidechains/tests + $ + +If you run ``git status`` at this point, you will see basically nothing. That +is, |git| does not admire empty directories. Before you bring your module under +version control, create a couple of files which are always needed. + +.. code-block:: console + + $ touch sidechains/pymod/__init__.py + $ echo "FOO" >> sidechains/doc/index.rst + $ echo ":mod:\`~promod3.sidechains\` - ProMod3 side chain optimiser" >> sidechains/doc/index.rst + $ echo "================================================================================" >> sidechains/doc/index.rst + $ + +Having an empty :file:`__init__.py` is perfectly fine for |python|, it just +announces a directory as a module. But a blank :file:`index.rst` has the chance +to give |sphinx| quite a headache so you already fill it with a headline for +your documentation. + +For integration with :command:`make`, the build system needs to now about the +new module and its members. This goes for setting up new |cmake| files and +extending some around the directory root. + +.. code-block:: console + + $ touch sidechains/CMakeLists.txt + $ touch sidechains/pymod/CMakeLists.txt + $ touch sidechains/doc/CMakeLists.txt + $ + +Each of those files still needs a bit of content. The simplest one comes from +the module's root, :file:`sidechains/CMakeLists.txt`: + +.. code-block:: cmake + :linenos: + + add_subdirectory(pymod) + add_subdirectory(doc) + +Those two directives just tell |cmake| to go and look in directories +:file:`pymod` and :file:`doc` below the current path for more |cmake| +configurations. The next level in :file:`CMakeLists.txt` magic comes for the +:file:`doc` directory: + +.. code-block:: cmake + :linenos: + + set(SIDECHAINS_RST + index.rst + ) + + add_doc_source(NAME sidechains RST ${SIDECHAINS_RST}) + +``add_doc_source`` is our custom |cmake| macro to register +|restructuredtext_abrv| files for the documentation. On running +:command:`make`, those files are placed in a :file:`doc/source` directory tree +within the build directory. Each new submodule in your project should be +covered by its own documentation entity, extending the list in ``RST``. +Maintaining readability, its good practice to store this list in a separate +variable, called ``SIDECHAINS_RST`` here. + +For the actual code, you should keep in mind that a |python| module may be +rather complex. There is for sure |python| code, there could be a bit of |C++| +and conditional compilation. In rare cases you also want to modify the +directory structure of the package. All this has to be declared in the +:file:`pymod` subtree. We cannot enumerate all specialities but there should be +a couple of examples around in this repository. Here is the most basic +:file:`CMakeLists.txt`: + +.. code-block:: cmake + :linenos: + + set(SIDECHAINS_PYMOD + __init__.py + ) + + pymod(NAME sidechains PY ${SIDECHAINS_PYMOD}) + +Source files should be again listed in a dedicated variable. Later, you +probably add some |C++| code and settings diverging from the defaults via the +``pymod`` macro. This is where things clutter up quite quickly. As set up here, +your project would be added as a module ``sidechains`` in the |project| +|python| package tree. + +The final step towards |cmake| is to register your module's directory in the +top level :file:`CMakeLists.txt`: + +.. code-block:: cmake + :linenos: + :emphasize-lines: 80 + + #------------------------------------------------------------------------------- + # Author: Bienchen + #------------------------------------------------------------------------------- + # Options to CMake: + # DISABLE_DOCUMENTATION: Don't build documentation, don't search for Sphinx + # DISABLE_DOCTEST: Don't run example code from documentation on 'make check' + # DISABLE_LINKCHECK: Don't test links from documentation on 'make check' + # (if documentation is disabled, there is no doctest, linkcheck at all) + cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake_support) + + project(PROMOD3 CXX C) + + include(PROMOD3) + + set(PROMOD3_VERSION_MAJOR 0) + set(PROMOD3_VERSION_MINOR 1) + set(PROMOD3_VERSION_PATCH 0) + set(PROMOD3_VERSION_STRING ${PROMOD3_VERSION_MAJOR}.${PROMOD3_VERSION_MINOR}.${PROMOD3_VERSION_PATCH}) + + if (CMAKE_COMPILER_IS_GNUCXX) + exec_program(gcc ARGS --version OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION) + if(CMAKE_C_COMPILER_VERSION MATCHES ".*4\\.[5-9].*") + set(PROMOD_GCC_45 true) + else() + set(PROMOD_GCC_45 false) + endif() + endif() + + if (OPTIMIZE) + set(CMAKE_BUILD_TYPE Release) + set(_OPT ON) + else() + set(CMAKE_BUILD_TYPE Debug) + set(_OPT OFF) + endif() + + setup_stage() + file(MAKE_DIRECTORY ${STAGE_DIR} + ${EXECUTABLE_OUTPUT_PATH} + ${HEADER_STAGE_PATH} + ${LIB_STAGE_PATH} + ${LIBEXEC_STAGE_PATH}) + + setup_compiler_flags() + setup_boost() + + find_package(Python 2.7 REQUIRED) + if(NOT DISABLE_DOCUMENTATION) + find_package(Sphinx ${PYTHON_VERSION} REQUIRED) + set(PYTHON_DOC_URL "https://docs.python.org/${PYTHON_VERSION}") + # set this to the URL corresponding to the version of OST you are using + set(OST_DOC_URL "http://www.openstructure.org/docs/1.3") + endif() + find_package(OPENSTRUCTURE 1.4 REQUIRED + COMPONENTS io mol seq seq_alg mol_alg conop) + + if (CMAKE_COMPILER_IS_GNUCXX) + # do not write back into cache, otherwise the compile command line gets + # expanded with multiple -fno-strict-aliasing flags, triggering a complete + # rebuild whenever cmake is run + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-strict-aliasing") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_GREATER "4.6") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes") + endif("${CMAKE_CXX_COMPILER_VERSION}" VERSION_GREATER "4.6") + endif() + + # basic environment + include_directories(${Boost_INCLUDE_DIRS} + ${OST_INCLUDE_DIR}) + + set(FILES_TO_BE_REMOVED ${PROJECT_BINARY_DIR}/stage) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES + "${FILES_TO_BE_REMOVED}") + + ## sub dirs to be recognised by CMake + ## e.g. add_subdirectory(src), subdirs have their own CMakeLists.txt + add_subdirectory(config) + add_subdirectory(core) + add_subdirectory(sidechains) + add_subdirectory(scripts) + add_subdirectory(actions) + if(NOT DISABLE_DOCUMENTATION) + add_changelog_to_doc(FILE "${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG") + add_subdirectory(doc) + endif() + + ## report setup + message(STATUS "PROMOD3 will be built with the following options:\n" + " OpenStructure (-DOST_ROOT) : ${OST_ROOT}\n" + " Optimized (-DOPTIMIZE) : ${_OPT}\n" + " Python : ${PYTHON_BINARY}\n") + +All that needs to be done for |cmake| to recognise your module is adding its +directory as shown in line 80. + +This was the final step to set up the build system. Running |cmake| at this +point would create the build environment in place. But building software in +your code repository has several drawbacks. First of all, it puts all kind of +new files in the directory tree and ``git status`` would show them all. Then +its very likely, that manual intervention is needed after ``make clean``. Plus, +this would be very static. Imagine at one point you want to switch on all +debugging flags for your |C++| code. So you either clean the whole repository +and rebuild or you go by two separated repositories copying code changes from A +to B. The solution to this is instead of 'in place' you go 'out of source'. You +still can stay in your repository while being out of the source tree by using +sub-directories. |project| comes with a dedicated prefix 'build*' in +:file:`.gitignore`. Have a directory :file:`build` and :file:`build-dbg` and it +will not show up in ``git status``. + +.. code-block:: console + + $ mkdir build + $ cd build + $ + +To actually create all the makefiles and generated files, you may use one of +the configuration scripts from the :file:`conf-scripts` directory. Usually +those scripts only need to be pointed to an |ost_s| staging tree. Even if you +are on a system not covered by available scripts, their code may help you at +the |cmake| command. Once you managed to conquer a new system, feel free to add +a new configuration script. The following example assumes |fedora| 19. + +.. code-block:: console + + $ ../conf-scripts/fedora-19-conf ../../ost.git/stage + +From this point, :command:`make` should work and you could start adding your +files to the repository using ``git add``. + + .. _restructuredtext: http://docutils.sourceforge.net/rst.html +.. |fedora| replace:: Fedora + .. LocalWords: cmake hotfix doctest linkcheck rebase BRANCHNAME rebasing py .. LocalWords: CMakeLists txt rst pymod init submodule src restructuredtext -.. LocalWords: makefiles formatters Changelog codetest promod +.. LocalWords: makefiles formatters Changelog codetest promod sidechains io +.. LocalWords: mkdir linenos subdirectory abrv emphasize CXX GNUCXX gcc fno +.. LocalWords: ARGS endif OPTIMIZE LIBEXEC Wno DIRS dirs subdirs config dbg +.. LocalWords: changelog Optimized DOPTIMIZE gitignore cd conf