Simplified uniform GPU selection in CMake
[gromacs.git] / src / gromacs / CMakeLists.txt
blob3416b466805d64c36d78753c147c740d156c78a5
2 # This file is part of the GROMACS molecular simulation package.
4 # Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
5 # Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
6 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 # and including many others, as listed in the AUTHORS file in the
8 # top-level source directory and at http://www.gromacs.org.
10 # GROMACS is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU Lesser General Public License
12 # as published by the Free Software Foundation; either version 2.1
13 # of the License, or (at your option) any later version.
15 # GROMACS is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 # Lesser General Public License for more details.
20 # You should have received a copy of the GNU Lesser General Public
21 # License along with GROMACS; if not, see
22 # http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25 # If you want to redistribute modifications to GROMACS, please
26 # consider that scientific software is very special. Version
27 # control is crucial - bugs must be traceable. We will be happy to
28 # consider code for inclusion in the official distribution, but
29 # derived work must not be called official GROMACS. Details are found
30 # in the README & COPYING files - if they are missing, get the
31 # official version at http://www.gromacs.org.
33 # To help us fund GROMACS development, we humbly ask that you cite
34 # the research papers on the package. Check out http://www.gromacs.org.
36 set(LIBGROMACS_SOURCES)
38 if (GMX_CLANG_CUDA)
39     include(gmxClangCudaUtils)
40 endif()
42 set_property(GLOBAL PROPERTY GMX_LIBGROMACS_SOURCES)
43 set_property(GLOBAL PROPERTY GMX_LIBGROMACS_GPU_IMPL_SOURCES)
44 set_property(GLOBAL PROPERTY GMX_INSTALLED_HEADERS)
45 set_property(GLOBAL PROPERTY GMX_AVX_512_SOURCE)
47 set(libgromacs_object_library_dependencies "")
48 function (_gmx_add_files_to_property PROPERTY)
49     foreach (_file ${ARGN})
50         if (IS_ABSOLUTE "${_file}")
51             set_property(GLOBAL APPEND PROPERTY ${PROPERTY} ${_file})
52         else()
53             set_property(GLOBAL APPEND PROPERTY ${PROPERTY}
54                          ${CMAKE_CURRENT_LIST_DIR}/${_file})
55         endif()
56     endforeach()
57 endfunction ()
59 function (gmx_add_libgromacs_sources)
60     _gmx_add_files_to_property(GMX_LIBGROMACS_SOURCES ${ARGN})
61 endfunction ()
63 # Permit the configuration to disable compiling the many nbnxm kernels
64 # and others involved in force calculations. Currently only
65 # short-ranged and bonded kernels are disabled this way, but in future
66 # others may be appropriate. Thus the cmake option is not specific to
67 # nbnxm module.
68 option(GMX_USE_SIMD_KERNELS "Whether to compile NBNXM and other SIMD kernels" ON)
69 mark_as_advanced(GMX_USE_SIMD_KERNELS)
71 # Add these contents first because linking their tests can take a lot
72 # of time, so we want lots of parallel work still available after
73 # linking starts.
74 add_subdirectory(utility)
75 # Add normal contents
76 add_subdirectory(gmxlib)
77 add_subdirectory(mdlib)
78 add_subdirectory(applied_forces)
79 add_subdirectory(listed_forces)
80 add_subdirectory(nbnxm)
81 add_subdirectory(commandline)
82 add_subdirectory(domdec)
83 add_subdirectory(ewald)
84 add_subdirectory(fft)
85 add_subdirectory(gpu_utils)
86 add_subdirectory(hardware)
87 add_subdirectory(linearalgebra)
88 add_subdirectory(math)
89 add_subdirectory(mdrun)
90 add_subdirectory(mdrunutility)
91 add_subdirectory(mdspan)
92 add_subdirectory(mdtypes)
93 add_subdirectory(onlinehelp)
94 add_subdirectory(options)
95 add_subdirectory(pbcutil)
96 add_subdirectory(random)
97 add_subdirectory(restraint)
98 add_subdirectory(tables)
99 add_subdirectory(taskassignment)
100 add_subdirectory(timing)
101 add_subdirectory(topology)
102 add_subdirectory(trajectory)
103 add_subdirectory(swap)
104 add_subdirectory(essentialdynamics)
105 add_subdirectory(pulling)
106 add_subdirectory(awh)
107 add_subdirectory(simd)
108 add_subdirectory(imd)
109 add_subdirectory(compat)
110 add_subdirectory(mimic)
111 add_subdirectory(modularsimulator)
112 if (NOT GMX_BUILD_MDRUN_ONLY)
113     add_subdirectory(gmxana)
114     add_subdirectory(gmxpreprocess)
115     add_subdirectory(correlationfunctions)
116     add_subdirectory(statistics)
117     add_subdirectory(analysisdata)
118     add_subdirectory(coordinateio)
119     add_subdirectory(trajectoryanalysis)
120     add_subdirectory(energyanalysis)
121     add_subdirectory(tools)
122 endif()
124 get_property(PROPERTY_SOURCES GLOBAL PROPERTY GMX_LIBGROMACS_SOURCES)
125 list(APPEND LIBGROMACS_SOURCES ${GMXLIB_SOURCES} ${MDLIB_SOURCES} ${PROPERTY_SOURCES})
127 # This would be the standard way to include thread_mpi, but
128 # we want libgromacs to link the functions directly
129 #if(GMX_THREAD_MPI)
130 #    add_subdirectory(thread_mpi)
131 #endif()
132 #target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES} ${THREAD_MPI_LIB})
133 tmpi_get_source_list(THREAD_MPI_SOURCES ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/src)
134 add_library(thread_mpi OBJECT ${THREAD_MPI_SOURCES})
135 target_compile_definitions(thread_mpi PRIVATE HAVE_CONFIG_H)
136 if(CYGWIN)
137     # Needs POSIX-isms for strdup, not just std-isms
138     target_compile_definitions(thread_mpi PRIVATE _POSIX_C_SOURCE=200809L)
139 endif()
140 gmx_target_compile_options(thread_mpi)
141 if (WIN32)
142     gmx_target_warning_suppression(thread_mpi /wd4996 HAS_NO_MSVC_UNSAFE_FUNCTION)
143 endif()
144 list(APPEND libgromacs_object_library_dependencies thread_mpi)
146 configure_file(version.h.cmakein version.h)
147 if(GMX_INSTALL_LEGACY_API)
148   install(FILES
149           ${CMAKE_CURRENT_BINARY_DIR}/version.h
150           DESTINATION include/gromacs)
151 endif()
153 # This code is here instead of utility/CMakeLists.txt, because CMake
154 # custom commands and source file properties can only be set in the directory
155 # that contains the target that uses them.
156 # TODO: Generate a header instead that can be included from baseversion.cpp.
157 # That probably simplifies things somewhat.
158 set(GENERATED_VERSION_FILE utility/baseversion-gen.cpp)
159 gmx_configure_version_file(
160     utility/baseversion-gen.cpp.cmakein ${GENERATED_VERSION_FILE}
161     REMOTE_HASH
162     EXTRA_VARS
163         GMX_SOURCE_DOI
164         GMX_RELEASE_HASH
165         GMX_SOURCE_HASH
166         )
167 list(APPEND LIBGROMACS_SOURCES ${GENERATED_VERSION_FILE})
169 # Mark some shared GPU implementation files to compile with CUDA if needed
170 if (GMX_GPU_CUDA)
171     get_property(LIBGROMACS_GPU_IMPL_SOURCES GLOBAL PROPERTY GMX_LIBGROMACS_GPU_IMPL_SOURCES)
172     set_source_files_properties(${LIBGROMACS_GPU_IMPL_SOURCES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
173 endif()
175 # set up CUDA compilation with clang
176 if (GMX_CLANG_CUDA)
177     foreach (_file ${LIBGROMACS_SOURCES})
178         get_filename_component(_ext ${_file} EXT)
179         get_source_file_property(_cuda_source_format ${_file} CUDA_SOURCE_PROPERTY_FORMAT)
180         if ("${_ext}" STREQUAL ".cu" OR _cuda_source_format)
181             gmx_compile_cuda_file_with_clang(${_file})
182         endif()
183     endforeach()
184 endif()
186 if (GMX_GPU_CUDA)
187     # Work around FindCUDA that prevents using target_link_libraries()
188     # with keywords otherwise...
189     set(CUDA_LIBRARIES PRIVATE ${CUDA_LIBRARIES})
190     if (NOT GMX_CLANG_CUDA)
191         gmx_cuda_add_library(libgromacs ${LIBGROMACS_SOURCES})
192     else()
193         add_library(libgromacs ${LIBGROMACS_SOURCES})
194     endif()
195     target_link_libraries(libgromacs PRIVATE ${CUDA_CUFFT_LIBRARIES})
196 else()
197     add_library(libgromacs ${LIBGROMACS_SOURCES})
198 endif()
200 # Add these contents first because linking their tests can take a lot
201 # of time, so we want lots of parallel work still available after
202 # linking starts.
203 add_subdirectory(fileio)
204 add_subdirectory(selection)
206 # Suppress a warning about our abuse of t_inputrec
207 gmx_source_file_warning_suppression(mdtypes/inputrec.cpp -Wno-class-memaccess HAS_NO_CLASS_MEMACCESS)
209 # Handle the object libraries that contain the source file
210 # dependencies that need special handling because they are generated
211 # or external code.
212 foreach(object_library ${libgromacs_object_library_dependencies})
213     if (BUILD_SHARED_LIBS)
214         set_target_properties(${object_library} PROPERTIES POSITION_INDEPENDENT_CODE true)
215     endif()
216     target_include_directories(${object_library} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
218     # Add the sources from the object libraries to the main library.
219     target_sources(libgromacs PRIVATE $<TARGET_OBJECTS:${object_library}>)
220 endforeach()
221 gmx_target_compile_options(libgromacs)
222 target_compile_definitions(libgromacs PRIVATE HAVE_CONFIG_H)
223 target_include_directories(libgromacs SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
225 if (GMX_GPU_OPENCL)
226     option(GMX_EXTERNAL_CLFFT "True if an external clFFT is required to be used" FALSE)
227     mark_as_advanced(GMX_EXTERNAL_CLFFT)
229     # Default to using clFFT found on the system
230     # switch to quiet at the second run.
231     if (DEFINED clFFT_LIBRARY)
232         set (clFFT_FIND_QUIETLY TRUE)
233     endif()
234     find_package(clFFT)
235     if (NOT clFFT_FOUND)
236         if (GMX_EXTERNAL_CLFFT)
237             message(FATAL_ERROR "Did not find required external clFFT library, consider setting clFFT_ROOT_DIR")
238         endif()
240         if(MSVC)
241             message(FATAL_ERROR
242 "An OpenCL build was requested with Visual Studio compiler, but GROMACS
243 requires clFFT, which was not found on your system. GROMACS does bundle
244 clFFT to help with building for OpenCL, but that clFFT has not yet been
245 ported to the more recent versions of that compiler that GROMACS itself
246 requires. Thus for now, OpenCL is not available with MSVC and the internal
247 build of clFFT in GROMACS 2019. Either change compiler, try installing
248 a clFFT package, or use the latest GROMACS 2018 point release.")
249         endif()
251         # Fall back on the internal version
252         set (_clFFT_dir ../external/clFFT/src)
253         add_subdirectory(${_clFFT_dir} clFFT-build)
254         target_sources(libgromacs PRIVATE
255             $<TARGET_OBJECTS:clFFT>
256         )
257         target_include_directories(libgromacs SYSTEM PRIVATE ${_clFFT_dir}/include)
258         # Use the magic variable for how to link any library needed for
259         # dlopen, etc.  which is -ldl where needed, and empty otherwise
260         # (e.g. Windows, BSD, Mac).
261         target_link_libraries(libgromacs PRIVATE "${CMAKE_DL_LIBS}")
262     else()
263         target_link_libraries(libgromacs PRIVATE clFFT)
264     endif()
265 endif()
267 # Permit GROMACS code to include externally developed headers, such as
268 # the functionality from the nonstd project that we use for
269 # gmx::compat::optional. These are included as system headers so that
270 # no warnings are issued from them.
272 # TODO Perhaps generalize this for all headers from src/external
273 target_include_directories(libgromacs SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
275 if(SIMD_AVX_512_CXX_SUPPORTED AND NOT ("${GMX_SIMD_ACTIVE}" STREQUAL "AVX_512_KNL"))
276     # Since we might be overriding -march=core-avx2, add a flag so we don't warn for this specific file.
277     # On KNL this can cause illegal instruction because the compiler might use non KNL AVX instructions
278     # with the SIMD_AVX_512_CXX_FLAGS flags.
279     set_source_files_properties(hardware/identifyavx512fmaunits.cpp PROPERTIES COMPILE_FLAGS "${SIMD_AVX_512_CXX_FLAGS} ${CXX_NO_UNUSED_OPTION_WARNING_FLAGS}")
280 endif()
282 gmx_setup_tng_for_libgromacs()
284 target_link_libraries(libgromacs
285                       PRIVATE
286                       ${EXTRAE_LIBRARIES}
287                       ${GMX_EXTRA_LIBRARIES}
288                       ${GMX_COMMON_LIBRARIES}
289                       ${FFT_LIBRARIES} ${LINEAR_ALGEBRA_LIBRARIES}
290                       ${THREAD_LIB} ${GMX_SHARED_LINKER_FLAGS}
291                       ${OpenCL_LIBRARIES}
292                       $<$<PLATFORM_ID:SunOS>:socket>
293                       PUBLIC
294                       ${GMX_PUBLIC_LIBRARIES}
295                       )
296 if (GMX_OPENMP)
297     target_link_libraries(libgromacs PUBLIC OpenMP::OpenMP_CXX)
298 endif()
299 set_target_properties(libgromacs PROPERTIES
300                       OUTPUT_NAME "gromacs${GMX_LIBS_SUFFIX}"
301                       SOVERSION ${LIBRARY_SOVERSION_MAJOR}
302                       VERSION ${LIBRARY_VERSION}
303                       )
305 gmx_manage_lmfit()
306 target_link_libraries(libgromacs PRIVATE lmfit)
308 # Make sure we fix "everything" found by more recent versions of clang.
309 if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
310    target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS}>)
311 endif()
312 if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
313    target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/analyze /analyze:stacksize 70000
314      #Control flow warnings are disabled because the commond line output is insufficient. There is no tool
315      #to convert the xml report to e.g. HTML and even in Visual Studio the viewer doesn't work with cmake support.
316      /wd6001  #unitialized memory
317      /wd6011  #derefencing NULL
318      /wd6053  #prior call not zero-terminate
319      /wd6054  #might not be zero-terminated
320      /wd6385  #reading invalid data
321      /wd6386  #buffer overrun
322      /wd6387  #could be '0'
323      /wd28199 #uninitialized memory
324      # For compile time constant (e.g. templates) the following warnings have flase postives
325      /wd6239  #(<non-zero> && <expr>)
326      /wd6240  #(<expr> && <non-zero>)
327      /wd6294  #Ill-defined for-loop
328      /wd6326  #comparison of constant with other constant
329      /wd28020 #expression involving paramter is not true
330      # Misc
331      /wd6330  #incorrect type to function (warns for char (instead of unsigned) for isspace/isalpha/isdigit/..))
332      /wd6993  #OpenMP ignored
333      #TODO
334      /wd6031  #return value ignored (important - mostly warnigns about sscanf)
335      /wd6244  #hides declaration (known issue - we ingore similar warnings for other compilers)
336      /wd6246  #hides declaration
337      >
338    )
339 endif()
341 if (GMX_CLANG_TIDY)
342    set_target_properties(libgromacs PROPERTIES CXX_CLANG_TIDY
343        "${CLANG_TIDY_EXE};-warnings-as-errors=*")
344 endif()
346 # clang-3.6 warns about a number of issues that are not reported by more modern compilers
347 # and we know they are not real issues. So we only check that it can compile without error
348 # but ignore all warnings.
349 if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^3\.6")
350     target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-w>)
351 endif()
353 # Only install the library in mdrun-only mode if it is actually necessary
354 # for the binary
355 if (NOT GMX_BUILD_MDRUN_ONLY OR BUILD_SHARED_LIBS)
356     install(TARGETS libgromacs
357             EXPORT libgromacs
358             LIBRARY
359                 DESTINATION ${CMAKE_INSTALL_LIBDIR}
360                 COMPONENT libraries
361             RUNTIME
362                 DESTINATION ${CMAKE_INSTALL_BINDIR}
363                 COMPONENT libraries
364             ARCHIVE
365                 DESTINATION ${CMAKE_INSTALL_LIBDIR}
366                 COMPONENT libraries
367             INCLUDES DESTINATION include)
368     target_compile_definitions(libgromacs PUBLIC $<INSTALL_INTERFACE:GMX_DOUBLE=${GMX_DOUBLE_VALUE}>)
369     # legacy headers use c++17 features, so consumer codes need to use that standard, too
370     if(GMX_INSTALL_LEGACY_API)
371         target_compile_features(libgromacs INTERFACE cxx_std_${CMAKE_CXX_STANDARD})
372     endif()
373     add_library(Gromacs::libgromacs ALIAS libgromacs)
374 endif()
376 if (NOT GMX_BUILD_MDRUN_ONLY)
377     include(InstallLibInfo.cmake)
378 endif()
380 # Technically, the user could want to do this for an OpenCL build
381 # using the CUDA runtime, but currently there's no reason to want to
382 # do that.
383 if (INSTALL_CUDART_LIB) #can be set manual by user
384     if (GMX_GPU_CUDA)
385         foreach(CUDA_LIB ${CUDA_LIBRARIES})
386             string(REGEX MATCH "cudart" IS_CUDART ${CUDA_LIB})
387             if(IS_CUDART) #libcuda should not be installed
388                 #install also name-links (linker uses those)
389                 file(GLOB CUDA_LIBS ${CUDA_LIB}*)
390                 install(FILES ${CUDA_LIBS} DESTINATION
391                     ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
392             endif()
393         endforeach()
394     else()
395         message(WARNING "INSTALL_CUDART_LIB only makes sense when configuring for CUDA support")
396     endif()
397 endif()
399 if(GMX_GPU_OPENCL)
400     # Install the utility headers
401     file(GLOB OPENCL_INSTALLED_FILES
402         gpu_utils/vectype_ops.clh
403         gpu_utils/device_utils.clh
404         )
405     install(FILES ${OPENCL_INSTALLED_FILES}
406         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/gpu_utils
407         COMPONENT libraries)
408     file(GLOB OPENCL_INSTALLED_FILES
409         pbcutil/ishift.h
410         )
411     install(FILES ${OPENCL_INSTALLED_FILES}
412         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/pbcutil
413         COMPONENT libraries)
415     # Install the NBNXM source and headers
416     file(GLOB OPENCL_INSTALLED_FILES
417         nbnxm/constants.h
418         )
419     install(FILES ${OPENCL_INSTALLED_FILES}
420         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/nbnxm
421         COMPONENT libraries)
422     file(GLOB OPENCL_INSTALLED_FILES
423         nbnxm/opencl/nbnxm_ocl_kernels.cl
424         nbnxm/opencl/nbnxm_ocl_kernel.clh
425         nbnxm/opencl/nbnxm_ocl_kernel_pruneonly.clh
426         nbnxm/opencl/nbnxm_ocl_kernels.clh
427         nbnxm/opencl/nbnxm_ocl_kernels_fastgen.clh
428         nbnxm/opencl/nbnxm_ocl_kernels_fastgen_add_twincut.clh
429         nbnxm/opencl/nbnxm_ocl_kernel_utils.clh
430         nbnxm/opencl/nbnxm_ocl_consts.h
431         )
432     install(FILES ${OPENCL_INSTALLED_FILES}
433         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/nbnxm/opencl
434         COMPONENT libraries)
436     # Install the PME source and headers
437     file(GLOB OPENCL_INSTALLED_FILES
438         ewald/pme_spread.clh
439         ewald/pme_solve.clh
440         ewald/pme_gather.clh
441         ewald/pme_gpu_utils.clh
442         ewald/pme_program.cl
443         ewald/pme_gpu_types.h
444         )
445     install(FILES ${OPENCL_INSTALLED_FILES}
446         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/ewald
447         COMPONENT libraries)
448 endif()