From 80c7bc179b24c226c89023737f198badf6a9a36d Mon Sep 17 00:00:00 2001 From: Markus Blatt Date: Tue, 25 Feb 2020 16:54:53 +0100 Subject: [PATCH] Make mixing incompatible host compiler/device compiler versions fail. We experienced weired linker errors when using host compiler version for compilation that were not supported by the nvcc used to compile the cuda code: ``` [ 15%] Linking CXX executable bin/test_timer /usr/bin/ld: /home/mblatt/src/dune/opm-2.6/opm-common/opm-seq/lib/libopmcommon.a(Parser.cpp.o): in function `Opm::(anonymous namespace)::file& std::vector >::emplace_back, std::allocator >&>(std::filesystem::__cxx11::path&, std::__cxx11::basic_string, std::allocator >&)': Parser.cpp:(.text+0x1096): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()' /usr/bin/ld: Parser.cpp:(.text+0x10ad): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()' /usr/bin/ld: /home/mblatt/src/dune/opm-2.6/opm-common/opm-seq/lib/libopmcommon.a(Parser.cpp.o): in function `Opm::(anonymous namespace)::ParserState::loadFile(std::filesystem::__cxx11::path const&)': Parser.cpp:(.text+0x23a1): undefined reference to `std::filesystem::canonical(std::filesystem::__cxx11::path const&)' /usr/bin/ld: Parser.cpp:(.text+0x24e0): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()' ``` The reason turned out to be that the library path was build up by paths of the old (g++-7) compiler used by nvcc and the actual (newer) compiler g++-8. This completely messed up the linker paths for CMake. To detect this situation already when running cmake we have resorted to first setting the CMAKE_CUDA_FLAGS to force cmake to make nvcc use the host compiler and to activate CUDA (if available) before calling `find_package(CUDA)`. If the host compiler is not supported CMake will error out during `enable(CUDA)` Note that we still use (deprecated) FindCUDA later to determine the libraries to link to. The users has the option to either deactivate CUDA by setting `-DCMAKE_DISABLE_FIND_PACKAGE_CUDA=ON` or to use a compiler supported by nvcc (setting `-DCMAKE_CXX_COMPILER=compiler`). Additionally we do not try to activate CUDA the CMake version is < 3.8. Please note that previously CMake would have errored out here anyway since we used the unsupported `enable_language(CUDA)` even in this case. Closes #2363. --- CMakeLists.txt | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c0f29153..929ed32ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,37 @@ project(opm-simulators C CXX) cmake_minimum_required (VERSION 2.8) -find_package(CUDA) +# Make sure we are using the same compiler underneath +# NVCC as for the rest. In the case that NVCC does not support +# that compiler it will error out. Unfortunately this will only +# work CMake >= 3.8. We found no way to make FindCUDA.cmake error +# out. It seems to ignore CMAKE_NVCC_FLAGS and CMAKE. Additionally +# our way of specifying cuda source files never worked for CMake +# version < 3.8. Hence we deactivate cuda for these versions. +if(NOT CMAKE_DISABLE_FIND_PACKAGE_CUDA AND + CMAKE_VERSION VERSION_GREATER_EQUAL 3.8) + if(NOT DEFINED ENV{CUDAHOSTCXX} AND + (NOT CMAKE_CUDA_FLAGS OR NOT CMAKE_CUDA_FLAGS MATCHES ".*-ccbin .*")) + set(CMAKE_CUDA_FLAGS "-ccbin ${CMAKE_CXX_COMPILER} ${CMAKE_CUDA_FLAGS}") + endif() + include(CheckLanguage) + # Unfortunately check_language(CUDA) will only check whether there is + # a nvcc compiler. It will not check whether compilation with the above + # option works. Since the OPTIONAL flag of enable_language is currently + # ignored CMake will error out below if the options do not work. + check_language(CUDA) + if(CMAKE_CUDA_COMPILER) + enable_language(CUDA OPTIONAL) + endif() + # While the documentation says that it is deprecated, FindCUDA seems the + # only easy way to determine the cublas and cusparse libraries. + # Hence we call it unconditionally + find_package(CUDA) +endif() if(CUDA_FOUND) - include_directories(${CUDA_INCLUDE_DIRS}) - enable_language(CUDA) set(HAVE_CUDA 1) + include_directories(${CUDA_INCLUDE_DIRS}) endif() option(SIBLING_SEARCH "Search for other modules in sibling directories?" ON) @@ -320,7 +345,7 @@ endif() # must link libraries after target 'flow' has been defined if(CUDA_FOUND) - target_link_libraries( opmsimulators ${CUDA_cublas_LIBRARY} ) - target_link_libraries( opmsimulators ${CUDA_cusparse_LIBRARY} ) + target_link_libraries( opmsimulators PUBLIC ${CUDA_cusparse_LIBRARY} ) + target_link_libraries( opmsimulators PUBLIC ${CUDA_cublas_LIBRARY} ) endif()