Add initial support for python bindings
[alexxy/gromacs.git] / cmake / gmxManageGPU.cmake
index ba3c5b476121c2d6643ab9c861d25e6940d1b25a..69cbd5916d925fd1ec05b509d3bac4a1819ae34e 100644 (file)
@@ -1,10 +1,10 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2012, 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.
+# 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.
 #
 # GROMACS is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public License
@@ -31,7 +31,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.
-#
+
 # If the user did not set GMX_GPU we'll consider this option to be
 # in "auto" mode meaning that we will:
 # - search for CUDA and set GMX_GPU=ON we find it
@@ -64,11 +64,23 @@ if(GMX_GPU OR GMX_GPU_AUTO)
         # Noise is acceptable when there is a GPU or the user required one.
         set(FIND_CUDA_QUIETLY QUIET)
     endif()
-    # We support CUDA >=v3.2 on *nix, but <= v4.1 doesn't work with MSVC
-    if(MSVC)
-        find_package(CUDA 4.1 ${FIND_CUDA_QUIETLY})
-    else()
-        find_package(CUDA 3.2 ${FIND_CUDA_QUIETLY})
+    find_package(CUDA ${REQUIRED_CUDA_VERSION} ${FIND_CUDA_QUIETLY})
+
+    # Cmake 2.8.12 (and CMake 3.0) introduced a new bug where the cuda
+    # library dir is added twice as an rpath on APPLE, which in turn causes
+    # the install_name_tool to wreck the binaries when it tries to remove this
+    # path. Since this is set inside the cuda module, we remove the extra rpath
+    # added in the library string - an rpath is not a library anyway, and at
+    # least for Gromacs this works on all CMake versions. This should be
+    # reasonably future-proof, since newer versions of CMake appear to handle
+    # the rpath automatically based on the provided library path, meaning
+    # the explicit rpath specification is no longer needed.
+    if(APPLE AND (CMAKE_VERSION VERSION_GREATER 2.8.11))
+        foreach(elem ${CUDA_LIBRARIES})
+            if(elem MATCHES "-Wl,.*")
+                list(REMOVE_ITEM CUDA_LIBRARIES ${elem})
+            endif()
+        endforeach(elem)
     endif()
 endif()
 
@@ -89,44 +101,36 @@ if((GMX_GPU OR GMX_GPU_AUTO) AND NOT GMX_GPU_DETECTION_DONE)
 
     # assemble warning/error message
     if (GMX_DETECT_GPU_AVAILABLE)
-        set(_msg "
-    ${GMX_DETECT_GPU_COUNT} NVIDIA GPU(s) found in the system")
+        set(_msg "${GMX_DETECT_GPU_COUNT} NVIDIA GPU(s) found in the system")
 
         # append GPU names
         if (NOT GMX_DETECT_GPU_INFO STREQUAL "")
             set(_msg "${_msg}:")
             foreach(gpu ${GMX_DETECT_GPU_INFO})
                 set(_msg "${_msg}
-                ${gpu}")
+${gpu}")
             endforeach()
         endif()
 
         # TODO remove the second part of the message when we'll have compute
         # capability information from the detection.
         set(_msg "${_msg}
-    Compute capability information not available, consult the NVIDIA website:
-    https://developer.nvidia.com/cuda-gpus
-            ")
+Compute capability information not available, consult the NVIDIA website:
+https://developer.nvidia.com/cuda-gpus")
     endif()
 
-        set(CUDA_NOTFOUND_MESSAGE "
-    mdrun supports native GPU acceleration on NVIDIA hardware with compute
-    capability >=2.0 (Fermi or later). This requires the NVIDIA CUDA toolkit,
-    which was not found. Its location can be hinted by setting the
-    CUDA_TOOLKIT_ROOT_DIR CMake option (does not work as an environment variable).
-    The typical location would be /usr/local/cuda[-version].
-    Note that CPU or GPU acceleration can be selected at runtime!
+        set(CUDA_NOTFOUND_MESSAGE "mdrun supports native GPU acceleration on NVIDIA hardware with compute capability >= ${REQUIRED_CUDA_COMPUTE_CAPABILITY} (Fermi or later). This requires the NVIDIA CUDA toolkit, which was not found. Its location can be hinted by setting the CUDA_TOOLKIT_ROOT_DIR CMake option (does not work as an environment variable). The typical location would be /usr/local/cuda[-version]. Note that CPU or GPU acceleration can be selected at runtime.
 
-    ${_msg}")
+${_msg}")
         unset(_msg)
 
     if (NOT CUDA_FOUND)
         if (GMX_GPU_AUTO)
             # Disable GPU acceleration in auto mode
-            message(STATUS "No compatible CUDA toolkit found (v3.2+), disabling native GPU acceleration")
+            message(STATUS "No compatible CUDA toolkit found (v4.0+), disabling native GPU acceleration")
             set_property(CACHE GMX_GPU PROPERTY VALUE OFF)
             set(CUDA_NOTFOUND_AUTO ON)
-        else ()
+        else()
             # the user requested CUDA, but it wasn't found
             message(FATAL_ERROR "${CUDA_NOTFOUND_MESSAGE}")
         endif()
@@ -146,24 +150,53 @@ if(NOT GMX_GPU)
     mark_as_advanced(CUDA_TOOLKIT_ROOT_DIR)
 endif()
 
+# Try to execute ${CUDA_NVCC_EXECUTABLE} --version and set the output
+# (or an error string) in the argument variable.
+# Note that semicolon is used as separator for nvcc.
+#
+# Parameters:
+#   COMPILER_INFO   - [output variable] string with compiler path, ID and
+#                     some compiler-provided information
+#   COMPILER_FLAGS  - [output variable] flags for the compiler
+#
+macro(get_cuda_compiler_info COMPILER_INFO COMPILER_FLAGS)
+    if(CUDA_NVCC_EXECUTABLE)
+
+        # Get the nvcc version string. This is multi-line, but since it is only 4 lines
+        # and might change in the future it is better to store than trying to parse out
+        # the version from the current format.
+        execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} --version
+            RESULT_VARIABLE _nvcc_version_res
+            OUTPUT_VARIABLE _nvcc_version_out
+            ERROR_VARIABLE  _nvcc_version_err
+            OUTPUT_STRIP_TRAILING_WHITESPACE)
+        if (${_nvcc_version_res} EQUAL 0)
+            # Fix multi-line mess: Replace newline with ";" so we can use it in a define
+            string(REPLACE "\n" ";" _nvcc_info_singleline ${_nvcc_version_out})
+            SET(${COMPILER_INFO} "${CUDA_NVCC_EXECUTABLE} ${_nvcc_info_singleline}")
+            string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type)
+            SET(_compiler_flags "${CUDA_NVCC_FLAGS_${_build_type}}")
+            if(CUDA_PROPAGATE_HOST_FLAGS)
+                string(REGEX REPLACE "[ ]+" ";" _cxx_flags_nospace "${BUILD_CXXFLAGS}")
+            endif()
+            SET(${COMPILER_FLAGS} "${CUDA_NVCC_FLAGS}${CUDA_NVCC_FLAGS_${_build_type}}; ${_cxx_flags_nospace}")
+        else()
+            SET(${COMPILER_INFO} "N/A")
+            SET(${COMPILER_FLAGS} "N/A")
+        endif()
+    endif()
+endmacro ()
+
 macro(gmx_gpu_setup)
     # set up nvcc options
     include(gmxManageNvccConfig)
 
-    # Version info (semicolon used as line separator) for nvcc.
-    get_nvcc_version_info()
-
     # Atomic operations used for polling wait for GPU
     # (to avoid the cudaStreamSynchronize + ECC bug).
     # ThreadMPI is now always included. Thus, we don't check for Atomics anymore here.
 
     # no OpenMP is no good!
     if(NOT GMX_OPENMP)
-        message(WARNING "
-    To use GPU acceleration efficiently, mdrun requires OpenMP multi-threading.
-    Without OpenMP a single CPU core can be used with a GPU which is not optimal.
-    Note that with MPI multiple processes can be forced to use a single GPU, but this
-    typically inefficient. Note that you need to set both C and C++ compilers that
-    support OpenMP (CC and CXX environment variables, respectively) when using GPUs.")
+        message(WARNING "To use GPU acceleration efficiently, mdrun requires OpenMP multi-threading. Without OpenMP a single CPU core can be used with a GPU which is not optimal. Note that with MPI multiple processes can be forced to use a single GPU, but this is typically inefficient. You need to set both C and C++ compilers that support OpenMP (CC and CXX environment variables, respectively) when using GPUs.")
     endif()
 endmacro()