gfortran编译错误:_gfortran_set_options等符号多重定义问题
解决gfortran 8.1.0 + CMake拆分exe与DLL时的符号多重定义问题
问题根源
gfortran 8.1.0默认会将Fortran运行时库静态链接到每个编译目标(exe和dll),导致_gfortran_set_options这类运行时符号在两个目标中都被重复定义,链接阶段触发冲突错误。
解决方案
1. 强制使用动态链接的Fortran运行时库
给gfortran添加-shared-libgfortran编译选项,让exe和DLL共享同一个动态版本的运行时库,避免静态库符号重复嵌入。
2. 调整CMake配置
确保DLL正确导出符号,同时让主程序能找到DLL的模块文件。以下是完整的CMake配置示例:
cmake_minimum_required(VERSION 3.10) project(FortranDLLDemo Fortran) # 全局设置gfortran使用动态运行时库 set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -shared-libgfortran") # 编译DLL目标 add_library(mydll SHARED src/dll_source.f90) # 指定模块输出目录,主程序需引用此目录找到模块 set_target_properties(mydll PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules) # 编译主程序 add_executable(main_exe src/main_source.f90) # 链接DLL库 target_link_libraries(main_exe PRIVATE mydll) # 让主程序能找到DLL导出的模块 target_include_directories(main_exe PRIVATE ${CMAKE_BINARY_DIR}/modules)
3. 修正DLL与主程序源码
- DLL源码(dll_source.f90):明确导出需要被主程序调用的符号
module mydll_mod implicit none ! 使用gfortran的属性标记导出子程序 !GCC$ ATTRIBUTES DLLEXPORT :: hello_from_dll contains subroutine hello_from_dll() print *, "Hello from DLL!" end subroutine hello_from_dll end module mydll_mod
- 主程序源码(main_source.f90):正常引用DLL的模块即可
program main use mydll_mod implicit none call hello_from_dll() print *, "Main program running!" end program main
错误日志解释
编译日志中出现的
_gfortran_set_options等符号多重定义,本质是静态链接的运行时库在exe和DLL中都包含了相同的符号实现,导致链接器判定符号重复。启用-shared-libgfortran后,两个目标都会动态链接到系统的libgfortran动态库,从根本上避免符号重复问题。
内容的提问来源于stack exchange,提问作者stone
相关产品推荐
相关产品推荐

