Overview docs for using Gromacs as a library
authorTeemu Murtola <teemu.murtola@gmail.com>
Tue, 31 Dec 2013 11:15:53 +0000 (13:15 +0200)
committerTeemu Murtola <teemu.murtola@gmail.com>
Thu, 30 Jan 2014 14:37:09 +0000 (15:37 +0100)
Add some documentation for the commandline module, and make the set of
installed headers provide a useful set of features.
Add an overview documentation for how to initialize Gromacs as a library
under different contexts.  Also, include some general notes about the
Gromacs API.  Can be extended in the future.

Change-Id: I13921fe1f1434fee8c495a169e6f5db645711f79

doxygen/mainpage.md
doxygen/usinglibrary.md [new file with mode: 0644]
src/gromacs/commandline.h
src/gromacs/commandline/CMakeLists.txt
src/gromacs/commandline/cmdlineinit.cpp
src/gromacs/commandline/cmdlineinit.h

index ddb1b5852b22401b89261ada9848c9427539cd90..011f7cfb2b9d03e6ae0aebe07d451504d195ec30 100644 (file)
@@ -52,6 +52,9 @@ give an overview of some of the topics that are documented:
  - \subpage page_analysisframework <br/>
    Provides an overview of the framework that the \Gromacs library provides for
    writing (trajectory) analysis tools.
+ - \subpage page_usinglibrary <br/>
+   Provides general guidance for writing software that uses the \Gromacs
+   library.
 \if libapi
  - \subpage thread_mpi <br/>
    This code is used internally for threading support, and also provides a
diff --git a/doxygen/usinglibrary.md b/doxygen/usinglibrary.md
new file mode 100644 (file)
index 0000000..2550741
--- /dev/null
@@ -0,0 +1,85 @@
+Using \Gromacs as a library {#page_usinglibrary}
+===========================
+
+Getting started
+===============
+
+\todo
+Describe how to link against \Gromacs (pkg-config, FindGromacs.cmake, etc.)
+
+The \Gromacs library (`libgromacs`) provides a few different alternatives for
+using it.  These are listed here from the highest level of abstraction to the
+low-level functions.
+ - If you are writing a trajectory analysis tool, please see
+   \ref page_analysisframework.  \ref page_analysistemplate should contain
+   all the ingredients to get started.
+   If you have an existing tool written using the analysis template from 4.5 or
+   4.6 (using the selection engine added in 4.5), you need to do some
+   conversion work to get this work with the new template.  This is mostly
+   straightforward, but requires some studying to understand the new framework.
+ - If you are writing a command line tool for some other purpose, you can use
+   the facilities provided by \ref module_commandline.  There are a few
+   different alternatives, depending on how much control you want to give
+   \Gromacs:
+    - For C++ code, you can implement gmx::CommandLineModuleInterface, and
+      use gmx::runCommandLineModule() to execute it.  This requires using some
+      additional \Gromacs classes (in particular, for implementing
+      gmx::CommandLineModuleInterface::writeHelp(), if you want to support the
+      `-h` option).
+    - For C code, you can use gmx_run_cmain() to wrap an existing C main
+      method.  The only constraint on the provided main method is that it
+      should use parse_common_args() for argument processing.
+      This approach should allow you to convert existing C tools written
+      against pre-5.0 \Gromacs (e.g., using the analysis template from 4.0 or
+      earlier) to the new version.
+    - If you want more control (for example, you do not want the default
+      command line options added by \Gromacs), you can directly initialize
+      \Gromacs using gmx::initForCommandLine() before calling other \Gromacs
+      routines.  This allows you to write your own handling for command line
+      options from scratch.  This is also discussed in \ref module_commandline.
+ - For most control, you can use gmx::init() to do basic initialization, create
+   your own implementation for gmx::ProgramContextInterface, and set that using
+   gmx::setProgramContext().  This allows you to customize how the \Gromacs
+   library shows the name of the program in messages, as well as how it locates
+   its own data files.
+
+If these do not fit your needs, you may need to modify the \Gromacs source code
+yourself.  In particular, it is currently relatively difficult to extend the
+functionality of `mdrun` without modifying the source code directly.
+If you think that some particular API would be necessary for your work, and
+think that it would be easy to expose, please drop a line on the
+`gmx-developers` mailing list, or contribute the necessary changes on
+http://gerrit.gromacs.org/.
+
+Notes on \Gromacs API
+=====================
+
+The headers for the public \Gromacs API are installed in `include/gromacs/`
+under the installation directory.  The layout reflects the source code layout
+under the `src/gromacs/` directory (see \ref page_codelayout).  The headers
+directly under `include/gromacs/` do not contain any declarations, but instead
+include a collection of headers from subdirectories.
+You should prefer to include these convenience headers instead of individual
+headers from the subdirectories, since they are much more stable.  The
+individual headers in the subdirectories can be renamed or moved, but the goal
+is to only rarely change the name of these top-level headers.
+
+Pre-5.0 versions of \Gromacs installed (nearly) all headers directly under
+`include/gromacs/`.  Most of these headers still exist, but now under
+`include/gromacs/legacyheaders/`.  The long-term goal is to move these to
+proper module hierarchy or get rid of them, but unfortunately this can take a
+long time.  Thus, you should not expect much stability from the API in these
+headers.  Some have already been moved, so if you do not find your favorite
+header there, try searching for a declaration from the other subdirectories.
+
+For headers under other subdirectories, some effort has been put to design the
+API for stability.  However, with limited development resources, and the focus
+of \Gromacs being in high performance simulations, all the APIs are subject to
+change without notice.  With each new release (with possible exception of patch
+releases), you should expect incompatible API changes.  This is in particular
+true until the planned reorganization of the `legacyheaders/` subdirectory is
+complete.
+
+This Doxygen documentation only covers part of the API.  In particular, nearly
+all of `include/gromacs/legacyheaders/` is undocumented, as well as code
+recently moved from there.
index 49aa86ff713d65404d4c99dbd9f423248646e1ed..017cac44bd0690b1ee8f202eb21818a5ecc1303a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
  * To help us fund GROMACS development, we humbly ask that you cite
  * the research papers on the package. Check out http://www.gromacs.org.
  */
-/*! \defgroup module_commandline Command Line Parsing and Help (commandline)
+/*! \defgroup module_commandline Command Line Program Management (commandline)
  * \ingroup group_utilitymodules
  * \brief
- * Provides functionality for parsing command-line arguments and writing help.
+ * Provides functionality for managing command line programs.
  *
- * This module implements gmx::CommandLineParser that assigns values to
- * gmx::Options (see \ref module_options) based on command-line arguments.
- * gmx::CommandLineHelpWriter is also provided to write help text for a program
- * that uses the parser.
+ * This module provides utility classes and functions for implementing command
+ * line programs.  They are mainly used within \Gromacs, but can also be used
+ * from external programs if they want to get a similar user experience to
+ * \Gromacs tools.
+ *
+ * The classes exposed from this module can be roughly divided into two groups:
+ *
+ *  - Helper classes/functions for implementing the %main() function.
+ *    See \ref page_usinglibrary for an overview of those available for user
+ *    programs.  These are declared in cmdlineinit.h
+ *    (gmx::CommandLineModuleInterface is declared in cmdlinemodule.h).
+ *    \if libapi
+ *
+ *    Additionally, for internal \Gromacs use, gmx::CommandLineModuleManager
+ *    provides the functionality to implement the `gmx` wrapper binary, as well
+ *    as command line options common to all \Gromacs programs (such as
+ *    `-version`).
+ *    \endif
+ *
+ *  - Helper classes for particular command line tasks:
+ *     - gmx::CommandLineParser implements command line parsing to assign
+ *       values to gmx::Options (see \ref module_options).
+ *     - gmx::CommandLineHelpWriter writes help text for a program that uses
+ *       the parser.
+ *     - parse_common_args() is an old interface to \Gromacs command line
+ *       parsing.  This is still used by many parts of \Gromacs.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  */
 /*! \file
  * \brief
- * Public API convenience header for handling command-line parameters.
+ * Public API convenience header for managing command line programs.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inpublicapi
@@ -56,6 +78,9 @@
 #define GMX_COMMANDLINE_H
 
 #include "commandline/cmdlinehelpwriter.h"
+#include "commandline/cmdlineinit.h"
+#include "commandline/cmdlinemodule.h"
 #include "commandline/cmdlineparser.h"
+#include "commandline/pargs.h"
 
 #endif
index 3bdd73c59b4975cd2fb677a939346eab8b5dd19a..5efde47341da86d99794c6110aa9b77f1c8bae44 100644 (file)
@@ -38,6 +38,7 @@ set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${COMMANDLINE_SOURCES} PARENT_SCOPE
 set(COMMANDLINE_PUBLIC_HEADERS
     cmdlinehelpwriter.h
     cmdlineinit.h
+    cmdlinemodule.h
     cmdlineparser.h
     cmdlineprogramcontext.h
     pargs.h)
index 4f17e42e74ca908c203c994e08a1095106f8b30a..aef6121bc39f3c44937840598a601c1df3812674 100644 (file)
@@ -49,6 +49,7 @@
 #include "gromacs/legacyheaders/smalloc.h"
 #include "gromacs/legacyheaders/types/commrec.h"
 
+#include "gromacs/commandline/cmdlinemodulemanager.h"
 #include "gromacs/commandline/cmdlineprogramcontext.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
@@ -136,4 +137,15 @@ void finalizeForCommandLine()
     g_commandLineContext.reset();
 }
 
+int runCommandLineModule(int argc, char *argv[],
+                         CommandLineModuleInterface *module)
+{
+    return gmx::CommandLineModuleManager::runAsMainSingleModule(argc, argv, module);
+}
+
 } // namespace gmx
+
+int gmx_run_cmain(int argc, char *argv[], int (*mainFunction)(int, char *[]))
+{
+    return gmx::CommandLineModuleManager::runAsMainCMain(argc, argv, mainFunction);
+}
index 326986faa11cfa1db7f5a12a1219777502da5c2a..5c0fc026eb2b3aae9c9b84c96242502b6916b76e 100644 (file)
@@ -34,7 +34,7 @@
  */
 /*! \file
  * \brief
- * Declares functions for initializing the \Gromacs library for command-line use.
+ * Declares functions for initializing the \Gromacs library for command line use.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inpublicapi
@@ -43,6 +43,8 @@
 #ifndef GMX_COMMANDLINE_CMDLINEINIT_H
 #define GMX_COMMANDLINE_CMDLINEINIT_H
 
+#ifdef __cplusplus
+
 // Forward declaration of class CommandLineProgramContext is not sufficient for
 // MSVC if the return value of initForCommandLine() is ignored(!)
 #include "cmdlineprogramcontext.h"
@@ -50,6 +52,8 @@
 namespace gmx
 {
 
+class CommandLineModuleInterface;
+
 /*! \brief
  * Initializes the \Gromacs library for command-line use.
  *
@@ -89,6 +93,81 @@ CommandLineProgramContext &initForCommandLine(int *argc, char ***argv);
  */
 void finalizeForCommandLine();
 
+/*! \brief
+ * Implements a main() method that runs a single module.
+ *
+ * \param argc   \c argc passed to main().
+ * \param argv   \c argv passed to main().
+ * \param module Module to run.
+ *
+ * This method allows for uniform behavior for binaries that only
+ * contain a single module without duplicating any of the
+ * implementation from CommandLineModuleManager (startup headers,
+ * common options etc.).
+ *
+ * The signature assumes that \p module construction does not throw
+ * (because otherwise the caller would need to duplicate all the
+ * exception handling code).  It is possible to move the construction
+ * inside the try/catch in this method using an indirection similar to
+ * TrajectoryAnalysisCommandLineRunner::runAsMain(), but until that is
+ * necessary, the current approach leads to simpler code.
+ *
+ * Usage:
+ * \code
+   int main(int argc, char *argv[])
+   {
+       CustomCommandLineModule module;
+       return gmx::runCommandLineModule(argc, argv, &module);
+   }
+   \endcode
+ *
+ * Does not throw.  All exceptions are caught and handled internally.
+ */
+int runCommandLineModule(int argc, char *argv[],
+                         CommandLineModuleInterface *module);
+
 } // namespace gmx
 
+extern "C"
+{
+#endif
+
+/*! \brief
+ * Implements a main() method that runs a given C main function.
+ *
+ * \param argc         \c argc passed to main().
+ * \param argv         \c argv passed to main().
+ * \param mainFunction The main()-like method to wrap.
+ *
+ * This method creates a dummy command line module that does its
+ * processing by calling \p mainFunction.  It then runs this module as with
+ * gmx::runCommandLineModule().
+ * This allows the resulting executable to handle common options and do
+ * other common actions (e.g., startup headers) without duplicate code
+ * in the main methods.
+ *
+ * \p mainFunction should call parse_common_args() to process its command-line
+ * arguments.
+ *
+ * Usage:
+ * \code
+   int my_main(int argc, char *argv[])
+   {
+       // <...>
+   }
+
+   int main(int argc, char *argv[])
+   {
+       return gmx_run_cmain(argc, argv, &my_main);
+   }
+   \endcode
+ *
+ * Does not throw.  All exceptions are caught and handled internally.
+ */
+int gmx_run_cmain(int argc, char *argv[], int (*mainFunction)(int, char *[]));
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif