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<Opm::(anonymous namespace)::file, std::allocator<Opm::(anonymous namespace)::file> >::emplace_back<std::filesystem::__cxx11::path&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(std::filesystem::__cxx11::path&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
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.
This commit is contained in:
Markus Blatt 2020-02-25 16:54:53 +01:00
parent 8cd9da0d83
commit 80c7bc179b

View File

@ -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()