Merge release-5-0 into master
authorTeemu Murtola <teemu.murtola@gmail.com>
Sat, 5 Jul 2014 16:14:21 +0000 (19:14 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Sat, 5 Jul 2014 16:18:41 +0000 (19:18 +0300)
Change-Id: I9813e3770c78f62c9003987b22c0315c89c87485

21 files changed:
CMakeLists.txt
cmake/gmxGetMsvcTupleWorkaround.cmake [new file with mode: 0644]
cmake/gmxManageFFTLibraries.cmake
install-guide/install-guide.md
src/external/gmock-1.7.0/CMakeLists.txt
src/external/tng_io/BuildTNG.cmake
src/external/tng_io/src/lib/tng_io.c
src/gromacs/CMakeLists.txt
src/gromacs/gmxlib/CMakeLists.txt
src/gromacs/selection/parsetree.cpp
src/gromacs/selection/selectioncollection.cpp
src/gromacs/selection/selelem.cpp
src/gromacs/selection/selelem.h
src/gromacs/selection/selmethod.h
src/gromacs/selection/sm_position.cpp
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesUnsortedIndexGroupsInSelections.xml
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesUnsortedIndexGroupsInSelectionsDelayed.xml [new file with mode: 0644]
src/gromacs/selection/tests/selectioncollection.cpp
src/gromacs/utility/exceptions.h
src/testutils/CMakeLists.txt
src/testutils/TestMacros.cmake

index c5e2a265041b8c349a4372931a2d97e7ea2b37ab..8810d30888ce597373d994f6ce6f8cf0b1b1943e 100644 (file)
@@ -103,9 +103,6 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND UNIX)
     set(CMAKE_INSTALL_PREFIX "/usr/local/gromacs" CACHE STRING "Installation prefix (installation will need write permissions here)" FORCE)
 endif()
 
-set(GMX_INSTALL_PREFIX "" CACHE STRING "Prefix gets appended to CMAKE_INSTALL_PREFIX. For cpack it sets the root folder of the archive.")
-mark_as_advanced(GMX_INSTALL_PREFIX)
-
 include(gmxBuildTypeReference)
 include(gmxBuildTypeProfile)
 include(gmxBuildTypeTSAN)
@@ -564,6 +561,9 @@ if(GMX_EXTERNAL_BOOST AND NOT Boost_FOUND)
         "version of Boost included with Gromacs.")
 endif()
 
+if(NOT DEFINED GMX_BUILD_UNITTESTS AND NOT HAVE_LIBXML2)
+    message(WARNING "libxml2 not found. Will build GROMACS without unit-tests. This is not recommended, because the unit-tests help to verify that GROMACS functions correctly. Most likely you are missing the libxml2-dev(el) package. After you installed it, set GMX_BUILD_UNITTESTS=ON.")
+endif()
 option(GMX_BUILD_UNITTESTS "Build unit tests with BUILD_TESTING (uses Google C++ Testing and Mocking Frameworks, requires libxml2)" ${HAVE_LIBXML2})
 mark_as_advanced(GMX_BUILD_UNITTESTS)
 gmx_add_cache_dependency(GMX_BUILD_UNITTESTS BOOL BUILD_TESTING OFF)
@@ -584,14 +584,14 @@ endif()
 ########################################################################
 
 add_definitions( -DHAVE_CONFIG_H )
-include_directories(${CMAKE_SOURCE_DIR}/src)
-include_directories(${CMAKE_SOURCE_DIR}/src/external/thread_mpi/include)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/thread_mpi/include)
 # Required for config.h, maybe should only be set in src/CMakeLists.txt
-include_directories(${CMAKE_BINARY_DIR}/src)
+include_directories(BEFORE ${CMAKE_BINARY_DIR}/src)
 # Required for gmx_header_config_gen.h to be found before installation
-include_directories(${CMAKE_BINARY_DIR}/src/gromacs/utility)
+include_directories(BEFORE ${CMAKE_BINARY_DIR}/src/gromacs/utility)
 # Required for now to make old code compile
-include_directories(${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
+include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
 
 include(gmxTestInlineASM)
 gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
@@ -793,21 +793,26 @@ set(PKG_CFLAGS "${PKG_CFLAGS} ${OpenMP_C_FLAGS}")
 ########################################################################
 # Specify install locations
 ########################################################################
-# Use GNUInstallDirst to set paths on multiarch systems
+# Use GNUInstallDirs to set paths on multiarch systems.
 include(GNUInstallDirs)
 
+# Customization for the installation tree paths.
 set(GMX_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE STRING
     "Library installation directory (default: ${CMAKE_INSTALL_LIBDIR})")
 set(GMX_DATA_INSTALL_DIR gromacs CACHE STRING
     "Data installation directory under share/ (default: gromacs)")
 mark_as_advanced(GMX_LIB_INSTALL_DIR GMX_DATA_INSTALL_DIR)
 
-set(LIB_INSTALL_DIR  ${GMX_INSTALL_PREFIX}${GMX_LIB_INSTALL_DIR})
-set(BIN_INSTALL_DIR  ${GMX_INSTALL_PREFIX}bin)
-set(DATA_INSTALL_DIR ${GMX_INSTALL_PREFIX}share/${GMX_DATA_INSTALL_DIR})
-set(MAN_INSTALL_DIR  ${GMX_INSTALL_PREFIX}share/man)
-set(INCL_INSTALL_DIR ${GMX_INSTALL_PREFIX}include)
+# These variables are used internally to provide a central location for
+# customizing the install locations.
+set(LIB_INSTALL_DIR  ${GMX_LIB_INSTALL_DIR})
+set(BIN_INSTALL_DIR  bin)
+set(DATA_INSTALL_DIR share/${GMX_DATA_INSTALL_DIR})
+set(MAN_INSTALL_DIR  share/man)
+set(INCL_INSTALL_DIR include)
 
+# These variables get written into config.h for use in finding the data
+# directories.
 set(GMXLIB_SEARCH_DIR share/${GMX_DATA_INSTALL_DIR}/top)
 set(GMXLIB_FALLBACK   ${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/top)
 
@@ -815,12 +820,22 @@ set(GMXLIB_FALLBACK   ${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/top)
 include(gmxManageSuffixes)
 
 ################################################################
-# Shared library settings
+# Shared library load path settings
 ################################################################
-if((NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR ((CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) AND (NOT CMAKE_VERSION VERSION_LESS 2.8.12)))
+# CMake supports RPATH on OS X only from 2.8.12 upwards.
+# CMAKE_SYSTEM_VERSION > 8.0 matches OS X 10.5 and above, where RPATH support
+# was added.
+if((NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR
+   ((CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) AND (NOT CMAKE_VERSION VERSION_LESS 2.8.12)))
+    # The build folder always has bin/ and lib/; if we are also going to
+    # install to lib/, then the installation RPATH works also in the build
+    # tree.  This makes installation slightly faster (no need to rewrite the
+    # RPATHs), and makes the binaries in the build tree relocatable.
     if(GMX_LIB_INSTALL_DIR STREQUAL "lib")
         set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
     endif()
+    # Set the RPATH as relative to the executable location to make the
+    # binaries relocatable.
     if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
         set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${GMX_LIB_INSTALL_DIR}")
     else()
@@ -829,11 +844,13 @@ if((NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") OR ((CMAKE_SYSTEM_VERSION VERSION_G
     set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
     set(CMAKE_MACOSX_RPATH 1)
 else()
-    # We are on Darwin/OSX, and cmake cannot handle proper RPATHs
-    if(CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0) #rpath supported for >10.4
+    # We are on Darwin/OSX, and CMake cannot handle RPATHs automatically.
+    if(CMAKE_SYSTEM_VERSION VERSION_GREATER 8.0)
+        # Set the RPATH options manually.
         set(CMAKE_INSTALL_NAME_DIR "@rpath")
         set(GMX_EXE_LINKER_FLAGS ${GMX_EXE_LINKER_FLAGS} "-Wl,-rpath,@executable_path/../${GMX_LIB_INSTALL_DIR}")
     else()
+        # Use the old INSTALL_NAME_DIR mechanism if RPATH is not supported.
         set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}")
     endif()
 endif()
@@ -846,7 +863,7 @@ if(GMX_EXTERNAL_BOOST)
     include_directories(${Boost_INCLUDE_DIRS})
     set(PKG_CFLAGS "${PKG_CFLAGS} -I${Boost_INCLUDE_DIRS}")
 else()
-    include_directories(${CMAKE_SOURCE_DIR}/src/external/boost)
+    include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/boost)
     # typeid not supported for minimal internal version
     # (would add significant amount of code)
     add_definitions(-DBOOST_NO_TYPEID)
diff --git a/cmake/gmxGetMsvcTupleWorkaround.cmake b/cmake/gmxGetMsvcTupleWorkaround.cmake
new file mode 100644 (file)
index 0000000..7096174
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 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.
+#
+# 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.
+
+# GMock uses tuples extensively, and MSVC bundles a tuple library that
+# is not compatible with the standard. r675 of googletest works around
+# this properly, but that's not in GMock 1.7.0. That logic is
+# duplicated here. See
+# https://code.google.com/p/googletest/source/detail?r=675#, but note
+# that its summary does not represent its code correctly.
+#
+# This function should be called to get the compile definitions
+# suitable for working around MSVC to compile GMock, if any.
+# Returns a string of options in VARIABLE
+function(GET_MSVC_TUPLE_WORKAROUND_DEFINITIONS VARIABLE)
+    set(${VARIABLE} "")
+    if(MSVC AND MSVC_VERSION VERSION_EQUAL 1700)
+        # Fixes Visual Studio 2012
+        set(${VARIABLE} "_VARIADIC_MAX=10")
+    endif()
+    set(${VARIABLE} ${${VARIABLE}} PARENT_SCOPE)
+endfunction()
index 4bbfc2df4e94ce5baf9661ff73fe7d87a5046c1c..104576d4b3a6c3932f1df3e88ee62a6e2eaa33a0 100644 (file)
@@ -77,7 +77,11 @@ if(${GMX_FFT_LIBRARY} STREQUAL "FFTW3")
     endif()
 
     set(PKG_FFT "${${FFTW}_PKG}")
-    include_directories(${${FFTW}_INCLUDE_DIRS})
+    if (GMX_BUILD_OWN_FFTW)
+        include_directories(BEFORE ${${FFTW}_INCLUDE_DIRS})
+    else()
+        include_directories(${${FFTW}_INCLUDE_DIRS})
+    endif()
     set(FFT_LIBRARIES ${${FFTW}_LIBRARIES})
     set(GMX_FFT_FFTW3 1)
 
index 2b19bcf0dfda9d9e0a20187698b826680e4be7da..84481d005977e21e96c7354ae806ad4d9707ce3d 100644 (file)
@@ -13,7 +13,7 @@ at <http://www.gromacs.org/Documentation/Installation_Instructions>.
 3. Get and unpack the latest version of the GROMACS tarball.
 4. Make a separate build directory and change to it. 
 5. Run `cmake` with the path to the source as an argument
-6. Run `make` and `make install`
+6. Run `make`, `make test`, and `make install`
 
 Or, as a sequence of commands to execute:
 
@@ -21,8 +21,9 @@ Or, as a sequence of commands to execute:
     cd gromacs-@PROJECT_VERSION@
     mkdir build
     cd build
-    cmake .. -DGMX_BUILD_OWN_FFTW=ON
+    cmake .. -DGMX_BUILD_OWN_FFTW=ON -DREGRESSIONTEST_DOWNLOAD=ON
     make
+    make test
     sudo make install
     source /usr/local/gromacs/bin/GMXRC
 
@@ -360,9 +361,8 @@ general advice on what you are seeing and how to navigate and change
 things. The settings you might normally want to change are already
 presented. You may make changes, then re-configure (using `c`), so that it
 gets a chance to make changes that depend on yours and perform more
-checking. This might require several configuration stages when you are
-using `ccmake` - when you are using `cmake` the
-iteration is done behind the scenes.
+checking. It may take several configuration passes to reach the desired
+configuration, in particular if you need to resolve errors.
 
 A key thing to consider here is the setting of
 `CMAKE_INSTALL_PREFIX`. You will need to be able to write to this
@@ -374,9 +374,11 @@ home directory for your GROMACS installation. Even if you do have
 super-user privileges, you should use them only for the installation
 phase, and never for configuring, building, or running GROMACS!
 
-When `cmake` or `ccmake` have completed iterating, the
-cache is stable and a build tree can be generated, with `g` in
-`ccmake` or automatically with `cmake`.
+When you have reached the desired configuration with `ccmake`, the
+build system can be generated by pressing `g`.  This requires that the previous
+configuration pass did not reveal any additional settings (if it did, you need
+to configure once more with `c`).  With `cmake`, the build system is generated
+after each pass that does not produce errors.
 
 You cannot attempt to change compilers after the initial run of
 `cmake`. If you need to change, clean up, and start again.
@@ -633,6 +635,36 @@ programs and libraries, one might specify:
 Thus the names of all programs and libraries will be appended with
 `_mod`.
 
+### Changing installation tree structure ###
+
+By default, a few different directories under `CMAKE_INSTALL_PREFIX` are used
+when when GROMACS is installed. Some of these can be changed, which is mainly
+useful for packaging GROMACS for various distributions. The directories are
+listed below, with additional notes about some of them. Unless otherwise noted,
+the directories can be renamed by editing the installation paths in the main
+CMakeLists.txt.
+
+`bin/`
+  : The standard location for executables, some scripts, and some symlinks.
+    Some of the scripts hardcode the absolute installation prefix, which needs
+    to be changed if the scripts are relocated.
+`include/gromacs/`
+  : The standard location for installed headers.
+`lib/`
+  : The standard location for libraries. The default depends on the system, and
+    is determined by CMake.
+    The name of the directory can be changed using `GMX_LIB_INSTALL_DIR` CMake
+    variable.
+`share/gromacs/`
+  : Various data files and some documentation go here.
+    The `gromacs` part can be changed using `GMX_DATA_INSTALL_DIR`. Using this
+    CMake variable is the preferred way of changing the installation path for
+    `share/gromacs/top/`, since the path to this directory is built into
+    `libgromacs` as well as some scripts, both as a relative and as an absolute
+    path (the latter as a fallback if everything else fails).
+`share/man/`
+  : Installed man pages go here.
+
 ## Building GROMACS ##
 
 Once you have configured with `cmake`, you can build GROMACS. It is
index 99b6f7da69015ce20b957e3bb411a78004b123b2..3cb202bfd0ec27f7c3de5b58d0c84a95d330c74d 100644 (file)
 # As stated in README.Gromacs, this file is not part of GMock, but is written
 # specifically for the GROMACS build system from scratch.
 
+include(gmxGetMsvcTupleWorkaround)
+get_msvc_tuple_workaround_definitions(GMOCK_COMPILE_DEFINITIONS)
+set(GMOCK_COMPILE_DEFINITIONS ${GMOCK_COMPILE_DEFINITIONS} PARENT_SCOPE)
+
 # GTest/GMock suggest linking with pthreads when available for thread safety
 set(CMAKE_THREAD_PREFER_PTHREAD 1)
 find_package(Threads)
@@ -51,11 +55,12 @@ set(GMOCK_SOURCES ${GMOCK_DIR}/src/gmock-all.cc)
 set(GTEST_INCLUDE_DIRS ${GTEST_DIR}/include)
 set(GMOCK_INCLUDE_DIRS ${GMOCK_DIR}/include ${GTEST_INCLUDE_DIRS})
 
-include_directories(${GTEST_INCLUDE_DIRS})
-include_directories(${GTEST_DIR})
-include_directories(${GMOCK_INCLUDE_DIRS})
-include_directories(${GMOCK_DIR})
+include_directories(BEFORE ${GTEST_INCLUDE_DIRS})
+include_directories(BEFORE ${GTEST_DIR})
+include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
+include_directories(BEFORE ${GMOCK_DIR})
 add_library(gmock STATIC ${GMOCK_SOURCES} ${GTEST_SOURCES})
+set_property(TARGET gmock APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
 
 set(GMOCK_LIBRARIES gmock ${PTHREADS_LIBRARIES} PARENT_SCOPE)
 set(GTEST_LIBRARIES ${GMOCK_LIBRARIES} PARENT_SCOPE)
index f4f2caf1d413fa872dcda7843616366bebb3f36f..ea77430cf92c228b80425a7db2d486884fb8e21e 100644 (file)
@@ -5,7 +5,7 @@ set(TNG_ROOT_BINARY_DIR ${CMAKE_BINARY_DIR}/${TNG_ROOT_BINARY_DIR})
 function (TNG_GENERATE_VERSION_H)
     set(TNG_MAJOR_VERSION "1")
     set(TNG_MINOR_VERSION "6")
-    set(TNG_VERSION_PATCH_LEVEL "0")
+    set(TNG_VERSION_PATCH_LEVEL "1")
     set(TNG_IO_VERSION "${TNG_MAJOR_VERSION}.${TNG_MINOR_VERSION}.${TNG_VERSION_PATCH_LEVEL}")
     set(TNG_API_VERSION "6")
     configure_file(${TNG_ROOT_SOURCE_DIR}/include/tng/version.h.in
@@ -23,8 +23,8 @@ include(CheckIncludeFile)
 check_include_file(inttypes.h TNG_HAVE_INTTYPES_H)
 
 macro(TNG_GET_SOURCE_LIST TNG_SOURCELIST TNG_COMPILEDEFS)
-    include_directories(${TNG_ROOT_SOURCE_DIR}/include)
-    include_directories(${TNG_ROOT_BINARY_DIR}/include)
+    include_directories(BEFORE ${TNG_ROOT_SOURCE_DIR}/include)
+    include_directories(BEFORE ${TNG_ROOT_BINARY_DIR}/include)
     set(_tng_compression_sources bwlzh.c bwt.c coder.c dict.c fixpoint.c huffman.c huffmem.c lz77.c merge_sort.c mtf.c rle.c tng_compress.c vals16.c warnmalloc.c widemuldiv.c xtc2.c xtc3.c)
     set(_tng_io_sources tng_io.c md5.c)
     set(${TNG_SOURCELIST})
index 792be2e92900f5d1e17a3f4167e7464e3426750e..d0028bd69fcd17cd1943608cb8c4a9eb0ed0b465 100644 (file)
@@ -11525,7 +11525,7 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
     int64_t long_stride_length, medium_stride_length;
     long file_pos, orig_frame_set_file_pos;
     tng_trajectory_frame_set_t frame_set;
-    struct tng_trajectory_frame_set   orig_frame_set;
+    struct tng_trajectory_frame_set orig_frame_set;
     tng_gen_block_t block;
     tng_function_status stat;
     int64_t cnt = 0;
@@ -11540,6 +11540,12 @@ tng_function_status DECLSPECDLLEXPORT tng_num_frame_sets_get
     orig_frame_set_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
     file_pos = (long)tng_data->first_trajectory_frame_set_input_file_pos;
 
+    if(file_pos < 0)
+    {
+        *n = tng_data->n_trajectory_frame_sets = cnt;
+        return(TNG_SUCCESS);
+    }
+
     tng_block_init(&block);
     fseek(tng_data->input_file,
           file_pos,
@@ -16903,7 +16909,12 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open
         /* Read the file headers */
         tng_file_headers_read(*tng_data_p, TNG_USE_HASH);
 
-        tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+        stat = tng_num_frame_sets_get(*tng_data_p, &(*tng_data_p)->n_trajectory_frame_sets);
+
+        if(stat != TNG_SUCCESS)
+        {
+            return(stat);
+        }
     }
 
     if(mode == 'w')
@@ -17368,6 +17379,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
                 {
                     return(stat);
                 }
+                if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+                {
+                    return(TNG_FAILURE);
+                }
                 i = frame_set->first_frame;
             }
         }
@@ -17528,6 +17543,10 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
                 {
                     return(stat);
                 }
+                if(frame_set->first_frame + frame_set->n_frames - 1 < i)
+                {
+                    return(TNG_FAILURE);
+                }
                 i = frame_set->first_frame;
             }
         }
index 1fb48645be4cd6f7da47181232e85d8760be2093..3536e4711101a56e67a0782640537408d5150891 100644 (file)
@@ -75,7 +75,7 @@ if(GMX_USE_TNG)
     endif()
 else()
     # We still need to get tng/tng_io_fwd.h from somewhere!
-    include_directories(${CMAKE_SOURCE_DIR}/src/external/tng_io/include)
+    include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/tng_io/include)
 endif()
 
 add_subdirectory(gmxlib)
index c84bbcfcfc9f141da1497d3216f87183df490ed7..5c919622bf1566a9ebb5bbbc66fa2ff32c23b919 100644 (file)
@@ -32,7 +32,7 @@
 # To help us fund GROMACS development, we humbly ask that you cite
 # the research papers on the package. Check out http://www.gromacs.org.
 
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
 
 add_subdirectory(nonbonded)
 
index 51a8f0646aae3af0f9e499052e623b76bc4ed963..14f55a9a6aac7f521e5e61b5a8b4e49dbd04b8c4 100644 (file)
@@ -1001,6 +1001,12 @@ _gmx_sel_init_selection(const char                             *name,
     }
     /* Update the flags */
     _gmx_selelem_update_flags(root);
+    gmx::ExceptionInitializer errors("Invalid index group reference(s)");
+    root->checkUnsortedAtoms(true, &errors);
+    if (errors.hasNestedExceptions())
+    {
+        GMX_THROW(gmx::InconsistentInputError(errors));
+    }
 
     root->fillNameIfMissing(_gmx_sel_lexer_pselstr(scanner));
 
@@ -1040,28 +1046,34 @@ _gmx_sel_assign_variable(const char                             *name,
     {
         /* If so, just assign the constant value to the variable */
         sc->symtab->addVariable(name, expr);
-        goto finish;
     }
     /* Check if we are assigning a variable to another variable */
-    if (expr->type == SEL_SUBEXPRREF)
+    else if (expr->type == SEL_SUBEXPRREF)
     {
         /* If so, make a simple alias */
         sc->symtab->addVariable(name, expr->child);
-        goto finish;
     }
-    /* Create the root element */
-    root.reset(new SelectionTreeElement(SEL_ROOT));
-    root->setName(name);
-    /* Create the subexpression element */
-    root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
-    root->child->setName(name);
-    _gmx_selelem_set_vtype(root->child, expr->v.type);
-    root->child->child  = expr;
-    /* Update flags */
-    _gmx_selelem_update_flags(root);
-    /* Add the variable to the symbol table */
-    sc->symtab->addVariable(name, root->child);
-finish:
+    else
+    {
+        /* Create the root element */
+        root.reset(new SelectionTreeElement(SEL_ROOT));
+        root->setName(name);
+        /* Create the subexpression element */
+        root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
+        root->child->setName(name);
+        _gmx_selelem_set_vtype(root->child, expr->v.type);
+        root->child->child  = expr;
+        /* Update flags */
+        _gmx_selelem_update_flags(root);
+        gmx::ExceptionInitializer errors("Invalid index group reference(s)");
+        root->checkUnsortedAtoms(true, &errors);
+        if (errors.hasNestedExceptions())
+        {
+            GMX_THROW(gmx::InconsistentInputError(errors));
+        }
+        /* Add the variable to the symbol table */
+        sc->symtab->addVariable(name, root->child);
+    }
     srenew(sc->varstrs, sc->nvars + 1);
     sc->varstrs[sc->nvars] = strdup(pselstr);
     ++sc->nvars;
index 577707488d31182b04bc65cbb2c7fb9a2651825b..5b522a1ef45fac14430517a509bd80a7944cfacc 100644 (file)
@@ -568,11 +568,12 @@ SelectionCollection::setIndexGroups(gmx_ana_indexgrps_t *grps)
     impl_->grps_               = grps;
     impl_->bExternalGroupsSet_ = true;
 
-    ExceptionInitializer        errors("Unknown index group references encountered");
+    ExceptionInitializer        errors("Invalid index group reference(s)");
     SelectionTreeElementPointer root = impl_->sc_.root;
     while (root)
     {
         impl_->resolveExternalGroups(root, &errors);
+        root->checkUnsortedAtoms(true, &errors);
         root = root->next;
     }
     if (errors.hasNestedExceptions())
index e80e4f75c8d241d946505ec85d6e5901a2666206..a10d5a5802af892480c4664f5984b2e459165660 100644 (file)
@@ -53,6 +53,7 @@
 #include "keywords.h"
 #include "mempool.h"
 #include "selelem.h"
+#include "selmethod.h"
 
 /*!
  * \param[in] sel Selection for which the string is requested
@@ -328,6 +329,43 @@ void SelectionTreeElement::fillNameIfMissing(const char *selectionText)
     }
 }
 
+void SelectionTreeElement::checkUnsortedAtoms(
+        bool bUnsortedAllowed, ExceptionInitializer *errors) const
+{
+    const bool bUnsortedSupported
+        = (type == SEL_CONST && v.type == GROUP_VALUE)
+            || type == SEL_ROOT || type == SEL_SUBEXPR || type == SEL_SUBEXPRREF
+            // TODO: Consolidate.
+            || type == SEL_MODIFIER
+            || (type == SEL_EXPRESSION && (u.expr.method->flags & SMETH_ALLOW_UNSORTED));
+
+    // TODO: For some complicated selections, this may result in the same
+    // index group reference being flagged as an error multiple times for the
+    // same selection.
+    SelectionTreeElementPointer child = this->child;
+    while (child)
+    {
+        child->checkUnsortedAtoms(bUnsortedAllowed && bUnsortedSupported,
+                                  errors);
+        child = child->next;
+    }
+
+    // The logic here is simplified by the fact that only constant groups can
+    // currently be the root cause of SEL_UNSORTED being set, so only those
+    // need to be considered in triggering the error.
+    if (!bUnsortedAllowed && (flags & SEL_UNSORTED)
+        && type == SEL_CONST && v.type == GROUP_VALUE)
+    {
+        std::string message = formatString(
+                    "Group '%s' cannot be used in selections except "
+                    "as a full value of the selection, "
+                    "because atom indices in it are not sorted and/or "
+                    "it contains duplicate atoms.",
+                    name().c_str());
+        errors->addNested(InconsistentInputError(message));
+    }
+}
+
 void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
 {
     GMX_RELEASE_ASSERT(type == SEL_GROUPREF,
@@ -366,16 +404,6 @@ void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
     if (!gmx_ana_index_check_sorted(&foundGroup))
     {
         flags |= SEL_UNSORTED;
-        // TODO: Add this test elsewhere, where it does not break valid use cases.
-#if 0
-        gmx_ana_index_deinit(&foundGroup);
-        std::string message = formatString(
-                    "Group '%s' ('%s') cannot be used in selections, "
-                    "because atom indices in it are not sorted and/or "
-                    "it contains duplicate atoms.",
-                    foundName.c_str(), name().c_str());
-        GMX_THROW(InconsistentInputError(message));
-#endif
     }
 
     sfree(u.gref.name);
index 2acdb5bae7d42236d3155b8bb1fc9bda920050c4..13c0e949f8314aaada316df89d35fc65dd11ea6d 100644 (file)
@@ -237,6 +237,8 @@ _gmx_sel_value_type_str(const gmx_ana_selvalue_t *val);
 namespace gmx
 {
 
+class ExceptionInitializer;
+
 /*! \brief
  * Function pointer for evaluating a gmx::SelectionTreeElement.
  */
@@ -323,6 +325,19 @@ class SelectionTreeElement
          */
         void fillNameIfMissing(const char *selectionText);
 
+        /*! \brief
+         * Checks that this element and its children do not contain unsupported
+         * elements with unsorted atoms.
+         *
+         * \param[in] bUnsortedAllowed Whether this element's parents allow it
+         *     to have unsorted atoms.
+         * \param     errors           Object for reporting any error messages.
+         * \throws    std::bad_alloc if out of memory.
+         *
+         * Errors are reported as nested exceptions in \p errors.
+         */
+        void checkUnsortedAtoms(bool                  bUnsortedAllowed,
+                                ExceptionInitializer *errors) const;
         /*! \brief
          * Resolved an unresolved reference to an index group.
          *
index 3a2167d797783e4e33d155d1656dee2467a87d53..538c94db175bc6b88ed05403fda9811285fa9a31 100644 (file)
@@ -91,6 +91,9 @@
  *  - \ref SMETH_MODIFIER : If set, the method is a selection modifier and
  *    not an actual selection method.
  *    For more details, see \ref selmethods_modifiers.
+ *  - \ref SMETH_ALLOW_UNSORTED : If set, the method supports unsorted atoms
+ *    in its input parameters. \ref SMETH_MODIFIER methods are assumed to always
+ *    support unsorted atoms, as their purpose is to affect the ordering.
  *
  * There are two additional flags that specify the number of values the
  * method returns. Only one of them can be set at a time.
@@ -345,6 +348,15 @@ struct t_trxframe;
  * the string pointers.
  */
 #define SMETH_CHARVAL    64
+/*! \brief
+ * If set, the method accepts unsorted atoms in its input parameters.
+ *
+ * Currently, the support for this functionality is fairly limited, and only
+ * static index group references can actually contain unsorted atoms.
+ * But to make this single case work, the position evaluation must support
+ * unsorted atoms as well.
+ */
+#define SMETH_ALLOW_UNSORTED 128
 /*! \brief
  * If set, the method is a selection modifier.
  *
index aeeb9573c4c2616ad17cb856b22a732e7388901b..31f3c0a8b2dd9c6f84182d5255be263680eecf43 100644 (file)
@@ -142,7 +142,7 @@ static gmx_ana_selparam_t smparams_com[] = {
 
 /** Selection method data for position keyword evaluation. */
 gmx_ana_selmethod_t sm_keyword_pos = {
-    "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL,
+    "kw_pos", POS_VALUE, SMETH_DYNAMIC | SMETH_VARNUMVAL | SMETH_ALLOW_UNSORTED,
     asize(smparams_keyword_pos), smparams_keyword_pos,
     &init_data_pos,
     &set_poscoll_pos,
index ddcda26bc4aaa0b116f666abafee6be0e98b270f..cc54442ee6b41ebd6748db90dd2807739ab77c16 100644 (file)
@@ -2,6 +2,9 @@
 <?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
 <ReferenceData>
   <ParsedSelections Name="Parsed">
+    <ParsedVariable Name="Variable1">
+      <String Name="Input">foo = group "GrpUnsorted"</String>
+    </ParsedVariable>
     <ParsedSelection Name="Selection1">
       <String Name="Input">group "GrpUnsorted"</String>
       <String Name="Name">GrpUnsorted</String>
       <String Name="Text">group "GrpUnsorted" permute 2 1</String>
       <Bool Name="Dynamic">false</Bool>
     </ParsedSelection>
+    <ParsedSelection Name="Selection6">
+      <String Name="Input">foo</String>
+      <String Name="Name">foo</String>
+      <String Name="Text">foo</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
   </ParsedSelections>
   <CompiledSelections Name="Compiled">
     <Selection Name="Selection1">
         </Position>
       </Sequence>
     </Selection>
+    <Selection Name="Selection6">
+      <String Name="Name">foo</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">8</Int>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>0</Int>
+          </Sequence>
+          <Int Name="RefId">0</Int>
+          <Int Name="MappedId">0</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>2</Int>
+          </Sequence>
+          <Int Name="RefId">1</Int>
+          <Int Name="MappedId">2</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>1</Int>
+          </Sequence>
+          <Int Name="RefId">2</Int>
+          <Int Name="MappedId">1</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>8</Int>
+          </Sequence>
+          <Int Name="RefId">3</Int>
+          <Int Name="MappedId">8</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>6</Int>
+          </Sequence>
+          <Int Name="RefId">4</Int>
+          <Int Name="MappedId">6</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>4</Int>
+          </Sequence>
+          <Int Name="RefId">5</Int>
+          <Int Name="MappedId">4</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>2</Int>
+          </Sequence>
+          <Int Name="RefId">6</Int>
+          <Int Name="MappedId">2</Int>
+        </Position>
+        <Position>
+          <Sequence Name="Atoms">
+            <Int Name="Length">1</Int>
+            <Int>11</Int>
+          </Sequence>
+          <Int Name="RefId">7</Int>
+          <Int Name="MappedId">11</Int>
+        </Position>
+      </Sequence>
+    </Selection>
   </CompiledSelections>
 </ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesUnsortedIndexGroupsInSelectionsDelayed.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_HandlesUnsortedIndexGroupsInSelectionsDelayed.xml
new file mode 100644 (file)
index 0000000..c7fd97c
--- /dev/null
@@ -0,0 +1,119 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <ParsedSelections Name="Parsed">
+    <ParsedVariable Name="Variable1">
+      <String Name="Input">foo = group "GrpUnsorted"</String>
+    </ParsedVariable>
+    <ParsedSelection Name="Selection1">
+      <String Name="Input">group "GrpUnsorted"</String>
+      <String Name="Text">group "GrpUnsorted"</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection2">
+      <String Name="Input">GrpUnsorted</String>
+      <String Name="Text">GrpUnsorted</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection3">
+      <String Name="Input">2</String>
+      <String Name="Text">2</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection4">
+      <String Name="Input">res_cog of group "GrpUnsorted"</String>
+      <String Name="Text">res_cog of group "GrpUnsorted"</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection5">
+      <String Name="Input">group "GrpUnsorted" permute 2 1</String>
+      <String Name="Text">group "GrpUnsorted" permute 2 1</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection6">
+      <String Name="Input">foo</String>
+      <String Name="Text">foo</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+  </ParsedSelections>
+  <CompiledSelections Name="Compiled">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>2</Int>
+        <Int>0</Int>
+        <Int>8</Int>
+        <Int>1</Int>
+        <Int>4</Int>
+        <Int>6</Int>
+        <Int>11</Int>
+        <Int>2</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection6">
+      <Sequence Name="Atoms">
+        <Int Name="Length">8</Int>
+        <Int>0</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>8</Int>
+        <Int>6</Int>
+        <Int>4</Int>
+        <Int>2</Int>
+        <Int>11</Int>
+      </Sequence>
+    </Selection>
+  </CompiledSelections>
+</ReferenceData>
index 500bfa5aae4f332d67a7886d10add05b1c1e3277..8cfcae13c6e8ce846aa954aa68c2629698461da6 100644 (file)
@@ -488,21 +488,26 @@ TEST_F(SelectionCollectionTest, HandlesUnknownGroupReferenceDelayed2)
     EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
 }
 
-// TODO: Make the check less eager so that it doesn't break other tests, and
-// adapt these tests accordingly.
-TEST_F(SelectionCollectionTest, DISABLED_HandlesUnsortedGroupReference)
+TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReference)
 {
     ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
-    EXPECT_THROW_GMX(sc_.parseFromString("group \"GrpUnsorted\""),
+    EXPECT_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""),
+                     gmx::InconsistentInputError);
+    EXPECT_THROW_GMX(sc_.parseFromString("group 2 or atomnr 2 to 5"),
+                     gmx::InconsistentInputError);
+    EXPECT_THROW_GMX(sc_.parseFromString("within 1 of group 2"),
                      gmx::InconsistentInputError);
-    EXPECT_THROW_GMX(sc_.parseFromString("2"), gmx::InconsistentInputError);
 }
 
-TEST_F(SelectionCollectionTest, DISABLED_HandlesUnsortedGroupReferenceDelayed)
+TEST_F(SelectionCollectionTest, HandlesUnsortedGroupReferenceDelayed)
 {
-    ASSERT_NO_THROW_GMX(sc_.parseFromString("group 2; group \"GrpUnsorted\""));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group \"GrpUnsorted\""));
+    ASSERT_NO_THROW_GMX(sc_.parseFromString("atomnr 1 to 3 and group 2"));
     EXPECT_THROW_GMX(loadIndexGroups("simple.ndx"), gmx::InconsistentInputError);
-    EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
+    // TODO: Add a separate check in the selection compiler for a safer API
+    // (makes sense in the future if the compiler needs the information for
+    // other purposes as well).
+    // EXPECT_THROW_GMX(sc_.compile(), gmx::APIError);
 }
 
 TEST_F(SelectionCollectionTest, RecoversFromMissingMoleculeInfo)
@@ -930,11 +935,13 @@ TEST_F(SelectionCollectionDataTest, HandlesIndexGroupsInSelectionsDelayed)
 TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelections)
 {
     static const char * const selections[] = {
+        "foo = group \"GrpUnsorted\"",
         "group \"GrpUnsorted\"",
         "GrpUnsorted",
         "2",
         "res_cog of group \"GrpUnsorted\"",
-        "group \"GrpUnsorted\" permute 2 1"
+        "group \"GrpUnsorted\" permute 2 1",
+        "foo"
     };
     setFlags(TestFlags() | efTestPositionAtoms | efTestPositionMapping
              | efTestSelectionNames);
@@ -942,6 +949,23 @@ TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelections)
     runTest("simple.gro", selections);
 }
 
+TEST_F(SelectionCollectionDataTest, HandlesUnsortedIndexGroupsInSelectionsDelayed)
+{
+    static const char * const selections[] = {
+        "foo = group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\"",
+        "GrpUnsorted",
+        "2",
+        "res_cog of group \"GrpUnsorted\"",
+        "group \"GrpUnsorted\" permute 2 1",
+        "foo"
+    };
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+}
+
 TEST_F(SelectionCollectionDataTest, HandlesConstantPositions)
 {
     static const char * const selections[] = {
index 0425dc6d5bffe5200e7b944d15642e30cbd77cdb..ace7b66224c830146d2d9bc503b8f3e840234987 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2011,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.
@@ -135,6 +135,21 @@ class ExceptionInitializer
         {
             nested_.push_back(boost::current_exception());
         }
+        /*! \brief
+         * Adds the specified exception as a nested exception.
+         *
+         * May be called multiple times; all provided exceptions will be added
+         * in a list of nested exceptions.
+         *
+         * This is equivalent to throwing \p ex and calling
+         * addCurrentExceptionAsNested() in the catch block, but potentially
+         * more efficient.
+         */
+        template <class Exception>
+        void addNested(const Exception &ex)
+        {
+            nested_.push_back(boost::copy_exception(ex));
+        }
 
     private:
         std::string                     reason_;
index 1faf43cd4e35345e984005ff86d246dff068373a..8dd207ad0ea12ed3f663fbd7ebda41d942435602 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2011,2012,2013, by the GROMACS development team, led by
+# Copyright (c) 2011,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.
 
-include_directories(${GMOCK_INCLUDE_DIRS})
+include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
 include_directories(${LIBXML2_INCLUDE_DIR})
 file(GLOB TESTUTILS_SOURCES *.cpp)
 
 add_library(testutils STATIC ${TESTUTILS_SOURCES})
 set(TESTUTILS_LIBS testutils ${GMOCK_LIBRARIES} ${LIBXML2_LIBRARIES})
+set_property(TARGET testutils APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
 target_link_libraries(testutils libgromacs ${GMOCK_LIBRARIES} ${LIBXML2_LIBRARIES})
 
 set(TESTUTILS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
index daf252cb2823057f29551926f32d60fd58c24aaa..3c8425962ee3c106e323875b1968128deffa09c2 100644 (file)
 
 function (gmx_add_unit_test_object_library NAME)
     if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
-        include_directories(${GMOCK_INCLUDE_DIRS})
+        include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
         add_library(${NAME} OBJECT ${ARGN})
+        set_property(TARGET ${NAME} APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
     endif()
 endfunction ()
 
 function (gmx_build_unit_test NAME EXENAME)
     if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
-        include_directories(${GMOCK_INCLUDE_DIRS})
+        include_directories(BEFORE ${GMOCK_INCLUDE_DIRS})
         add_executable(${EXENAME} ${ARGN} ${TESTUTILS_DIR}/unittest_main.cpp)
+        set_property(TARGET ${EXENAME} APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS}")
         target_link_libraries(${EXENAME} libgromacs ${TESTUTILS_LIBS} ${GMOCK_LIBRARIES} ${GMX_EXE_LINKER_FLAGS})
         set(_temporary_files_path "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary")
         file(MAKE_DIRECTORY ${_temporary_files_path})