CUDA + Fortran links against the wrong version of libgfortran
When enabling both Fortran and CUDA, the Fortran compiler wants to compile against the wrong version of libgfortran. Specifically, I'm using gfortran 7.3.0, but CMake passes the flag -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.1
to gfortran when compiling. Here is a minimal example:
# CMakeLists.txt cmake_minimum_required(VERSION 3.8) project(cuda LANGUAGES Fortran CUDA) add_executable(main main.f90 tmp.cu)
# main.f90 end
tmp.cu is an empty file. Running
cmake . && make VERBOSE=1
results in
-- The Fortran compiler identification is GNU 7.3.0 -- The CUDA compiler identification is NVIDIA 9.1.85 -- Check for working Fortran compiler: /usr/bin/f95 -- Check for working Fortran compiler: /usr/bin/f95 -- works -- Detecting Fortran compiler ABI info -- Detecting Fortran compiler ABI info - done -- Checking whether /usr/bin/f95 supports Fortran 90 -- Checking whether /usr/bin/f95 supports Fortran 90 -- yes -- Check for working CUDA compiler: /opt/cuda/bin/nvcc -- Check for working CUDA compiler: /opt/cuda/bin/nvcc -- works -- Detecting CUDA compiler ABI info -- Detecting CUDA compiler ABI info - done -- Configuring done -- Generating done -- Build files have been written to: /home/raul/tmp/aims/build /usr/bin/cmake -H/home/raul/tmp/aims -B/home/raul/tmp/aims/build --check-build-system CMakeFiles/Makefile.cmake 0 /usr/bin/cmake -E cmake_progress_start /home/raul/tmp/aims/build/CMakeFiles /home/raul/tmp/aims/build/CMakeFiles/progress.marks make -f CMakeFiles/Makefile2 all make[1]: Entering directory '/home/raul/tmp/aims/build' make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/depend make[2]: Entering directory '/home/raul/tmp/aims/build' cd /home/raul/tmp/aims/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/raul/tmp/aims /home/raul/tmp/aims /home/raul/tmp/aims/build /home/raul/tmp/aims/build /home/raul/tmp/aims/build/CMakeFiles/main.dir/DependInfo.cmake --color= Dependee "/home/raul/tmp/aims/build/CMakeFiles/main.dir/DependInfo.cmake" is newer than depender "/home/raul/tmp/aims/build/CMakeFiles/main.dir/depend.internal". Dependee "/home/raul/tmp/aims/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/raul/tmp/aims/build/CMakeFiles/main.dir/depend.internal". Scanning dependencies of target main make[2]: Leaving directory '/home/raul/tmp/aims/build' make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/requires make[2]: Entering directory '/home/raul/tmp/aims/build' make[2]: Nothing to be done for 'CMakeFiles/main.dir/requires'. make[2]: Leaving directory '/home/raul/tmp/aims/build' make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build make[2]: Entering directory '/home/raul/tmp/aims/build' [ 25%] Building Fortran object CMakeFiles/main.dir/main.f90.o /usr/bin/f95 -c /home/raul/tmp/aims/main.f90 -o CMakeFiles/main.dir/main.f90.o [ 50%] Building CUDA object CMakeFiles/main.dir/tmp.cu.o /opt/cuda/bin/nvcc -x cu -c /home/raul/tmp/aims/tmp.cu -o CMakeFiles/main.dir/tmp.cu.o [ 75%] Linking CUDA device code CMakeFiles/main.dir/cmake_device_link.o /usr/bin/cmake -E cmake_link_script CMakeFiles/main.dir/dlink.txt --verbose=1 /opt/cuda/bin/nvcc -Xcompiler=-fPIC -Wno-deprecated-gpu-targets -shared -dlink CMakeFiles/main.dir/main.f90.o CMakeFiles/main.dir/tmp.cu.o -o CMakeFiles/main.dir/cmake_device_link.o -L/opt/cuda/lib64/stubs -L/opt/cuda/lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.1 [100%] Linking Fortran executable main /usr/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1 /usr/bin/f95 CMakeFiles/main.dir/main.f90.o CMakeFiles/main.dir/tmp.cu.o CMakeFiles/main.dir/cmake_device_link.o -o main -L/opt/cuda/lib64/stubs -L/opt/cuda/lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.1 -lcudadevrt -lcudart_static -lrt -lpthread -ldl -lstdc++ make[2]: Leaving directory '/home/raul/tmp/aims/build' [100%] Built target main make[1]: Leaving directory '/home/raul/tmp/aims/build' /usr/bin/cmake -E cmake_progress_start /home/raul/tmp/aims/build/CMakeFiles 0
which looks fine. However, if I try to run the executable I get
./main: error while loading shared libraries: libgfortran.so.3: cannot open shared object file: No such file or directory
If you look at the compilation output, a bunch of flags have been passed to nvcc
, including -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.1
. This is because nvcc
requires GCC version 6 and no higher. However, in the next lines, the same flags have been passed to f95
, which results in the runtime error. Is it possible for me to have a control over which flags are passed to f95
(ideally, I would remove -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.4.1
)?
My current solution is to set
set(CMAKE_EXE_LINKER_FLAGS "-L/usr/lib ${CMAKE_EXE_LINKER_FLAGS}")
which forces to link against libgfortran.so.4.