Fix that VMD version check was performed for binary not plugin
authorRoland Schulz <roland@utk.edu>
Tue, 3 Jul 2012 00:05:19 +0000 (20:05 -0400)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 26 Jul 2012 00:42:51 +0000 (02:42 +0200)
Gromacs is not using the VMD binary and thus it is not very
insightful to check the VMD binary version. Also checking the VMD
binary version was potential very slow.
The new code tries to find and load one of the VMD plugins and
check the version of the plugin.

Change-Id: Iba7be9cb742c530ce4edb8963597b8ea467e5520

CMakeLists.txt
cmake/FindVMD.cmake
cmake/TestVMD.c [new file with mode: 0644]
src/gmxlib/vmdio.c

index 0eef9de6fd7d448813dcd4914845bd5b2562ec1b..80f305949fea34d8813c2965e6ad42a3e5456cfb 100644 (file)
@@ -857,8 +857,6 @@ mark_as_advanced(GMX_EXTERNAL_LAPACK)
 mark_as_advanced(GMX_EXTERNAL_BLAS)
 
 set(GMX_USE_PLUGINS OFF CACHE INTERNAL "Whether GROMACS will really try to compile support for VMD plugins")
-set(GMX_VMD_PLUGIN_PATH)
-mark_as_advanced(GMX_VMD_PLUGIN_PATH)
 
 if(GMX_LOAD_PLUGINS)
   if(CYGWIN OR NOT WIN32)
@@ -868,49 +866,17 @@ if(GMX_LOAD_PLUGINS)
     gmx_test_dlopen(HAVE_DLOPEN)
   endif()
 
-  find_package(VMD)
-
-  # Test for unsuitable versions of VMD
-
-  if(VMD_FOUND AND NOT GMX_VMD_PLUGIN_PATH)
-    message(STATUS "Checking for suitable VMD version")
-    exec_program(${VMD_EXECUTABLE}
-      ARGS --help
-      OUTPUT_VARIABLE VMD_HELP
-      RETURN_VALUE VMD_EXEC_RETURN)
-
-    if(VMD_EXEC_RETURN EQUAL 0)
-      # This is the accepted idiom for subexpression matching, unfortunately
-      string(REGEX REPLACE ".*VMD for .*, version ([0-9]+\\.[0-9]*\\.?[0-9]*).*" "\\1" VMD_VERSION ${VMD_HELP})
-      string(REGEX REPLACE ".*VMD for (.*), version .*" "\\1" VMD_ARCH ${VMD_HELP})
-
-      if(VMD_VERSION VERSION_LESS "1.8")
-        MESSAGE(WARNING "Found VMD version ${VMD_VERSION}, but GROMACS needs at least 1.8")
-        unset(VMD_EXECUTABLE)
-        set(VMD_FOUND FALSE)
-      else()
-        message(STATUS "VMD version ${VMD_VERSION} is suitable")
-        if(DEFINED ENV{VMDDIR})
-          # This permits GROMACS to avoid hard-coding a fall-back
-          # path that it can tell right now would be useless.
-          set(GMX_VMD_PLUGIN_PATH "$ENV{VMDDIR}/plugins/${VMD_ARCH}/molfile" CACHE PATH "Path to VMD plugins for molfile I/O")
-        else()
-          set(GMX_VMD_PLUGIN_PATH "/usr/local/lib/vmd/plugins/*/molfile" CACHE PATH "Path to VMD plugins for molfile I/O")
-        endif()
-      endif()
-
-      # clean up
-      unset(VMD_HELP)
-      unset(VMD_VERSION)
-      unset(VMD_ARCH)
-    endif()
-  endif()
-
   # so, should we use plug-ins?
   if((WIN32 AND NOT CYGWIN) OR (HAVE_DLOPEN AND BUILD_SHARED_LIBS))
-    if (NOT VMD_QUIETLY)
-      MESSAGE(STATUS "Found the ability to use plug-ins when building shared libaries, so will compile to use plug-ins (e.g. to read VMD-supported file formats).")
-    endif(NOT VMD_QUIETLY)
+    if(NOT VMD_QUIETLY)
+      MESSAGE(STATUS
+          "Found the ability to use plug-ins when building shared libaries, "
+          "so will compile to use plug-ins (e.g. to read VMD-supported file "
+          "formats).")
+    endif()
+    if(NOT GMX_VMD_PLUGIN_PATH)
+      find_package(VMD)
+    endif()
     set(GMX_USE_PLUGINS ON)
     list(APPEND GMX_EXTRA_LIBRARIES ${CMAKE_DL_LIBS}) # magic cross-platform pre-set variable for dlopen library
     set(PKG_DL_LIBS "-l${CMAKE_DL_LIBS}")
index d3e5cf20fc5f888bc1dde0ab8f1fb44baf54224f..29c34dff1debd74b0012d9b2a172e7b7e8eb581a 100644 (file)
@@ -9,94 +9,69 @@
 #  To help us fund GROMACS development, we humbly ask that you cite
 #  the research papers on the package. Check out http://www.gromacs.org
 
-# ================================================================
-
-# This file is adapted from FindGit.cmake from CMake 2.8.5
-# That file is copyright and redistribution outside
-# CMake requires the following license statement.
-
-# ================================================================
-
-# CMake - Cross Platform Makefile Generator
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
-# All rights reserved.
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-
-# * Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-
-# * Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-
-# * Neither the names of Kitware, Inc., the Insight Software Consortium,
-#   nor the names of their contributors may be used to endorse or promote
-#   products derived from this software without specific prior written
-#   permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ------------------------------------------------------------------------------
-
-# The above copyright and license notice applies to distributions of
-# CMake in source and binary form.  Some source files contain additional
-# notices of original copyright by their contributors; see each source
-# for details.  Third-party software packages supplied with CMake under
-# compatible licenses provide their own copyright notices documented in
-# corresponding subdirectories.
-
-# ------------------------------------------------------------------------------
-
-# CMake was initially developed by Kitware with the following sponsorship:
-
-#  * National Library of Medicine at the National Institutes of Health
-#    as part of the Insight Segmentation and Registration Toolkit (ITK).
-
-#  * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
-#    Visualization Initiative.
-
-#  * National Alliance for Medical Image Computing (NAMIC) is funded by the
-#    National Institutes of Health through the NIH Roadmap for Medical Research,
-#    Grant U54 EB005149.
-
-#  * Kitware, Inc.
-
-# ================================================================
 
 # The module defines the following variables:
 #   VMD_EXECUTABLE - path to vmd command
-#   VMD_FOUND - true if the command was found
-# Example usage:
-#   find_package(VMD)
-#   if(VMD_FOUND)
-#     message("vmd found: ${VMD_EXECUTABLE}")
-#   endif()
-
-set(vmd_names vmd)
-
-find_program(VMD_EXECUTABLE
-  NAMES ${vmd_names}
-  PATHS ENV VMDDIR
-  PATH_SUFFIXES bin # I guess this allows for OS-independence
-  DOC "VMD command"
-  )
-mark_as_advanced(VMD_EXECUTABLE)
-
-# Handle the QUIETLY and REQUIRED arguments and set VMD_FOUND to TRUE if
-# all listed variables are TRUE
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(VMD DEFAULT_MSG VMD_EXECUTABLE)
+#   GMX_VMD_PLUGIN_PATH - path to vmd plugins
+
+message(STATUS "Checking for suitable VMD version")
+find_program(VMD_EXECUTABLE NAMES vmd PATH_SUFFIXES bin
+    DOC "VMD command")
+
+#set search path in increasing priority:
+# default path, vmd binary path, enviroment variable
+set(VMD_PATHS "/usr/local/lib/vmd/plugins/*/molfile/")
+if(VMD_EXECUTABLE)
+    file(STRINGS "${VMD_EXECUTABLE}" VMDDIR REGEX "^defaultvmddir=.*$")
+    string(REGEX REPLACE "(^.*=\"?|\"$)" "" VMDDIR "${VMDDIR}")
+    list(INSERT VMD_PATHS 0 "${VMDDIR}/plugins/*/molfile/")
+endif()
+if(NOT "$ENV{VMDDIR}" STREQUAL "")
+    list(INSERT VMD_PATHS 0 "$ENV{VMDDIR}/plugins/*/molfile/")
+endif()
+
+#xyz is just an example. Any other molfile plugin could be used.
+#But some require extra link flags.
+find_library(VMDXYZPLUGIN NAME "xyzplugin${CMAKE_SHARED_LIBRARY_SUFFIX}"
+    PATHS ${VMD_PATHS})
+
+if (VMDXYZPLUGIN)
+    try_run(TESTVMD TESTVMD_COMPILED ${CMAKE_BINARY_DIR}
+        "${CMAKE_SOURCE_DIR}/cmake/TestVMD.c"
+        CMAKE_FLAGS "-DLINK_LIBRARIES=${CMAKE_DL_LIBS}"
+            "-DINCLUDE_DIRECTORIES=${CMAKE_SOURCE_DIR}/src/gmxlib"
+        COMPILE_DEFINITIONS "-DGMX_USE_PLUGINS"
+        RUN_OUTPUT_VARIABLE TESTVMD_OUTPUT ARGS ${VMDXYZPLUGIN})
+endif()
+
+if(NOT TESTVMD EQUAL 0)
+    if (NOT VMDXYZPLUGIN)
+        message(STATUS "VMD plugins not found. Path to VMD can be set with VMDDIR.")
+    elseif(NOT TESTVMD_COMPILED)
+        message(STATUS "Could not compile VMD version check")
+    elseif(TESTVMD EQUAL 1)
+        message(STATUS "Could not load VMD plugin ${VMDXYZPLUGIN}: ${TESTVMD_OUTPUT}")
+    elseif(TESTVMD EQUAL 5)
+        message(STATUS "VMD plugin ${VMDXYZPLUGIN} too old. VMD 1.8.6 required.")
+    else()
+        message(STATUS "Could not identify VMD version of ${VMDXYZPLUGIN}. Error: ${TESTVMD}")
+    endif()
+    # This permits GROMACS to avoid hard-coding a fall-back path.
+    # Fall-back is useful in case VMD is installed later.
+    set(GMX_VMD_PLUGIN_PATH "/usr/local/lib/vmd/plugins/*/molfile"
+        CACHE PATH "Path to VMD plugins for molfile I/O" FORCE)
+else()
+    get_filename_component(VMD_PLUGIN_PATH ${VMDXYZPLUGIN} PATH)
+    message(STATUS "VMD version of ${VMD_PLUGIN_PATH} is suitable")
+    set(GMX_VMD_PLUGIN_PATH ${VMD_PLUGIN_PATH}
+        CACHE PATH "Path to VMD plugins for molfile I/O" FORCE)
+endif()
+mark_as_advanced(GMX_VMD_PLUGIN_PATH)
+#Nothing is rerun unless GMX_VMD_PLUGIN_PATH is set to NO. Clean-up all.
+unset(VMDXYZPLUGIN CACHE)
+unset(VMD_EXECUTABLE CACHE)
+unset(TESTVMD CACHE)
+unset(TESTVMD_COMPILED CACHE)
+unset(VMD_PATHS)
+unset(VMD_PLUGIN_PATH)
+unset(VMDDIR)
diff --git a/cmake/TestVMD.c b/cmake/TestVMD.c
new file mode 100644 (file)
index 0000000..d0618ff
--- /dev/null
@@ -0,0 +1,33 @@
+#include "molfile_plugin.h"
+#include "vmddlopen.c"
+#include "stdio.h"
+
+static int register_cb(void *v, vmdplugin_t *p) {
+    *(molfile_plugin_t**)v = (molfile_plugin_t *)p;
+    return VMDPLUGIN_SUCCESS;
+}
+
+typedef int (*initfunc)(void);
+typedef int (*regfunc)(void *, vmdplugin_register_cb);
+
+/*run: gcc TestVMD.c -DGMX_USE_PLUGINS -Wall -ldl src/gmxlib/vmddlopen.c -I src/gmxlib && ./a.out .../xyzplugin.so ; echo $?*/
+int main(int argc, char** argv)
+{
+    void *handle, *ifunc, *registerfunc;
+    molfile_plugin_t* api;
+    if (argc!=2) return -1;
+    handle = vmddlopen(argv[1]);
+    if (!handle)
+    {
+        fprintf(stderr,"%s\n",vmddlerror());
+        return 1;
+    }
+    ifunc = vmddlsym(handle, "vmdplugin_init");
+    if (!ifunc || ((initfunc)(ifunc))()) return 2;
+    registerfunc = vmddlsym(handle, "vmdplugin_register");
+    if (!registerfunc) return 3;
+    ((regfunc)registerfunc)(&api, register_cb);
+    if (!api) return 4;
+    if (api->abiversion<10) return 5;
+    return 0;
+}
index 9d5405d119562b90d606c3bb26dd5076d9cc6f5c..9782231b205f45c3049d89c4c1ac98176e314ad9 100644 (file)
@@ -123,7 +123,7 @@ static int load_sharedlibrary_plugins(const char *fullpath,t_gmxvmdplugin* vmdpl
     }
 
     ifunc = vmddlsym(handle, "vmdplugin_init");
-    if (ifunc && ((initfunc)(ifunc))()) {
+    if (!ifunc || ((initfunc)(ifunc))()) {
         printf("\nvmdplugin_init() for %s returned an error; plugin(s) not loaded.\n", fullpath);
         vmddlclose(handle);
         return 0;