如何配置autoconf的configure.ac自动发现LAPACK等线性代数库并支持用户选择
Autoconf适配线性代数库方案解答
1. 现有可用AC宏说明
没有官方内置的专门适配LAPACK/ATLAS/OpenBLAS的标准AC宏,但是通用第三方宏库中有成熟的AX_BLAS、AX_LAPACK系列宏可以直接实现多BLAS/LAPACK库的检测、优先级选择逻辑,如果你不想引入第三方宏依赖,也可以自己手写轻量检测逻辑,代码量不大。
2. 自动查找库且默认优先线程版ATLAS的配置方法
核心逻辑是按你需要的优先级顺序逐个检测库的可用性,检测前先加入不同发行版常见的库搜索路径,检测通过就停止后续检测。
配置代码示例:
# 先保存原始的LDFLAGS和LIBS OLD_LDFLAGS="$LDFLAGS" OLD_LIBS="$LIBS" # 加入常见的ATLAS/OpenBLAS搜索路径,适配不同发行版 LDFLAGS="$LDFLAGS -L/usr/lib64/atlas -L/usr/lib/atlas -L/usr/lib64/openblas -L/usr/lib/openblas" # 优先级1:检测线程版ATLAS AC_CHECK_LIB([tatlas], [dgemm_], [ BLAS_LIBS="-ltatlas" LAPACK_LIBS="-ltatlas" found_blas=yes ], [], [-lm]) # 优先级2:检测串行版ATLAS if test "x$found_blas" != "xyes"; then AC_CHECK_LIB([satlas], [dgemm_], [ BLAS_LIBS="-lsatlas" LAPACK_LIBS="-lsatlas" found_blas=yes ], [], [-lm]) fi # 优先级3:检测OpenBLAS pthread版 if test "x$found_blas" != "xyes"; then AC_CHECK_LIB([openblasp], [dgemm_], [ BLAS_LIBS="-lopenblasp" LAPACK_LIBS="-lopenblasp" found_blas=yes ], [], [-lm]) fi # 优先级4:检测OpenBLAS串行版 if test "x$found_blas" != "xyes"; then AC_CHECK_LIB([openblas], [dgemm_], [ BLAS_LIBS="-lopenblas" LAPACK_LIBS="-lopenblas" found_blas=yes ], [], [-lm]) fi # 优先级5:检测原生LAPACK if test "x$found_blas" != "xyes"; then AC_CHECK_LIB([lapack], [dgemm_], [ BLAS_LIBS="-llapack" LAPACK_LIBS="-llapack" found_blas=yes ], [], [-lblas -lm]) fi # 恢复原始编译参数 LDFLAGS="$OLD_LDFLAGS" LIBS="$OLD_LIBS" # 没找到任何库就报错 if test "x$found_blas" != "xyes"; then AC_MSG_ERROR([No valid BLAS/LAPACK library found, please install LAPACK/ATLAS/OpenBLAS first]) fi # 导出变量给Makefile使用 AC_SUBST(BLAS_LIBS) AC_SUBST(LAPACK_LIBS)
3. 支持用户手动指定库版本的配置方法
不需要单独为每个版本加--with-*参数,更优雅的方案是统一提供--with-blas参数,接受不同的库类型值,用户也可以直接传入自定义的链接参数。如果需要单独的OpenMP版本开关也可以额外添加,以下是通用实现代码:
# 定义--with-blas参数 AC_ARG_WITH([blas], [AS_HELP_STRING([--with-blas=LIB], [Specify BLAS/LAPACK library to use, available values: atlas-thread, atlas-serial, openblas-pthread, openblas-openmp, openblas, lapack, or custom linker flags])], [with_blas="$withval"], [with_blas=auto]) # 如果用户指定了库,按用户指定的检测,不fallback if test "x$with_blas" != "xauto"; then OLD_LDFLAGS="$LDFLAGS" OLD_LIBS="$LIBS" LDFLAGS="$LDFLAGS -L/usr/lib64/atlas -L/usr/lib/atlas -L/usr/lib64/openblas -L/usr/lib/openblas" found_blas=no case "$with_blas" in atlas-thread) AC_CHECK_LIB([tatlas], [dgemm_], [ BLAS_LIBS="-ltatlas" LAPACK_LIBS="-ltatlas" found_blas=yes ], [], [-lm]) ;; atlas-serial) AC_CHECK_LIB([satlas], [dgemm_], [ BLAS_LIBS="-lsatlas" LAPACK_LIBS="-lsatlas" found_blas=yes ], [], [-lm]) ;; openblas-pthread) AC_CHECK_LIB([openblasp], [dgemm_], [ BLAS_LIBS="-lopenblasp" LAPACK_LIBS="-lopenblasp" found_blas=yes ], [], [-lm]) ;; openblas-openmp) AC_CHECK_LIB([openblaso], [dgemm_], [ BLAS_LIBS="-lopenblaso" LAPACK_LIBS="-lopenblaso" # 同步添加OpenMP编译参数 CFLAGS="$CFLAGS -fopenmp" CXXFLAGS="$CXXFLAGS -fopenmp" found_blas=yes ], [], [-lm -fopenmp]) ;; openblas) AC_CHECK_LIB([openblas], [dgemm_], [ BLAS_LIBS="-lopenblas" LAPACK_LIBS="-lopenblas" found_blas=yes ], [], [-lm]) ;; lapack) AC_CHECK_LIB([lapack], [dgemm_], [ BLAS_LIBS="-llapack" LAPACK_LIBS="-llapack" found_blas=yes ], [], [-lblas -lm]) ;; *) # 支持用户直接传入自定义链接参数 BLAS_LIBS="$with_blas" LAPACK_LIBS="$with_blas" found_blas=yes ;; esac LDFLAGS="$OLD_LDFLAGS" LIBS="$OLD_LIBS" if test "x$found_blas" != "xyes"; then AC_MSG_ERROR([Specified BLAS library $with_blas not available, please check your installation]) fi else # 此处放入第二部分的自动检测逻辑即可 fi
如果要单独加--with-openblas-openmp开关也可以,在参数定义部分补充如下代码即可,用户执行./configure --with-openblas-openmp就会直接选择OpenBLAS的OpenMP版本:
AC_ARG_WITH([openblas-openmp], [AS_HELP_STRING([--with-openblas-openmp], [Use OpenMP version of OpenBLAS])], [with_blas=openblas-openmp])
内容的提问来源于stack exchange,提问作者KJ7LNW
相关产品推荐
相关产品推荐

