CMake C项目中无法链接预构建LAPACKE库的问题
CMake管理的C项目链接LAPACKE时出现链接器错误
项目背景
我要通过CI构建一个CMake管理的C项目,项目会通过CBLAS和LAPACKE大量调用Fortran实现的BLAS和LAPACK。采用的方式是:在单独的CI任务中构建LAPACK包,生成的静态库(Linux下的.a文件)和头文件放在项目的<PROJECT_ROOT>/deps/lapack-3.12.0/build/目录下,包含lib和include子目录;另一个CI任务负责编译C项目并链接这些预构建产物。之前用add_subdirectory()链接纯Fortran可执行文件时一切正常,但对CBLAS和LAPACKE不太熟悉。
当前CMakeLists.txt配置
cmake_minimum_required(VERSION 3.20) project(collision-detection C Fortran ) #include_directories(${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/include) #link_directories(${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib) message("${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib") add_executable(helloworld_lapacke src/helloworld_lapacke.c) target_include_directories(helloworld_lapacke PRIVATE ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/include/) target_link_directories(helloworld_lapacke PRIVATE ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib/) target_link_libraries(helloworld_lapacke PRIVATE blas cblas lapack lapacke )
链接器错误信息
myproject/deps/lapack-3.12.0/build/lib/liblapacke.a(lapacke_dgels_work.c.o): in function `LAPACKE_dgels_work': lapacke_dgels_work.c:(.text+0x1c3): undefined reference to `dgels_' /usr/bin/ld: lapacke_dgels_work.c:(.text+0x2ee): undefined reference to `dgels_' collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/helloworld_lapacke.dir/build.make:97: helloworld_lapacke] Error 1 make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/helloworld_lapacke.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
测试用C代码
#include <stdio.h> #include <lapacke.h> int main(int argc, const char *argv[]) { double a[5][3] = {1, 1, 1, 2, 3, 4, 3, 5, 2, 4, 2, 5, 5, 4, 3}; double b[5][2] = {-10, -3, 12, 14, 14, 12, 16, 16, 18, 16}; lapack_int info, m, n, lda, ldb, nrhs; int i, j; m = 5; n = 3; nrhs = 2; lda = 3; ldb = 2; info = LAPACKE_dgels(LAPACK_ROW_MAJOR, 'N', m, n, nrhs, *a, lda, *b, ldb); for (i = 0; i < n; i++) { for (j = 0; j < nrhs; j++) { printf("%lf ", b[i][j]); } printf("\n"); } return (info); }
解决方案
1. 调整链接库顺序
链接器按顺序处理库,依赖其他库的库要放在被依赖库的前面。LAPACKE依赖LAPACK,LAPACK又依赖BLAS,调整后的链接顺序如下:
target_link_libraries(helloworld_lapacke PRIVATE lapacke lapack cblas blas )
2. 显式链接Fortran运行时库
由于LAPACK/BLAS是Fortran实现,C项目链接时需确保Fortran运行时库被包含。可添加以下配置:
find_package(Fortran REQUIRED) target_link_libraries(helloworld_lapacke PRIVATE ${Fortran_LIBRARIES})
3. 验证预构建LAPACK库的完整性
检查静态库中是否包含dgels_符号,确认CI构建的LAPACK库完整:
nm myproject/deps/lapack-3.12.0/build/lib/liblapack.a | grep dgels_
若没有输出,说明LAPACK构建不完整,需检查CI构建脚本,确保启用所有必要组件。
4. 使用更可靠的库查找方式(可选)
替代直接指定target_link_directories,用find_library定位库,让CMake更准确处理依赖:
find_library(LAPACKE_LIB lapacke PATHS ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib NO_DEFAULT_PATH) find_library(LAPACK_LIB lapack PATHS ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib NO_DEFAULT_PATH) find_library(CBLAS_LIB cblas PATHS ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib NO_DEFAULT_PATH) find_library(BLAS_LIB blas PATHS ${CMAKE_SOURCE_DIR}/deps/lapack-3.12.0/build/lib NO_DEFAULT_PATH) target_link_libraries(helloworld_lapacke PRIVATE ${LAPACKE_LIB} ${LAPACK_LIB} ${CBLAS_LIB} ${BLAS_LIB} ${Fortran_LIBRARIES} )
内容的提问来源于stack exchange,提问作者rbaleksandar
相关产品推荐
相关产品推荐

