即使在构建可执行文件时,CMake 3.0 + Fortran + CUDA也需要-fPIC

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了即使在构建可执行文件时,CMake 3.0 + Fortran + CUDA也需要-fPIC相关的知识,希望对你有一定的参考价值。

这是一个CMake问题。除非我包含-fPIC标志,否则在使用Intel Fortran编译器时,我无法使用CUDA支持编译Fortran可执行文件。问题是除非我正在建立一个图书馆,否则-fPIC不应该是必要的。

以下是最小的例子:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(cuda LANGUAGES Fortran CXX)
find_package(CUDA)
cuda_add_executable(main main.f90)

# main.f90
end

当我尝试构建和运行时,

cmake -D CMAKE_Fortran_COMPILER=ifort .. && make VERBOSE=1

我得到以下内容:

-- The Fortran compiler identification is Intel 18.0.0.20170811
-- The CXX compiler identification is GNU 7.3.0
-- Check for working Fortran compiler: /opt/intel/compilers_and_libraries_2018.0.128/linux/bin/intel64/ifort
-- Check for working Fortran compiler: /opt/intel/compilers_and_libraries_2018.0.128/linux/bin/intel64/ifort  -- works
-- Detecting Fortran compiler ABI info
-- Detecting Fortran compiler ABI info - done
-- Checking whether /opt/intel/compilers_and_libraries_2018.0.128/linux/bin/intel64/ifort supports Fortran 90
-- Checking whether /opt/intel/compilers_and_libraries_2018.0.128/linux/bin/intel64/ifort supports Fortran 90 -- yes
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found CUDA: /opt/cuda (found version "9.1")
-- Configuring done
-- Generating done
-- Build files have been written to: /home/raul/tmp/cuda/build
/usr/bin/cmake -H/home/raul/tmp/cuda -B/home/raul/tmp/cuda/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/raul/tmp/cuda/build/CMakeFiles /home/raul/tmp/cuda/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/raul/tmp/cuda/build'
make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/depend
make[2]: Entering directory '/home/raul/tmp/cuda/build'
cd /home/raul/tmp/cuda/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/raul/tmp/cuda /home/raul/tmp/cuda /home/raul/tmp/cuda/build /home/raul/tmp/cuda/build /home/raul/tmp/cuda/build/CMakeFiles/main.dir/DependInfo.cmake --color=
Dependee "/home/raul/tmp/cuda/build/CMakeFiles/main.dir/DependInfo.cmake" is newer than depender "/home/raul/tmp/cuda/build/CMakeFiles/main.dir/depend.internal".
Dependee "/home/raul/tmp/cuda/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/raul/tmp/cuda/build/CMakeFiles/main.dir/depend.internal".
Scanning dependencies of target main
make[2]: Leaving directory '/home/raul/tmp/cuda/build'
make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/requires
make[2]: Entering directory '/home/raul/tmp/cuda/build'
make[2]: Nothing to be done for 'CMakeFiles/main.dir/requires'.
make[2]: Leaving directory '/home/raul/tmp/cuda/build'
make -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
make[2]: Entering directory '/home/raul/tmp/cuda/build'
[ 50%] Building Fortran object CMakeFiles/main.dir/main.f90.o
/opt/intel/compilers_and_libraries_2018.0.128/linux/bin/intel64/ifort  -I/opt/cuda/include   -c /home/raul/tmp/cuda/main.f90 -o CMakeFiles/main.dir/main.f90.o
[100%] Linking CXX executable main
/usr/bin/cmake -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1
/usr/bin/c++    -rdynamic CMakeFiles/main.dir/main.f90.o  -o main /opt/cuda/lib64/libcudart_static.a -lpthread -ldl -lrt -lifport -lifcoremt -limf -lsvml -lipgo -lirc -lpthread -lsvml -lirc_s -ldl
/usr/bin/ld: CMakeFiles/main.dir/main.f90.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../lib/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/usr/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:97: main] Error 1
make[2]: Leaving directory '/home/raul/tmp/cuda/build'
make[1]: *** [CMakeFiles/Makefile2:69: CMakeFiles/main.dir/all] Error 2
make[1]: Leaving directory '/home/raul/tmp/cuda/build'
make: *** [Makefile:84: all] Error 2

如果我使用CMake的较新的CUDA功能,例如,我没有得到构建错误。

# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(cuda LANGUAGES Fortran CUDA)
add_executable(main main.f90)

但是,我们目前的政策是支持CMake 3.0,因此我不能使用更简单的版本。此外,如果我使用ifort代替gfortran,我不会得到任何错误。我目前正在研究CMake附带的FindCUDA.cmake,但我还没有找到解决方案。有什么想法吗?

答案

我找到了一个现在有效的解决方案,但它根本不是微不足道的。首先,应该使用ifp的icpc(不要求CMake> = 3.8)。事实证明,在icpc链接的许多库中(如果没有运行make VERBOSE=1,你将看不到它们),其中一个(但不是其他)应该与静态链接。因此,通过指定

target_link_libraries(main ifcoremt.a)

在CMakeLists.txt似乎解决了这个问题,至少对我而言。

以上是关于即使在构建可执行文件时,CMake 3.0 + Fortran + CUDA也需要-fPIC的主要内容,如果未能解决你的问题,请参考以下文章

CMake构建静态可执行文件

cmake 创建解决方案时未链接 64 位可执行文件

CMake 多配置生成器使用错误的构建目录

CMake:是不是可以仅从静态库而不是源代码构建可执行文件?

QtCreator 无法识别 cmake

在Android Studio 3.0中构建PIE和非PIE可执行文件