Fortran代码经CMake编译未生成可执行文件及链接错误求助
问题背景
核心初始CMake配置如下:
set(SRCS srcA.FOR srcB.FOR ... srcK.FOR) add_executable(filename ${SRCS})
编译过程无报错,仅输出三类警告:
- 存在未使用的变量(自身代码问题但不影响编译生成)
- "该名称未指定具体类型"
- "未对文件'path/to/file/filename.FOR.o'执行任何操作"
编译输出存在Linking Fortran executable filename、Built target filename提示,按逻辑应生成可执行文件,但使用find -type f -name "*.exe"和find -type f -name "*filename*"均无法找到对应文件。
补充信息1:警告详情
每个源文件对应一条相同警告(仅文件名不同):
ifort: warning #10145: no action performed for file 'CMakeFiles/dynamicmpm.dir/getversion.for.o'
补充信息2:完整CMake配置
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(MPM) enable_language (Fortran) get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME) MESSAGE("Fortran_COMPILER_NAME = ${Fortran_COMPILER_NAME}") set(CMAKE_Fortran_FLAGS "-nologo -O2 -assume buffered_io -fpp -Dinternal_release -reentrancy threaded -free -warn all -real_size 64 -Qauto -fp:strict -fp:constant -libs:static -threads -Qmkl:sequential -c -Qm64") if (Fortran_COMPILER_NAME MATCHES "gfortran") # gfortran set(COMMON_FLAGS "-fmax-identifier-length=63 -ffree-form -ffree-line-length-none -fdefault-real-8") set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} ${COMMON_FLAGS}") set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${COMMON_FLAGS}") endif() set(SRCS srcA.FOR srcB.FOR ... srcK.FOR) # 源文件较多此处用占位符替代 add_executable(filename ${SRCS})
补充信息3:修改配置后MKL链接报错
调整CMake配置后出现如下链接错误:
[100%] Linking Fortran executable dynamicmpm CMakeFiles/dynamicmpm.dir/Solver.FOR.o: In function `modsolver_mp_createprofiledss_': Solver.FOR:(.text+0x1143): undefined reference to `dss_create_' Solver.FOR:(.text+0x11a8): undefined reference to `dss_define_structure_' Solver.FOR:(.text+0x1471): undefined reference to `dss_reorder_' CMakeFiles/dynamicmpm.dir/Solver.FOR.o: In function `modsolver_mp_solveequations_': Solver.FOR:(.text+0x35ec): undefined reference to `dss_factor_real_d__' Solver.FOR:(.text+0x361d): undefined reference to `dss_solve_real_d_' CMakeFiles/dynamicmpm.dir/Solver.FOR.o: In function `modsolver_mp_destroyequations_': Solver.FOR:(.text+0x4495): undefined reference to `dss_delete_' CMakeFiles/dynamicmpm.dir/Solver.FOR.o: In function `modsolver_mp_initialisereducedsolution_': Solver.FOR:(.text+0x5a58): undefined reference to `dss_create_' Solver.FOR:(.text+0x5abd): undefined reference to `dss_define_structure_' Solver.FOR:(.text+0x606d): undefined reference to `dss_reorder_'
用户已在Solver.FOR开头添加use mkl_dss语句,且mkl_dss.f90已加入SRCS配置:set(SRCS srcA.FOR srcB.for mkl_dss.f90 ... otherSources.FOR)
找不到可执行文件问题
核心原因是你在CMAKE_Fortran_FLAGS中手动添加了-c参数,该参数会强制编译器只执行编译步骤生成目标文件、跳过链接步骤,自然不会生成最终的可执行文件。警告#10145也是该参数导致的:链接阶段调用编译器时携带-c参数,编译器会忽略输入的.o目标文件,直接输出无操作提示。
同时Linux下可执行文件默认没有.exe后缀,你的搜索规则本身也无法匹配到正确文件。
解决方法:直接删除CMAKE_Fortran_FLAGS里的-c参数,CMake会自动根据编译阶段分配对应参数。另外你当前全局设置的编译参数里包含大量Windows平台ifort专属参数(比如-nologo、-Qauto、-fp:strict等),Linux下ifort无法识别,建议移到Windows专属的判断分支中,或者替换为Linux平台的对应参数。
MKL链接报错问题
mkl_dss.f90仅包含MKL DSS模块的接口定义,实际功能实现放在MKL预编译库文件中,仅将源文件加入编译队列无法解决链接问题,需要手动链接MKL对应的库文件:
- 确认系统中MKL的安装路径,默认OneAPI环境下路径为
/opt/intel/oneapi/mkl/latest - 在CMake的
add_executable语句后添加如下配置(以Intel编译器、64位、顺序MKL为例):
set(MKL_ROOT /opt/intel/oneapi/mkl/latest) target_include_directories(filename PRIVATE ${MKL_ROOT}/include) target_link_directories(filename PRIVATE ${MKL_ROOT}/lib/intel64) target_link_libraries(filename mkl_intel_lp64 mkl_sequential mkl_core pthread m)
如果需要使用并行MKL,将mkl_sequential替换为mkl_intel_thread,再额外添加iomp5到链接库列表即可。
内容的提问来源于stack exchange,提问作者Sam Hinkie

