d7743c24e907b8951f4c82ed8b237a28c3e02b6b
[alexxy/gromacs.git] / cmake / gmxManageNvccConfig.cmake
1 # Manage CUDA nvcc compilation configuration, try to be smart to ease the users'
2 # pain as much as possible:
3 # - use the CUDA_HOST_COMPILER if defined by the user, otherwise
4 # - auto-detect compatible nvcc host compiler and set nvcc -ccbin (if not MPI wrapper)
5 # - set icc compatibility mode to gcc 4.4/4.5 (CUDA 4.0 is not compatible with gcc >v4.4)
6 # - (advanced) variables set:
7 #   * CUDA_HOST_COMPILER            - the host compiler for nvcc (only with cmake <2.8.10)
8 #   * CUDA_HOST_COMPILER_OPTIONS    - the full host-compiler related option list passed to nvcc
9 #
10 # Note that from CMake 2.8.10 FindCUDA defines CUDA_HOST_COMPILER internally,
11 # so we won't set it ourselves, but hope that the module does a good job.
12
13 if (NOT DEFINED CUDA_NVCC_FLAGS_SET)
14     set(CUDA_NVCC_FLAGS_SET TRUE CACHE INTERNAL "True if NVCC flags have been set" FORCE)
15
16     # Explicitly set the host compiler for nvcc if the current compiler is
17     # supported and it's not an MPI compiler wrapper, otherwise warn the user.
18     #
19     # Note that even though nvcc compiles host code as C++, we use the
20     # CMAKE_C_COMPILER as host compiler. We do this because CUDA versions
21     # preceding 5.0 only recognize icc, but not icpc. However, both gcc and icc
22     # (i.e. all supported compilers) happily compile C++ code.
23     #
24     # Also note that with MSVC nvcc sets the -compiler-bindir option behind the
25     # scenes; to avoid conflicts we don't set -ccbin automatically.
26
27     if (NOT DEFINED CUDA_HOST_COMPILER AND NOT MSVC)
28         if (NOT CMAKE_COMPILER_IS_GNUCC AND
29             NOT (CMAKE_C_COMPILER_ID MATCHES "Intel" AND UNIX AND NOT APPLE))
30             message(WARNING "
31             Will not set the nvcc host compiler because the current C compiler is not
32             compatible with nvcc:
33             ${CMAKE_C_COMPILER} (ID: ${CMAKE_C_COMPILER_ID})
34             Compatible compilers are: gcc on Linux and Mac OS X, the Intel Compiler on 64-bit
35             Linux and MSVC on Windows. Note that with newer CUDA releases this might change,
36             for up-to-date compatibility information check the NVIDIA documentation.
37             If nothing specified, nvcc will automatically pick the platform-default compiler;
38             Note that mixing compilers can cause errors.
39             To manually set the nvcc host compiler, edit CUDA_NVCC_FLAGS or re-configure
40             setting CUDA_HOST_COMPILER to the full path of a compatible compiler.
41             ")
42         else()
43             # do not use MPI compiler wrappers, as these are prone to brake nvcc
44             if (GMX_MPI AND
45                 NOT "${${MPI_PREFIX}_FOUND}" AND # FindMPI-based detection
46                 NOT GMX_THREAD_MPI)
47                 message(WARNING "
48             Will not set the nvcc host compiler because the current C compiler is an MPI
49             compiler wrapper: ${CMAKE_C_COMPILER}
50             MPI compiler wrappers are prone to not work with nvcc. You might get lucky,
51             but the safest is to use the C compiler that the MPI compiler wrapper uses
52             (if this is compatible).
53             To manually set the nvcc host compiler, edit CUDA_NVCC_FLAGS or re-configure
54             setting CUDA_HOST_COMPILER to the full path of a compatible compiler.
55             ")
56             else()
57                 set(CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}")
58                 set(CUDA_HOST_COMPILER_AUTOSET TRUE CACHE INTERNAL
59                     "True if CUDA_HOST_COMPILER is automatically set" FORCE)
60             endif()
61         endif()
62     endif()
63
64     if(DEFINED CUDA_HOST_COMPILER)
65         # FindCUDA in CMake 2.8.10 sets the host compiler internally
66         if (CMAKE_VERSION VERSION_LESS "2.8.10")
67             message(STATUS "Setting the nvcc host compiler to: ${CUDA_HOST_COMPILER}")
68             set(CUDA_HOST_COMPILER ${CUDA_HOST_COMPILER}
69                 CACHE PATH "Host compiler for nvcc (do not edit!)" FORCE)
70             set(_HOST_COMPILER_OPTION_STRING "-ccbin=${CUDA_HOST_COMPILER};")
71         endif()
72
73         # On *nix force icc in gcc 4.4 compatibility mode with CUDA 3.2/4.0 and
74         # gcc 4.5 compatibility mode with later CUDA versions. This is needed
75         # as even with icc use as host compiler, when icc's gcc compatibility
76         # mode is higher than the max gcc version officially supported by CUDA,
77         # nvcc will freak out.
78         if (UNIX AND CMAKE_C_COMPILER_ID MATCHES "Intel" AND
79             CUDA_HOST_COMPILER_AUTOSET)
80             if (CUDA_VERSION VERSION_LESS "4.1")
81                 message(STATUS "Setting Intel Compiler compatibity mode to gcc 4.4 for nvcc host compilation")
82                 set(CUDA_HOST_COMPILER_OPTIONS "${CUDA_HOST_COMPILER_OPTIONS};-Xcompiler;-gcc-version=440;")
83             else()
84                 message(STATUS "Setting Intel Compiler compatibity mode to gcc 4.5 for nvcc host compilation")
85                 set(CUDA_HOST_COMPILER_OPTIONS "${CUDA_HOST_COMPILER_OPTIONS};-Xcompiler;-gcc-version=450;")
86             endif()
87         endif()
88         set(CUDA_HOST_COMPILER_OPTIONS "${CUDA_HOST_COMPILER_OPTIONS}"
89             CACHE STRING "Options for nvcc host compiler (do not edit!)." FORCE)
90
91         mark_as_advanced(CUDA_HOST_COMPILER CUDA_HOST_COMPILER_OPTIONS)
92     endif()
93
94     # on Linux we need to add -fPIC when building shared gmx libs
95     # Note: will add -fPIC for any compiler that supports it as it shouldn't hurt
96     if(BUILD_SHARED_LIBS)
97         GMX_TEST_CXXFLAG(CXXFLAG_FPIC "-fPIC" _FPIC_NVCC_FLAG)
98         if(_FPIC_NVCC_FLAG)
99             set(CUDA_HOST_COMPILER_OPTIONS "${CUDA_HOST_COMPILER_OPTIONS}-Xcompiler;${_FPIC_NVCC_FLAG}")
100         endif()
101     endif()
102
103     # Set the CUDA GPU architectures to compile for:
104     # - with CUDA >v4.2 compute capability 2.0, 2.1 is, but 3.0 is not supported:
105     #     => compile sm_20, sm_21 cubin, and compute_20 PTX
106     # - with CUDA >=4.2 compute capabity <=3.0 is supported:
107     #     => compile sm_20, sm_21, sm_30 cubin, and compute_30 PTX
108     # - with CUDA 5.0 compute capabity 3.5 is supported, but generating code
109     #   optimized for sm_35 results in lower performance than with sm_30.
110     if(CUDA_VERSION VERSION_LESS "4.2")
111         set(_CUDA_ARCH_STR "-gencode;arch=compute_20,code=sm_20;-gencode;arch=compute_20,code=sm_21;-gencode;arch=compute_20,code=compute_20")
112     elseif(CUDA_VERSION VERSION_LESS "5.0")
113         set(_CUDA_ARCH_STR "-gencode;arch=compute_20,code=sm_20;-gencode;arch=compute_20,code=sm_21;-gencode;arch=compute_30,code=sm_30;-gencode;arch=compute_30,code=compute_30")
114     else()
115         set(_CUDA_ARCH_STR "-gencode;arch=compute_20,code=sm_20;-gencode;arch=compute_20,code=sm_21;-gencode;arch=compute_30,code=sm_30;-gencode;arch=compute_35,code=sm_35;-gencode;arch=compute_35,code=compute_35")
116     endif()
117
118     # finally set the damn flags
119     set(CUDA_NVCC_FLAGS
120         "${_CUDA_ARCH_STR};-use_fast_math;${_HOST_COMPILER_OPTION_STRING}${CUDA_HOST_COMPILER_OPTIONS}"
121         CACHE STRING "Compiler flags for nvcc." FORCE)
122 endif()