使用Makefile编译含HDF5的Fortran 90代码时遇未定义引用错误
解决HDF5 Fortran代码编译时的未定义引用问题
看起来你遇到的是链接阶段的依赖缺失问题——HDF5的Fortran接口库不是独立的,它依赖于HDF5核心库以及可能的系统压缩库,而且链接顺序也很关键。我来帮你修正Makefile并解释原因:
问题根源
你当前的LIBSHDF只引用了libhdf5_fortran.a,但这个库本身依赖HDF5的核心库libhdf5.a,如果你的HDF5编译时启用了压缩(比如DEFLATE/SZIP),还需要链接对应的系统压缩库。另外,链接顺序不对也会导致未定义引用(依赖库要放在被依赖库的后面)。
修正后的完整Makefile
# HDF5二进制文件位置(下方包含include/和lib/目录) HDF5 = /fs/posgrado16/other0/guido/libraries/hdf5/serial # 编译器 FC = gfortran # 编译选项:启用预处理、指定Fortran90标准、优化、引入HDF5头文件 FCFLAGS = -cpp -std=f90 -O2 -I$(HDF5)/include # ------ 此后无机器特定路径/变量 ----- # HDF5相关库:Fortran接口库在前,核心库在后 FORTRAN_HDF5_LIB = $(HDF5)/lib/libhdf5_fortran.a CORE_HDF5_LIB = $(HDF5)/lib/libhdf5.a # 系统依赖库:根据HDF5编译配置调整,一般需要这些 SYSTEM_LIBS = -lz -lsz -ldl -lm FSOURCE = h5_crtgrpar.f90 OBJECTS = $(FSOURCE:.f90=.o) EXECUTABLE = $(FSOURCE:.f90=.exe) # 完整链接库列表:接口库 → 核心库 → 系统库 LIBSHDF = $(FORTRAN_HDF5_LIB) $(CORE_HDF5_LIB) $(SYSTEM_LIBS) # 默认目标:生成可执行文件 all: $(EXECUTABLE) # 链接目标文件生成可执行文件 $(EXECUTABLE): $(OBJECTS) $(FC) $(OBJECTS) $(LIBSHDF) -o $@ # 编译Fortran源文件为目标文件 %.o: %.f90 $(FC) $(FCFLAGS) -c $< -o $@ # 清理生成的文件 clean: rm -f $(OBJECTS) $(EXECUTABLE)
关键修改点说明
补全依赖库:
libhdf5.a:HDF5的核心功能库,Fortran接口库必须依赖它才能工作-lz:zlib压缩库(如果你的HDF5启用了DEFLATE压缩)-lsz:SZIP压缩库(如果你的HDF5支持SZIP压缩,没有的话可以去掉)-ldl:动态加载库(部分HDF5编译配置需要)-lm:数学库(HDF5内部用到了数学运算函数)
优化编译规则:
- 新增了通用的
.f90→.o编译规则,确保所有Fortran源文件都用统一的编译选项处理 - 加入了
-cpp选项(如果你的代码里有预处理指令,比如#ifdef,可以保留;没有的话也可以去掉)
- 新增了通用的
更简单的替代方案:用HDF5自带的编译器包装器
HDF5提供了h5fc工具,它会自动处理所有依赖的include路径和库,完全不用手动配置。如果你的环境里能找到h5fc,可以直接用这个简化版Makefile:FC = h5fc FCFLAGS = -O2 FSOURCE = h5_crtgrpar.f90 OBJECTS = $(FSOURCE:.f90=.o) EXECUTABLE = $(FSOURCE:.f90=.exe) all: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(FC) $(OBJECTS) -o $@ %.o: %.f90 $(FC) $(FCFLAGS) -c $< -o $@ clean: rm -f $(OBJECTS) $(EXECUTABLE)
额外排查建议
如果还是出现未定义引用:
- 看错误信息里的具体符号,判断是属于哪个库的,再调整链接列表
- 确认你的HDF5是用
gfortran编译的——如果HDF5是用Intel Fortran等其他编译器编译的,和你的gfortran不兼容也会导致链接失败
内容的提问来源于stack exchange,提问作者Guido
相关产品推荐
相关产品推荐

