如何修改CMakeLists.txt解决HIP与Fortran混合编译的未定义引用问题
HIP与Fortran混合代码CMake编译链接错误解决
问题描述
现有一套由fcode.f90、hipcode.cpp、main.f90组成的HIP与Fortran混合代码,使用Makefile可正常编译运行,但自行编写CMakeLists.txt后,执行CXX=hipcc cmake .. && make -j编译通过,却出现**undefined reference to `hipcode_'**错误,需修改CMakeLists.txt解决该问题。
相关代码文件
fcode.f90
SUBROUTINE fcode() implicit double precision (a-h, o-z) parameter (M=64) dimension x(M),y(M),z(M) do k=1, M x(k) = 1.0 y(k) = 2.0 z(k) = 0.0 end do call hipcode(x,y,z,M) do k = 1, M if ( z(k) .ne. 3.0 ) then write(6,*) 'u fail !' return endif end do write(6,*)' PASSED !' return end
hipcode.cpp
#include <hip/hip_runtime.h> #define HIP_ASSERT(status) assert(status == hipSuccess) __global__ void add(double *x, double *y, double *z, const unsigned int M) { z[threadIdx.x] = x[threadIdx.x] + y[threadIdx.x]; } extern "C" void hipcode_(double *h_x, double *h_y, double *h_z, int &M) { HIP_ASSERT(hipSetDevice(0)); double *d_x, *d_y, *d_z; HIP_ASSERT(hipMalloc((void **)&d_x, M * sizeof(double))); HIP_ASSERT(hipMalloc((void **)&d_y, M * sizeof(double))); HIP_ASSERT(hipMalloc((void **)&d_z, M * sizeof(double))); HIP_ASSERT(hipMemcpy(d_x, h_x, M * sizeof(double), hipMemcpyHostToDevice)); HIP_ASSERT(hipMemcpy(d_y, h_y, M * sizeof(double), hipMemcpyHostToDevice)); HIP_ASSERT(hipMemcpy(d_z, h_z, M * sizeof(double), hipMemcpyHostToDevice)); hipLaunchKernelGGL(add, 1, 64, 0, 0, d_x, d_y, d_z, M); HIP_ASSERT(hipMemcpy(h_z, d_z, M * sizeof(double), hipMemcpyDeviceToHost)); hipFree(d_x); hipFree(d_y); hipFree(d_z); }
main.f90
call fcode() stop end
可正常运行的Makefile
OBJS=main.o fcode.o hipcode.o FC=gfortran HIPCC=hipcc FCFLAGS=-c HIPCCFLAGS=-c LDFLAGS=-lgfortran all : $(HIPCC) $(HIPCCFLAGS) hipcode.cpp $(FC) $(FCFLAGS) fcode.f90 $(FC) $(FCFLAGS) main.f90 $(HIPCC) $(OBJS) $(LDFLAGS) -o test
当前使用的CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(test LANGUAGES Fortran CXX) # source file: hipcode.cpp fcode.f90 main.f90 # target: # hipcc -c hipcode.cpp # gfortran -c fcode.f90 # gfortran -c main.f90 # hipcc hipcode.o fcode.o main.o -lgfortran -o test set(sources_list hipcode.cpp) set(raw_sources_list_f90 fcode.f90) # find hip find_package(HIP QUIET) set(CMAKE_HIP_FLAGS "${CMAKE_CXX_FLAGS} -D__HIP_PLATFORM_HCC__ --offload-arch=gfx906") set(HIP_CLANG_FLAGS "${HIP_CLANG_FLAG} --hip-link") set_source_files_properties(${sources_list} PROPERTIES HIP_SOURCE_PROPERTY_FORMAT 1) set(MY_SOURCE_FILES ${sources_list}) set(MY_TARGET_NAME hipcode) set(MY_HIPCC_OPTIONS "--hip-link") set(HIP_TARGET_LINK_LIB "rocm/hip/lib/libamdhip64.so" ) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -x hip -fgpu-rdc --hip-link -std=c++14 -g") set(CMAKE_CXX_COMPILER "hipcc") set(CMAKE_HIP_FLAFS "${CMAKE_HIP_FLAGS} --hip-link") set(CMAKE_HIP_LINKER_WRAPPER_FLAG "--hip-link") set(CMAKE_CXX_LINK_FLAGS " -fgpu-rdc --hip-link -std=c++14 ") set(HIP_HIPCC_CMAKE_LINKER_HELPER "hipcc") set(HIP_CLANG_PATH " ") set(HIP_CLANG_PARALLEL_BUILD_LINK_OPTIONS " ") add_library(${MY_TARGET_NAME} ${MY_SOURCE_FILES}) target_link_libraries(${MY_TARGET_NAME} ${HIP_TARGET_LINK_LIB} ) add_library(fcodef90 STATIC ${raw_sources_list_f90}) target_link_libraries(fcodef90 hipcode)
问题分析与解决方案
当前CMakeLists.txt存在以下问题:
- 未包含
main.f90文件,缺少主程序入口 - 链接逻辑混乱,未按照Makefile的方式用
hipcc作为最终链接器,且未正确关联Fortran编译的目标文件与HIP库 - 存在大量冗余、错误的编译/链接参数设置(比如拼写错误的
CMAKE_HIP_FLAFS)
修改后的CMakeLists.txt如下,完全对齐Makefile的编译逻辑:
cmake_minimum_required(VERSION 3.15) project(test LANGUAGES Fortran CXX) # 设置编译器 set(CMAKE_Fortran_COMPILER gfortran) set(CMAKE_CXX_COMPILER hipcc) # 源文件列表 set(FORTRAN_SOURCES main.f90 fcode.f90) set(HIP_SOURCES hipcode.cpp) # 编译Fortran源文件为目标文件 add_library(fortran_objs STATIC ${FORTRAN_SOURCES}) # 编译HIP源文件为目标文件 add_library(hip_objs STATIC ${HIP_SOURCES}) # 最终可执行文件:用hipcc链接所有目标文件,并链接gfortran库 add_executable(test $<TARGET_OBJECTS:fortran_objs> $<TARGET_OBJECTS:hip_objs>) # 链接gfortran库,确保Fortran运行时可用 target_link_libraries(test PRIVATE gfortran) # 设置HIP编译选项(根据你的GPU架构调整--offload-arch) target_compile_options(hip_objs PRIVATE --offload-arch=gfx906)
修改说明
- 明确指定编译器:
gfortran编译Fortran文件,hipcc编译HIP/C++文件 - 将Fortran和HIP源文件分别编译为静态库的目标文件,便于后续链接
- 用
hipcc作为最终链接器,这是解决Fortran调用HIP函数链接问题的关键(和Makefile逻辑一致) - 显式链接
gfortran库,保证Fortran运行时依赖被正确引入 - 精简了不必要的参数设置,只保留GPU架构相关的编译选项
编译命令保持不变:
CXX=hipcc cmake .. && make -j
内容的提问来源于stack exchange,提问作者AoShen
相关产品推荐
相关产品推荐

