From 5c50b4be67dbca9ac695ac6dc62cb624fd9d0c9e Mon Sep 17 00:00:00 2001 From: Roland Schulz Date: Mon, 2 Jul 2012 20:05:19 -0400 Subject: [PATCH] Fix that VMD version check was performed for binary not plugin 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 | 52 +++------------ cmake/FindVMD.cmake | 179 ++++++++++++++++++++++------------------------------ cmake/TestVMD.c | 33 ++++++++++ src/gmxlib/vmdio.c | 2 +- 4 files changed, 120 insertions(+), 146 deletions(-) rewrite cmake/FindVMD.cmake (85%) create mode 100644 cmake/TestVMD.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eef9de6fd..80f305949f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") diff --git a/cmake/FindVMD.cmake b/cmake/FindVMD.cmake dissimilarity index 85% index d3e5cf20fc..29c34dff1d 100644 --- a/cmake/FindVMD.cmake +++ b/cmake/FindVMD.cmake @@ -1,102 +1,77 @@ -# This file is part of Gromacs Copyright (c) 1991-2008 -# David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen. - -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. - -# 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) +# This file is part of Gromacs Copyright (c) 1991-2008 +# David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen. + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. + +# To help us fund GROMACS development, we humbly ask that you cite +# the research papers on the package. Check out http://www.gromacs.org + + +# The module defines the following variables: +# VMD_EXECUTABLE - path to vmd command +# 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 index 0000000000..d0618ff927 --- /dev/null +++ b/cmake/TestVMD.c @@ -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; +} diff --git a/src/gmxlib/vmdio.c b/src/gmxlib/vmdio.c index 9d5405d119..9782231b20 100644 --- a/src/gmxlib/vmdio.c +++ b/src/gmxlib/vmdio.c @@ -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; -- 2.11.4.GIT