Fix hipSYCL build with CUDA target
[alexxy/gromacs.git] / src / gromacs / CMakeLists.txt
index 71dceb857fda651590f897d23ff2a87747949925..bf530db08138c8ef39e526f80dcdf25c4fdd4959 100644 (file)
@@ -1,7 +1,9 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+# Copyright (c) 2020,2021, 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.
@@ -39,22 +41,11 @@ if (GMX_CLANG_CUDA)
 endif()
 
 set_property(GLOBAL PROPERTY GMX_LIBGROMACS_SOURCES)
-set_property(GLOBAL PROPERTY GMX_LIBGROMACS_GPU_IMPL_SOURCES)
+set_property(GLOBAL PROPERTY CUDA_SOURCES)
 set_property(GLOBAL PROPERTY GMX_INSTALLED_HEADERS)
 set_property(GLOBAL PROPERTY GMX_AVX_512_SOURCE)
 
-add_library(libgromacs_external OBJECT "")
-if(CMAKE_COMPILER_IS_GNUCXX)
-    # Keep quiet about e.g. linearalgebra module
-    target_compile_options(libgromacs_external PRIVATE ${CXXFLAGS_NO_STRINGOP_TRUNCATION})
-endif()
-
-add_library(libgromacs_generated OBJECT "")
-if (BUILD_SHARED_LIBS)
-    set_target_properties(libgromacs_external PROPERTIES POSITION_INDEPENDENT_CODE true)
-    set_target_properties(libgromacs_generated PROPERTIES POSITION_INDEPENDENT_CODE true)
-endif()
-
+set(libgromacs_object_library_dependencies "")
 function (_gmx_add_files_to_property PROPERTY)
     foreach (_file ${ARGN})
         if (IS_ABSOLUTE "${_file}")
@@ -70,33 +61,24 @@ function (gmx_add_libgromacs_sources)
     _gmx_add_files_to_property(GMX_LIBGROMACS_SOURCES ${ARGN})
 endfunction ()
 
-# TODO Reconsider this, as the CUDA driver API is probably a simpler
-# approach, at least for the build system. See Redmine #2530
-function (gmx_compile_cpp_as_cuda)
-    _gmx_add_files_to_property(GMX_LIBGROMACS_GPU_IMPL_SOURCES ${ARGN})
-endfunction ()
-
-function (gmx_install_headers)
-    if (NOT GMX_BUILD_MDRUN_ONLY)
-        file(RELATIVE_PATH _dest ${PROJECT_SOURCE_DIR}/src ${CMAKE_CURRENT_LIST_DIR})
-        install(FILES       ${ARGN}
-                DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_dest}"
-                COMPONENT   development)
-    endif()
-    _gmx_add_files_to_property(GMX_INSTALLED_HEADERS ${ARGN})
-endfunction ()
-
-function (gmx_write_installed_header_list)
-    get_property(_list GLOBAL PROPERTY GMX_INSTALLED_HEADERS)
-    string(REPLACE ";" "\n" _list "${_list}")
-    # TODO: Make this only update the file timestamp if the contents actually change.
-    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/installed-headers.txt "${_list}")
-endfunction()
-
+# Permit the configuration to disable compiling the many nbnxm kernels
+# and others involved in force calculations. Currently only
+# short-ranged and bonded kernels are disabled this way, but in future
+# others may be appropriate. Thus the cmake option is not specific to
+# nbnxm module.
+option(GMX_USE_SIMD_KERNELS "Whether to compile NBNXM and other SIMD kernels" ON)
+mark_as_advanced(GMX_USE_SIMD_KERNELS)
+
+# Add these contents first because linking their tests can take a lot
+# of time, so we want lots of parallel work still available after
+# linking starts.
+add_subdirectory(utility)
+# Add normal contents
 add_subdirectory(gmxlib)
 add_subdirectory(mdlib)
-add_subdirectory(applied-forces)
-add_subdirectory(listed-forces)
+add_subdirectory(applied_forces)
+add_subdirectory(listed_forces)
+add_subdirectory(nbnxm)
 add_subdirectory(commandline)
 add_subdirectory(domdec)
 add_subdirectory(ewald)
@@ -119,27 +101,23 @@ add_subdirectory(taskassignment)
 add_subdirectory(timing)
 add_subdirectory(topology)
 add_subdirectory(trajectory)
-add_subdirectory(utility)
-add_subdirectory(fileio)
 add_subdirectory(swap)
 add_subdirectory(essentialdynamics)
 add_subdirectory(pulling)
-add_subdirectory(awh)
 add_subdirectory(simd)
 add_subdirectory(imd)
 add_subdirectory(compat)
 add_subdirectory(mimic)
-if (NOT GMX_BUILD_MDRUN_ONLY)
-    add_subdirectory(gmxana)
-    add_subdirectory(gmxpreprocess)
-    add_subdirectory(correlationfunctions)
-    add_subdirectory(statistics)
-    add_subdirectory(analysisdata)
-    add_subdirectory(selection)
-    add_subdirectory(trajectoryanalysis)
-    add_subdirectory(energyanalysis)
-    add_subdirectory(tools)
-endif()
+add_subdirectory(modularsimulator)
+add_subdirectory(gmxana)
+add_subdirectory(gmxpreprocess)
+add_subdirectory(correlationfunctions)
+add_subdirectory(statistics)
+add_subdirectory(analysisdata)
+add_subdirectory(coordinateio)
+add_subdirectory(trajectoryanalysis)
+add_subdirectory(energyanalysis)
+add_subdirectory(tools)
 
 get_property(PROPERTY_SOURCES GLOBAL PROPERTY GMX_LIBGROMACS_SOURCES)
 list(APPEND LIBGROMACS_SOURCES ${GMXLIB_SOURCES} ${MDLIB_SOURCES} ${PROPERTY_SOURCES})
@@ -150,26 +128,32 @@ list(APPEND LIBGROMACS_SOURCES ${GMXLIB_SOURCES} ${MDLIB_SOURCES} ${PROPERTY_SOU
 #    add_subdirectory(thread_mpi)
 #endif()
 #target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES} ${THREAD_MPI_LIB})
-
-tmpi_get_source_list(THREAD_MPI_SOURCES ${CMAKE_SOURCE_DIR}/src/external/thread_mpi/src)
-target_sources(libgromacs_external PRIVATE ${THREAD_MPI_SOURCES})
-
-configure_file(version.h.cmakein version.h)
-gmx_install_headers(
-    analysisdata.h
-    commandline.h
-    options.h
-    random.h
-    selection.h
-    trajectoryanalysis.h
-    utility.h
-    ${CMAKE_CURRENT_BINARY_DIR}/version.h
-    )
+tmpi_get_source_list(THREAD_MPI_SOURCES ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/src)
+add_library(thread_mpi OBJECT ${THREAD_MPI_SOURCES})
+target_compile_definitions(thread_mpi PRIVATE HAVE_CONFIG_H)
+if(CYGWIN)
+    # Needs POSIX-isms for strdup, not just std-isms
+    target_compile_definitions(thread_mpi PRIVATE _POSIX_C_SOURCE=200809L)
+endif()
+gmx_target_compile_options(thread_mpi)
+if (WIN32)
+    gmx_target_warning_suppression(thread_mpi /wd4996 HAS_NO_MSVC_UNSAFE_FUNCTION)
+endif()
+list(APPEND libgromacs_object_library_dependencies thread_mpi)
+
+if(GMX_INSTALL_LEGACY_API)
+  install(FILES
+         analysisdata.h
+         options.h
+         selection.h
+         trajectoryanalysis.h
+          DESTINATION include/gromacs)
+endif()
 
 # This code is here instead of utility/CMakeLists.txt, because CMake
 # custom commands and source file properties can only be set in the directory
 # that contains the target that uses them.
-# TODO: Generate a header instead that can be included from baseversion.c.
+# TODO: Generate a header instead that can be included from baseversion.cpp.
 # That probably simplifies things somewhat.
 set(GENERATED_VERSION_FILE utility/baseversion-gen.cpp)
 gmx_configure_version_file(
@@ -177,34 +161,23 @@ gmx_configure_version_file(
     REMOTE_HASH
     EXTRA_VARS
         GMX_SOURCE_DOI
-    )
-list(APPEND LIBGROMACS_SOURCES ${GENERATED_VERSION_FILE}
-     $<TARGET_OBJECTS:libgromacs_external>
-     $<TARGET_OBJECTS:libgromacs_generated>)
+        GMX_RELEASE_HASH
+        GMX_SOURCE_HASH
+        )
+list(APPEND LIBGROMACS_SOURCES ${GENERATED_VERSION_FILE})
 
 # Mark some shared GPU implementation files to compile with CUDA if needed
-if (GMX_USE_CUDA)
-    get_property(LIBGROMACS_GPU_IMPL_SOURCES GLOBAL PROPERTY GMX_LIBGROMACS_GPU_IMPL_SOURCES)
-    set_source_files_properties(${LIBGROMACS_GPU_IMPL_SOURCES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+if (GMX_GPU_CUDA)
+    get_property(CUDA_SOURCES GLOBAL PROPERTY CUDA_SOURCES)
+    set_source_files_properties(${CUDA_SOURCES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
 endif()
 
-# set up CUDA compilation with clang
-if (GMX_CLANG_CUDA)
-    foreach (_file ${LIBGROMACS_SOURCES})
-        get_filename_component(_ext ${_file} EXT)
-        get_source_file_property(_cuda_source_format ${_file} CUDA_SOURCE_PROPERTY_FORMAT)
-        if ("${_ext}" STREQUAL ".cu" OR _cuda_source_format)
-            gmx_compile_cuda_file_with_clang(${_file})
-        endif()
-    endforeach()
-endif()
-
-if (GMX_USE_CUDA)
+if (GMX_GPU_CUDA)
     # Work around FindCUDA that prevents using target_link_libraries()
     # with keywords otherwise...
     set(CUDA_LIBRARIES PRIVATE ${CUDA_LIBRARIES})
     if (NOT GMX_CLANG_CUDA)
-        cuda_add_library(libgromacs ${LIBGROMACS_SOURCES})
+        gmx_cuda_add_library(libgromacs ${LIBGROMACS_SOURCES})
     else()
         add_library(libgromacs ${LIBGROMACS_SOURCES})
     endif()
@@ -213,7 +186,46 @@ else()
     add_library(libgromacs ${LIBGROMACS_SOURCES})
 endif()
 
-if (GMX_USE_OPENCL)
+if (TARGET Heffte::Heffte)
+    target_link_libraries(libgromacs PRIVATE Heffte::Heffte)
+endif()
+
+if (GMX_SYCL_HIPSYCL AND GMX_HIPSYCL_HAVE_HIP_TARGET)
+    target_link_libraries(libgromacs PUBLIC roc::rocfft)
+endif()
+
+target_link_libraries(libgromacs PRIVATE $<BUILD_INTERFACE:common>)
+# As long as the libgromacs target has source files that reference headers from
+# modules that don't provide CMake targets, libgromacs needs to use `src/`
+# amongst its include directories (to support `#include "gromacs/module/header.h"`).
+add_library(legacy_modules INTERFACE)
+target_include_directories(legacy_modules INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src>)
+target_link_libraries(libgromacs PRIVATE $<BUILD_INTERFACE:legacy_modules>)
+
+# Add these contents first because linking their tests can take a lot
+# of time, so we want lots of parallel work still available after
+# linking starts.
+add_subdirectory(fileio)
+add_subdirectory(selection)
+
+# Handle the object libraries that contain the source file
+# dependencies that need special handling because they are generated
+# or external code.
+foreach(object_library ${libgromacs_object_library_dependencies})
+    if (BUILD_SHARED_LIBS)
+        set_target_properties(${object_library} PROPERTIES POSITION_INDEPENDENT_CODE true)
+    endif()
+    target_include_directories(${object_library} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
+    target_link_libraries(${object_library} PRIVATE common)
+
+    # Add the sources from the object libraries to the main library.
+    target_sources(libgromacs PRIVATE $<TARGET_OBJECTS:${object_library}>)
+endforeach()
+gmx_target_compile_options(libgromacs)
+target_compile_definitions(libgromacs PRIVATE HAVE_CONFIG_H)
+target_include_directories(libgromacs SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
+
+if (GMX_GPU_OPENCL)
     option(GMX_EXTERNAL_CLFFT "True if an external clFFT is required to be used" FALSE)
     mark_as_advanced(GMX_EXTERNAL_CLFFT)
 
@@ -255,41 +267,13 @@ a clFFT package, or use the latest GROMACS 2018 point release.")
     endif()
 endif()
 
-# Recent versions of gcc and clang give warnings on scanner.cpp, which
-# is a generated source file. These are awkward to suppress inline, so
-# we do it in the compilation command (after testing that the compiler
-# supports the suppressions). Same issue exists for nonbonded kernels
-# so we supress them for all generated files.
-include(CheckCXXCompilerFlag)
-check_cxx_compiler_flag("-Wno-unused -Wno-unused-parameter" HAS_NO_UNUSED)
-check_cxx_compiler_flag(-Wno-missing-declarations HAS_NO_MISSING_DECL)
-check_cxx_compiler_flag(-Wno-missing-prototypes HAS_NO_MISSING_PROTO)
-check_cxx_compiler_flag(/wd4101 HAS_NO_MSVC_UNUSED)
-if (NOT MSVC)
-    check_cxx_compiler_flag(-wd1419 HAS_DECL_IN_SOURCE)
-endif()
-if (HAS_NO_UNUSED)
-    target_compile_options(libgromacs_generated PRIVATE "-Wno-unused;-Wno-unused-parameter")
-endif()
-if (HAS_NO_MISSING_DECL)
-    target_compile_options(libgromacs_generated PRIVATE "-Wno-missing-declarations")
-endif()
-# TODO The group scheme kernels don't use proper function prototype
-# declarations, and clang warns about such use, which we suppress
-# rather than fix. We would prefer to use no suppressions. However
-# other compilers do not support such a warning suppression for C++
-# source files, and issue warnings about that. Remove the use of
-# -Wno-missing-prototypes here and above when the group scheme is
-# removed.
-if (HAS_NO_MISSING_PROTO AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-    target_compile_options(libgromacs_generated PRIVATE "-Wno-missing-prototypes")
-endif()
-if (HAS_NO_MSVC_UNUSED)
-    target_compile_options(libgromacs_generated PRIVATE "/wd4101")
-endif()
-if (HAS_DECL_IN_SOURCE)
-    target_compile_options(libgromacs_generated PRIVATE "-wd1419")
-endif()
+# Permit GROMACS code to include externally developed headers, such as
+# the functionality from the nonstd project that we use for
+# gmx::compat::optional. These are included as system headers so that
+# no warnings are issued from them.
+#
+# TODO Perhaps generalize this for all headers from src/external
+target_include_directories(libgromacs SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
 
 if(SIMD_AVX_512_CXX_SUPPORTED AND NOT ("${GMX_SIMD_ACTIVE}" STREQUAL "AVX_512_KNL"))
     # Since we might be overriding -march=core-avx2, add a flag so we don't warn for this specific file.
@@ -298,8 +282,38 @@ if(SIMD_AVX_512_CXX_SUPPORTED AND NOT ("${GMX_SIMD_ACTIVE}" STREQUAL "AVX_512_KN
     set_source_files_properties(hardware/identifyavx512fmaunits.cpp PROPERTIES COMPILE_FLAGS "${SIMD_AVX_512_CXX_FLAGS} ${CXX_NO_UNUSED_OPTION_WARNING_FLAGS}")
 endif()
 
+# Do any special handling needed for .cpp files that use
+# CUDA runtime headers
+if (GMX_GPU_CUDA AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    foreach(_compile_flag ${NVCC_CLANG_SUPPRESSIONS_CXXFLAGS})
+        set(GMX_CUDA_CLANG_FLAGS "${GMX_CUDA_CLANG_FLAGS} ${_compile_flag}")
+    endforeach()
+    if (GMX_CLANG_CUDA)
+        foreach (_file ${LIBGROMACS_SOURCES})
+            get_filename_component(_ext ${_file} EXT)
+            get_source_file_property(_cuda_source_format ${_file} CUDA_SOURCE_PROPERTY_FORMAT)
+            if ("${_ext}" STREQUAL ".cu" OR _cuda_source_format)
+                gmx_compile_cuda_file_with_clang(${_file})
+            endif()
+        endforeach()
+    else()
+        get_property(CUDA_SOURCES GLOBAL PROPERTY CUDA_SOURCES)
+        set_source_files_properties(${CUDA_SOURCES} PROPERTIES COMPILE_FLAGS ${GMX_CUDA_CLANG_FLAGS})
+    endif()
+endif()
+
+# Only add the -fsycl flag to sources that really need it
+if (GMX_GPU_SYCL)
+    get_property(SYCL_SOURCES GLOBAL PROPERTY SYCL_SOURCES)
+    add_sycl_to_target(TARGET libgromacs SOURCES ${SYCL_SOURCES})
+endif()
+
 gmx_setup_tng_for_libgromacs()
 
+# We apply the SYCL flag explicitly just for libgromacs, since bugs in the beta versions of
+# icpx/dpcpp leads to crashes if we try to link an library without any SYCL code with the
+# -fsycl flag enabled. Once that bug is fixed, we should change it to simply add
+# SYCL_CXX_FLAGS to GMX_SHARED_LINKER_FLAGS.
 target_link_libraries(libgromacs
                       PRIVATE
                       ${EXTRAE_LIBRARIES}
@@ -307,10 +321,66 @@ target_link_libraries(libgromacs
                       ${GMX_COMMON_LIBRARIES}
                       ${FFT_LIBRARIES} ${LINEAR_ALGEBRA_LIBRARIES}
                       ${THREAD_LIB} ${GMX_SHARED_LINKER_FLAGS}
+                      ${SYCL_CXX_FLAGS}
                       ${OpenCL_LIBRARIES}
+                      $<$<PLATFORM_ID:SunOS>:socket>
                       PUBLIC
                       ${GMX_PUBLIC_LIBRARIES}
                       )
+target_link_libraries(libgromacs PUBLIC legacy_api)
+# Dependencies from libgromacs to the modules are set up here, but
+# once the add_subdirectory() commands are re-ordered then
+# responsibility for setting this up will move to the respective
+# modules.
+target_link_libraries(libgromacs PRIVATE
+                      $<BUILD_INTERFACE:analysisdata>
+                      $<BUILD_INTERFACE:applied_forces>
+                      $<BUILD_INTERFACE:commandline>
+                      $<BUILD_INTERFACE:compat>
+                      $<BUILD_INTERFACE:coordinateio>
+                      $<BUILD_INTERFACE:correlationfunctions>
+                      $<BUILD_INTERFACE:domdec>
+#                      $<BUILD_INTERFACE:energyanalysis>
+                      $<BUILD_INTERFACE:essentialdynamics>
+                      $<BUILD_INTERFACE:ewald>
+                      $<BUILD_INTERFACE:fft>
+                      $<BUILD_INTERFACE:fileio>
+                      $<BUILD_INTERFACE:gmxana>
+                      $<BUILD_INTERFACE:gmxlib>
+                      $<BUILD_INTERFACE:gmxpreprocess>
+                      $<BUILD_INTERFACE:gpu_utils>
+                      $<BUILD_INTERFACE:hardware>
+                      $<BUILD_INTERFACE:imd>
+                      $<BUILD_INTERFACE:linearalgebra>
+                      $<BUILD_INTERFACE:listed_forces>
+                      $<BUILD_INTERFACE:math>
+                      $<BUILD_INTERFACE:mdlib>
+                      $<BUILD_INTERFACE:mdrun>
+                      $<BUILD_INTERFACE:mdrunutility>
+                      $<BUILD_INTERFACE:mdspan>
+                      $<BUILD_INTERFACE:mdtypes>
+                      $<BUILD_INTERFACE:mimic>
+                      $<BUILD_INTERFACE:modularsimulator>
+                      $<BUILD_INTERFACE:nbnxm>
+                      $<BUILD_INTERFACE:onlinehelp>
+                      $<BUILD_INTERFACE:options>
+                      $<BUILD_INTERFACE:pbcutil>
+                      $<BUILD_INTERFACE:pulling>
+                      $<BUILD_INTERFACE:random>
+                      $<BUILD_INTERFACE:restraint>
+                      $<BUILD_INTERFACE:selection>
+                      $<BUILD_INTERFACE:simd>
+                      $<BUILD_INTERFACE:statistics>
+                      $<BUILD_INTERFACE:swap>
+                      $<BUILD_INTERFACE:tables>
+                      $<BUILD_INTERFACE:taskassignment>
+                      $<BUILD_INTERFACE:timing>
+                      $<BUILD_INTERFACE:tools>
+                      $<BUILD_INTERFACE:topology>
+                      $<BUILD_INTERFACE:trajectory>
+                      $<BUILD_INTERFACE:trajectoryanalysis>
+                      $<BUILD_INTERFACE:utility>
+    )
 if (GMX_OPENMP)
     target_link_libraries(libgromacs PUBLIC OpenMP::OpenMP_CXX)
 endif()
@@ -322,10 +392,11 @@ set_target_properties(libgromacs PROPERTIES
 
 gmx_manage_lmfit()
 target_link_libraries(libgromacs PRIVATE lmfit)
+gmx_manage_muparser()
+target_link_libraries(libgromacs PRIVATE muparser)
 
-if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^6\.0")
-   target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS}>)
-endif()
+# Make sure we fix "everything" found by compilers that support that
+gmx_warn_on_everything(libgromacs)
 if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/analyze /analyze:stacksize 70000
      #Control flow warnings are disabled because the commond line output is insufficient. There is no tool
@@ -360,28 +431,42 @@ if (GMX_CLANG_TIDY)
        "${CLANG_TIDY_EXE};-warnings-as-errors=*")
 endif()
 
-gmx_write_installed_header_list()
+# clang-3.6 warns about a number of issues that are not reported by more modern compilers
+# and we know they are not real issues. So we only check that it can compile without error
+# but ignore all warnings.
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^3\.6")
+    target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-w>)
+endif()
 
-# Only install the library in mdrun-only mode if it is actually necessary
-# for the binary
-if (NOT GMX_BUILD_MDRUN_ONLY OR BUILD_SHARED_LIBS)
+# TODO: Stop installing libgromacs. Possibly allow installation during deprecation period with GMX_INSTALL_LEGACY_API.
+if (BUILD_SHARED_LIBS)
     install(TARGETS libgromacs
             EXPORT libgromacs
-            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            COMPONENT libraries)
+            LIBRARY
+                DESTINATION ${CMAKE_INSTALL_LIBDIR}
+                COMPONENT libraries
+            RUNTIME
+                DESTINATION ${CMAKE_INSTALL_BINDIR}
+                COMPONENT libraries
+            ARCHIVE
+                DESTINATION ${CMAKE_INSTALL_LIBDIR}
+                COMPONENT libraries
+            INCLUDES DESTINATION include)
+    target_compile_definitions(libgromacs PUBLIC $<INSTALL_INTERFACE:GMX_DOUBLE=${GMX_DOUBLE_VALUE}>)
+    # legacy headers use c++17 features, so consumer codes need to use that standard, too
+    if(GMX_INSTALL_LEGACY_API)
+        target_compile_features(libgromacs INTERFACE cxx_std_${CMAKE_CXX_STANDARD})
+    endif()
 endif()
+add_library(Gromacs::libgromacs ALIAS libgromacs)
 
-if (NOT GMX_BUILD_MDRUN_ONLY)
-    include(InstallLibInfo.cmake)
-endif()
+include(InstallLibInfo.cmake)
 
 # Technically, the user could want to do this for an OpenCL build
 # using the CUDA runtime, but currently there's no reason to want to
 # do that.
 if (INSTALL_CUDART_LIB) #can be set manual by user
-    if (GMX_USE_CUDA)
+    if (GMX_GPU_CUDA)
         foreach(CUDA_LIB ${CUDA_LIBRARIES})
             string(REGEX MATCH "cudart" IS_CUDART ${CUDA_LIB})
             if(IS_CUDART) #libcuda should not be installed
@@ -396,7 +481,7 @@ if (INSTALL_CUDART_LIB) #can be set manual by user
     endif()
 endif()
 
-if(GMX_USE_OPENCL)
+if(GMX_GPU_OPENCL)
     # Install the utility headers
     file(GLOB OPENCL_INSTALLED_FILES
         gpu_utils/vectype_ops.clh
@@ -412,35 +497,35 @@ if(GMX_USE_OPENCL)
         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/pbcutil
         COMPONENT libraries)
 
-    # Install the NB source and headers
+    # Install the NBNXM source and headers
     file(GLOB OPENCL_INSTALLED_FILES
-        mdlib/nbnxn_consts.h
+        nbnxm/constants.h
         )
     install(FILES ${OPENCL_INSTALLED_FILES}
-        DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/mdlib
+        DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/nbnxm
         COMPONENT libraries)
     file(GLOB OPENCL_INSTALLED_FILES
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernels.cl
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernel.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernel_pruneonly.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernels.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernels_fastgen.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernels_fastgen_add_twincut.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_kernel_utils.clh
-        mdlib/nbnxn_ocl/nbnxn_ocl_consts.h
+        nbnxm/opencl/nbnxm_ocl_kernels.cl
+        nbnxm/opencl/nbnxm_ocl_kernel.clh
+        nbnxm/opencl/nbnxm_ocl_kernel_pruneonly.clh
+        nbnxm/opencl/nbnxm_ocl_kernels.clh
+        nbnxm/opencl/nbnxm_ocl_kernels_fastgen.clh
+        nbnxm/opencl/nbnxm_ocl_kernels_fastgen_add_twincut.clh
+        nbnxm/opencl/nbnxm_ocl_kernel_utils.clh
+        nbnxm/opencl/nbnxm_ocl_consts.h
         )
     install(FILES ${OPENCL_INSTALLED_FILES}
-        DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/mdlib/nbnxn_ocl
+        DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/nbnxm/opencl
         COMPONENT libraries)
 
     # Install the PME source and headers
     file(GLOB OPENCL_INSTALLED_FILES
-        ewald/pme-spread.clh
-        ewald/pme-solve.clh
-        ewald/pme-gather.clh
-        ewald/pme-gpu-utils.clh
-        ewald/pme-program.cl
-        ewald/pme-gpu-types.h
+        ewald/pme_spread.clh
+        ewald/pme_solve.clh
+        ewald/pme_gather.clh
+        ewald/pme_gpu_calculate_splines.clh
+        ewald/pme_program.cl
+        ewald/pme_gpu_types.h
         )
     install(FILES ${OPENCL_INSTALLED_FILES}
         DESTINATION ${GMX_INSTALL_OCLDIR}/gromacs/ewald