Man page export from the wrapper binary.
authorTeemu Murtola <teemu.murtola@gmail.com>
Tue, 3 Sep 2013 04:11:38 +0000 (07:11 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 3 Oct 2013 15:25:23 +0000 (17:25 +0200)
Implement nroff output format for 'gmx help -export'.
Move the header/footer generation out of wman.cpp.
The generation is now off by default.  Can be reinstantiated if someone
comes with a good approach for the case where the compiled binaries
don't run on the build host (e.g., compiling AVX256 binaries on a SSE4.1
host).

Related to #685 and #969.

Change-Id: I17725e3a487470bea8f6db2a59da31139e70621e

12 files changed:
CMakeLists.txt
CPackInit.cmake
cmake/BuildManPages.cmake [deleted file]
cmake/CreateManPage.cmake [deleted file]
share/CMakeLists.txt
share/man/.gitignore [new file with mode: 0644]
share/man/CMakeLists.txt [new file with mode: 0644]
share/man/man7/gromacs.7.cmakein [moved from man/man7/gromacs.7.cmakein with 98% similarity]
src/CMakeLists.txt
src/gromacs/commandline/cmdlinemodulemanager.cpp
src/gromacs/onlinehelp/helpwritercontext.h
src/gromacs/onlinehelp/wman.cpp

index 81b3f45d26f2b1c0e1ab0cd81ee7bad742d6d210..477c742764f7277e4c0462692ed78840e8e1277d 100644 (file)
@@ -81,16 +81,20 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
 set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/admin/InstallInfo.txt")
 set(CPACK_SOURCE_IGNORE_FILES "\\\\.isreposource$;\\\\.git/;\\\\.gitignore$")
 set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_SOURCE_DIR}/CPackInit.cmake")
-SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "${CMAKE_SOURCE_DIR};/;${CMAKE_BINARY_DIR}/man;man")
+set(CPACK_SOURCE_INSTALLED_DIRECTORIES "${CMAKE_SOURCE_DIR};/;${CMAKE_BINARY_DIR}/share/man;share/man")
 set(CPACK_PACKAGE_CONTACT "gmx-users@gromacs.org")
 
 #must come after all cpack settings!
 include(CPack)
 
 set(SOURCE_IS_GIT_REPOSITORY OFF)
+set(SOURCE_IS_SOURCE_DISTRIBUTION OFF)
 if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
     set(SOURCE_IS_GIT_REPOSITORY ON)
 endif()
+if(NOT EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
+    set(SOURCE_IS_SOURCE_DISTRIBUTION ON)
+endif()
 
 ########################################################################
 # Check and warn if cache generated on a different host is being reused
@@ -1061,21 +1065,6 @@ if(GMX_LOAD_PLUGINS)
 endif(GMX_LOAD_PLUGINS)
 set(VMD_QUIETLY TRUE CACHE INTERNAL "")
 
-if(EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
-    if(NOT CMAKE_CROSSCOMPILING)
-        option(GMX_BUILD_MANPAGES "Build man pages" ON)
-    else()
-        message(STATUS "Building the man pages is not available when "
-            "cross-compiling the developer version from git")
-    endif()
-else()
-    #make sure source package contains all man pages
-    if(NOT EXISTS "${CMAKE_SOURCE_DIR}/man/man1/ngmx.1")
-        message(FATAL_ERROR "Man pages are missing from source package.")
-    endif()
-endif()
-mark_as_advanced(GMX_BUILD_MANPAGES)
-
 # Math and thread libraries must often come after all others when linking...
 if(HAVE_LIBM)
     list(APPEND GMX_EXTRA_LIBRARIES m)
index eba4c45d7a8bc32c1c72d265f8cc94073fc3a76b..212f74947b2ff8ff0fdd37cfeed8ae7a8063d983 100644 (file)
@@ -1,10 +1,10 @@
 #TODO: add check that source doesn't contain any untracked files
 if(CPACK_SOURCE_PACKAGE_FILE_NAME) #building source package
     get_filename_component(CMAKE_BINARY_DIR ${CPACK_OUTPUT_CONFIG_FILE} PATH)
-    if(NOT EXISTS "${CMAKE_BINARY_DIR}/man/man1/ngmx.1")
-        message(FATAL_ERROR 
-            "To create a complete source package all man pages need to be generated."
-            "The man pages are automatically built together with the binaries. "
-            "Make sure to build all binaries (e.g. GMX_X11=on).")
+    if(NOT EXISTS "${CMAKE_BINARY_DIR}/share/man/man1/gmx-view.1")
+        message(FATAL_ERROR
+            "To create a complete source package all man pages need to be generated. "
+            "You need to run 'make man' or set GMX_BUILD_MANPAGES=ON to get "
+            "them automatically built together with the binaries.")
     endif()
 endif()
diff --git a/cmake/BuildManPages.cmake b/cmake/BuildManPages.cmake
deleted file mode 100644 (file)
index 88fc9d6..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-MACRO(TODAY RESULT)
-    IF(UNIX)
-        EXECUTE_PROCESS(COMMAND "date" "+%F" OUTPUT_VARIABLE ${RESULT} OUTPUT_STRIP_TRAILING_WHITESPACE)
-    ELSE()
-        set(${RESULT} "????-??-??")
-    ENDIF()
-ENDMACRO(TODAY)
-
-if(GMX_BUILD_MANPAGES)
-    set(MAN1_PATH ${CMAKE_BINARY_DIR}/man/man1)
-    file(MAKE_DIRECTORY ${MAN1_PATH})
-
-    #create gromacs.7
-    FILE(READ "${CMAKE_SOURCE_DIR}/admin/programs.txt" contents)
-
-    # Convert file contents into a CMake list. First escape ;
-    STRING(REGEX REPLACE ";" "\\\\;" contents "${contents}")
-    STRING(REGEX REPLACE "\n" ";" contents "${contents}")
-
-    set(PROGMANPAGES "")
-    foreach(line ${contents})
-        if (${line} MATCHES "^HEAD\\|")
-            string(REGEX REPLACE "^HEAD\\|" "" DESC ${line})
-            set(PROGMANPAGES "${PROGMANPAGES}.Sh \"${DESC}\"\n.IX Subsection \"${DESC}\"\n.Vb\n.ta 16n\n")
-        elseif(${line} MATCHES "^END$")
-            set(PROGMANPAGES "${PROGMANPAGES}.Ve\n")
-        elseif(${line} MATCHES "\\|")
-            string(REGEX REPLACE "\\|" "\t" line ${line})
-            set(PROGMANPAGES "${PROGMANPAGES}\\&  ${line}\n")
-        else()
-            message(WARNING "Incorrectly formated line \"${line}\" in programs.txt")
-        endif()
-    endforeach()
-    TODAY(TODAYS_DATE)
-    configure_file(${CMAKE_SOURCE_DIR}/man/man7/gromacs.7.cmakein ${CMAKE_BINARY_DIR}/man/man7/gromacs.7)
-    install(FILES ${CMAKE_BINARY_DIR}/man/man7/gromacs.7 DESTINATION
-        ${MAN_INSTALL_DIR}/man7)
-#man-pages are only avalaible if they are either build or this is a source archive
-elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
-    install(FILES ${CMAKE_SOURCE_DIR}/man/man7/gromacs.7 DESTINATION
-        ${MAN_INSTALL_DIR}/man7)
-endif()
-
-function (gmx_add_man_page EXENAME)
-    if(GMX_BUILD_MANPAGES)
-        file(STRINGS ${CMAKE_SOURCE_DIR}/admin/programs.txt DESC 
-            REGEX "^${EXENAME}\\|" LIMIT_COUNT 1)
-        #Regex breaks with a "|" in description. Cmake doesn't support 
-        #non-greedy regex.
-        string(REGEX REPLACE "^.*\\|" "" DESC "${DESC}")
-        if(DESC STREQUAL "")
-            message(WARNING "Missing description for ${EXENAME}")
-        endif()
-        add_custom_command(TARGET ${EXENAME} POST_BUILD 
-            COMMAND ${CMAKE_COMMAND} -DINFILE=${EXENAME}${GMX_BINARY_SUFFIX}.nroff 
-                -DOUTFILE=${MAN1_PATH}/${EXENAME}.1 -DDESC=" - ${DESC}"
-                -DEXENAME="${CMAKE_BINARY_DIR}/bin/${EXENAME}${GMX_BINARY_SUFFIX}"
-                -P ${CMAKE_SOURCE_DIR}/cmake/CreateManPage.cmake)
-        install(FILES ${MAN1_PATH}/${EXENAME}.1 DESTINATION 
-            ${MAN_INSTALL_DIR}/man1 OPTIONAL)
-    elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
-        install(FILES ${CMAKE_SOURCE_DIR}/man/man1/${EXENAME}.1 DESTINATION 
-            ${MAN_INSTALL_DIR}/man1)
-    endif()
-endfunction ()
diff --git a/cmake/CreateManPage.cmake b/cmake/CreateManPage.cmake
deleted file mode 100644 (file)
index f27b23b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#Create a single man page. Used by CreateManPage.cmake
-execute_process(COMMAND ${EXENAME} -quiet -man nroff
-    RESULT_VARIABLE SUCCESS OUTPUT_QUIET ERROR_QUIET)
-if(SUCCESS EQUAL 0)
-    configure_file(${INFILE} ${OUTFILE})
-    file(REMOVE ${INFILE})
-endif()
index 251744f74b245a525d63aebbaf7afc7d9c06a517..f4c7842c8656a3a29be5f02668b5ef0981165092 100644 (file)
@@ -1,10 +1,44 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
+# David van der Spoel, Berk Hess, Erik Lindahl, and including many
+# others, as listed in the AUTHORS file in the top-level source
+# directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version 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.
+
+add_subdirectory(man)
 add_subdirectory(template)
 
-install(DIRECTORY . DESTINATION ${DATA_INSTALL_DIR}
-  COMPONENT data
-  PATTERN "Makefile*" EXCLUDE
-  PATTERN "CMake*" EXCLUDE
-  PATTERN "cmake*" EXCLUDE
-  PATTERN "*~" EXCLUDE
-  PATTERN "template" EXCLUDE
-)
+install(FILES README.tutor README_FreeEnergyModifications.txt
+    DESTINATION ${DATA_INSTALL_DIR}
+    COMPONENT data)
+install(DIRECTORY top
+    DESTINATION ${DATA_INSTALL_DIR}/top
+    COMPONENT data
+    PATTERN "*~" EXCLUDE)
diff --git a/share/man/.gitignore b/share/man/.gitignore
new file mode 100644 (file)
index 0000000..a0e7b5c
--- /dev/null
@@ -0,0 +1,2 @@
+man1
+man7/gromacs.7
diff --git a/share/man/CMakeLists.txt b/share/man/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d6c2f13
--- /dev/null
@@ -0,0 +1,102 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2012,2013, by the GROMACS development team, led by
+# David van der Spoel, Berk Hess, Erik Lindahl, and including many
+# others, as listed in the AUTHORS file in the top-level source
+# directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version 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.
+
+if(NOT SOURCE_IS_SOURCE_DISTRIBUTION)
+    if(NOT CMAKE_CROSSCOMPILING)
+        # Defaults to off to avoid breaking the build.
+        # Can be changed if someone finds a nice solution for cases where the
+        # binary does not execute on the compilation host.
+        option(GMX_BUILD_MANPAGES "Build man pages" OFF)
+        mark_as_advanced(GMX_BUILD_MANPAGES)
+    else()
+        message(STATUS "Building the man pages is not available when "
+            "cross-compiling the developer version from git")
+    endif()
+else()
+    # Make sure source package contains all man pages.
+    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/man1/gmx-view.1")
+        message(FATAL_ERROR "Man pages are missing from source package.")
+    endif()
+endif()
+
+if(GMX_BUILD_MANPAGES)
+    # create gromacs.7
+    FILE(READ "${CMAKE_SOURCE_DIR}/admin/programs.txt" contents)
+
+    # Convert file contents into a CMake list. First escape ;
+    STRING(REGEX REPLACE ";" "\\\\;" contents "${contents}")
+    STRING(REGEX REPLACE "\n" ";" contents "${contents}")
+
+    set(PROGMANPAGES "")
+    foreach(line ${contents})
+        if (${line} MATCHES "^HEAD\\|")
+            string(REGEX REPLACE "^HEAD\\|" "" DESC ${line})
+            set(PROGMANPAGES "${PROGMANPAGES}.Sh \"${DESC}\"\n.IX Subsection \"${DESC}\"\n.Vb\n.ta 16n\n")
+        elseif(${line} MATCHES "^END$")
+            set(PROGMANPAGES "${PROGMANPAGES}.Ve\n")
+        elseif(${line} MATCHES "\\|")
+            string(REGEX REPLACE "\\|" "\t" line ${line})
+            set(PROGMANPAGES "${PROGMANPAGES}\\&  ${line}\n")
+        else()
+            message(WARNING "Incorrectly formated line \"${line}\" in programs.txt")
+        endif()
+    endforeach()
+    configure_file(man7/gromacs.7.cmakein man7/gromacs.7)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man7/gromacs.7
+        DESTINATION ${MAN_INSTALL_DIR}/man7
+        COMPONENT man)
+
+    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man1)
+    # TODO: It could be nicer to not do this as part of the ALL target,
+    # but instead on demand as part of make install.
+    add_custom_target(man ALL
+        gmx -quiet help -export man
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        COMMENT "Generating man pages for programs"
+        VERBATIM)
+    install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man1
+        DESTINATION ${MAN_INSTALL_DIR}
+        COMPONENT man)
+    set_directory_properties(PROPERTIES
+        ADDITIONAL_MAKE_CLEAN_FILES man1)
+
+# man pages are only available if they are either build or this is a source archive
+elseif(SOURCE_IS_SOURCE_DISTRIBUTION)
+    install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man7/gromacs.7
+        DESTINATION ${MAN_INSTALL_DIR}/man7
+        COMPONENT man)
+    install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/man1
+        DESTINATION ${MAN_INSTALL_DIR}
+        COMPONENT man)
+endif()
similarity index 98%
rename from man/man7/gromacs.7.cmakein
rename to share/man/man7/gromacs.7.cmakein
index aa17f1f4f9b0dba54e374baee501da34c4ad7d40..829867a4c649bfe5edd012cdff972697a240e75e 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "GROMACS 7"
-.TH GROMACS 7 "${TODAYS_DATE}" "gromacs" "GROMACS suite, Version ${PROJECT_VERSION}"
+.TH GROMACS 7 "" "${PROJECT_VERSION}" "GROMACS Manual"
 .SH "NAME"
 gromacs \- molecular dynamics simulation suite
 .SH "DESCRIPTION"
index 6a551a16afeb174cc81d8a8ab2b9eed7a051aa75..3a5f13644aacf49651295c32fcc3d0a9798c3fa9 100644 (file)
@@ -1,9 +1,6 @@
 configure_file(config.h.cmakein config.h)
 configure_file(buildinfo.h.cmakein buildinfo.h)
 
-if (NOT GMX_BUILD_MDRUN_ONLY)
-    include(../cmake/BuildManPages.cmake)
-endif()
 if (BUILD_TESTING)
     add_custom_target(tests)
     if (GMX_BUILD_UNITTESTS)
index dc3f8eb52beb4ab5a5311b55349fa0cd54bc2ef4..2fbed0342e217a230925b535de59b5f9eaf602d3 100644 (file)
@@ -43,6 +43,7 @@
 
 #include <cstdio>
 
+#include <algorithm>
 #include <map>
 #include <string>
 #include <utility>
@@ -253,6 +254,51 @@ class HelpExportInterface
                                       const CommandLineModuleInterface &module) = 0;
 };
 
+/********************************************************************
+ * HelpExportMan
+ */
+
+/*! \internal \brief
+ * Implements export for man pages.
+ *
+ * \ingroup module_commandline
+ */
+class HelpExportMan : public HelpExportInterface
+{
+    public:
+        virtual void exportModuleHelp(const std::string                &tag,
+                                      const CommandLineModuleInterface &module);
+};
+
+void HelpExportMan::exportModuleHelp(const std::string                &tag,
+                                     const CommandLineModuleInterface &module)
+{
+    File file("man1/" + tag + ".1", "w");
+
+    // TODO: It would be nice to remove the VERSION prefix from the version
+    // string to make it shorter.
+    file.writeLine(formatString(".TH %s 1 \"\" \"%s\" \"GROMACS Manual\"\n",
+                                tag.c_str(),
+                                GromacsVersion()));
+    file.writeLine(".SH NAME");
+    file.writeLine(formatString("%s - %s", tag.c_str(),
+                                module.shortDescription()));
+    file.writeLine();
+
+    CommandLineHelpContext context(&file, eHelpOutputFormat_Man);
+    std::string            displayName(tag);
+    std::replace(displayName.begin(), displayName.end(), '-', ' ');
+    context.setModuleDisplayName(displayName);
+    module.writeHelp(context);
+
+    file.writeLine(".SH SEE ALSO");
+    file.writeLine(".BR gromacs(7)");
+    file.writeLine();
+    file.writeLine("More information about \\fBGROMACS\\fR is available at <\\fIhttp://www.gromacs.org/\\fR>.");
+
+    file.close();
+}
+
 }   // namespace
 
 /********************************************************************
@@ -349,6 +395,11 @@ int CommandLineHelpModule::run(int argc, char *argv[])
     if (!exportFormat.empty())
     {
         boost::scoped_ptr<HelpExportInterface> exporter;
+        if (exportFormat == "man")
+        {
+            exporter.reset(new HelpExportMan);
+        }
+        else
         {
             GMX_THROW(NotImplementedError("This help format is not implemented"));
         }
@@ -483,6 +534,9 @@ class CMainCommandLineModule : public CommandLineModuleInterface
                 case eHelpOutputFormat_Console:
                     type = "help";
                     break;
+                case eHelpOutputFormat_Man:
+                    type = "nroff";
+                    break;
                 default:
                     GMX_THROW(NotImplementedError(
                                       "Command-line help is not implemented for this output format"));
index 6edae6658eda2ae64c6314e13a287d64667932d3..397e78f5ac3e32432e4564bb45d824059f196344 100644 (file)
@@ -57,6 +57,7 @@ class File;
 enum HelpOutputFormat
 {
     eHelpOutputFormat_Console,  //!< Plain text directly on the console.
+    eHelpOutputFormat_Man,      //!< Man page.
     eHelpOutputFormat_NR        //!< Used for the number of output formats.
 };
 //! \endcond
index 4e9e2e848d03fd876b91d19c8b5ec61e44ecb2ff..af7ec6e08f709a2e6da13957c42ad876c9d64487 100644 (file)
@@ -575,12 +575,6 @@ static void write_nroffman(FILE *out,
     int  i;
     char tmp[256];
 
-
-    fprintf(out, ".TH %s 1 \"%s\" \"\" \"GROMACS suite, %s\"\n", program, mydate(tmp, 255), GromacsVersion());
-    fprintf(out, ".SH NAME\n");
-    fprintf(out, "%s@DESC@\n\n", program);
-    fprintf(out, ".B %s\n", GromacsVersion());
-
     fprintf(out, ".SH SYNOPSIS\n");
     fprintf(out, "\\f3%s\\fP\n", program);
 
@@ -665,10 +659,6 @@ static void write_nroffman(FILE *out,
             fprintf(out, "\\- %s\n\n", check_nroff(bugs[i]));
         }
     }
-
-    fprintf(out, ".SH SEE ALSO\n.BR gromacs(7)\n\n");
-    fprintf(out, "More information about \\fBGROMACS\\fR is available at <\\fIhttp://www.gromacs.org/\\fR>.\n");
-
 }
 
 char *check_tty(const char *s)
@@ -1038,7 +1028,8 @@ void write_man(const char *mantp,
     }
     if (strcmp(mantp, "nroff") == 0)
     {
-        write_nroffman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
+        write_nroffman(out, context->moduleDisplayName(), nldesc, desc,
+                       nfile, fnm, npar, par, nbug, bugs, links);
     }
     if (strcmp(mantp, "help") == 0)
     {