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