You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:11:07