如何在我自己的应用程序中设置 configure.ac (autoconf) 以自动发现 LAPACK、ATLAS、OpenBLAS 和 KMP?

How do you set configure.ac (autoconf) in my own application to auto-discover LAPACK, ATLAS, OpenBLAS, and KMP?

我是 autoconf 和线性代数库的新手。据我所知,LAPACK、ATLAS、OpenBLAS 和 KML 可以在文件系统中共存,但您只能在 link 时间使用其中一个库,我想让 ./configure 选择任何内容可用或让用户 select 使用 ./configure --something.

不同的发行版将东西放在不同的目录中,如果 autoconf 能够解决这个问题就太好了。

问题:

感谢您的帮助!

PSFEX 包执行此操作,请参阅 https://github.com/astromatic/psfex/blob/master/configure.ac#L285 :

# Provide special options for INTEL MKL and force the use of icc
AC_MSG_CHECKING([whether INTEL's MKL is enabled])
AC_ARG_ENABLE(mkl,
    [AS_HELP_STRING([--enable-mkl],
    [Use INTEL's MKL for solvers and FFTs (default = no)])],
        enable_icc="yes"
        CC="icc"
    AC_MSG_RESULT([yes]),
    AC_MSG_RESULT([no]))
    
# Provide special options for ATLAS
AC_ARG_WITH(atlas-libdir,
    [AS_HELP_STRING([--with-atlas-libdir=<ATLAS library path>],
    [Provide an alternative path to the ATLAS library])])
AC_ARG_WITH(atlas-incdir,
    [AS_HELP_STRING([--with-atlas-incdir=<ATLAS header dir>],
    [Provide an alternative path to the ATLAS header directory])])
    
# Provide special options for OpenBLAS
AC_MSG_CHECKING([whether OpenBLAS is enabled])
AC_ARG_ENABLE(openblas,
    [AS_HELP_STRING([--enable-openblas],
    [Use the OpenBLAS library instead of ATLAS (default = no)])],
    AC_MSG_RESULT([yes]),
    AC_MSG_RESULT([no]))
AC_ARG_WITH(openblas-libdir,
    [AS_HELP_STRING([--with-openblas-libdir=<OpenBLAS library path>],
    [Provide an alternative path to the OpenBLAS library])])
AC_ARG_WITH(openblas-incdir,
    [AS_HELP_STRING([--with-openblas-incdir=<OpenBLAS header dir>],
    [Provide an alternative path to the OpenBLAS header directory])])


############ handle the INTEL MKL library (FFTW + LAPACKe) ###########
if test "$enable_mkl" = "yes"; then
  convlibs="${srcdir}/../src/wcs/libwcs_c.a,${srcdir}/../src/levmar/liblevmar.a"
  ACX_MKL($with_mkl_dir,no,$enable_best_link,$convlibs)
  AC_MSG_CHECKING([for the INTEL MKL])
  if test "$MKL_WARN" == ""; then
    AC_MSG_RESULT([yes])
  else
    AC_MSG_RESULT([no])
    AC_MSG_WARN([$MKL_WARN])
  fi
  AM_CFLAGS="$AM_CFLAGS $MKL_CFLAGS "
  AM_LDFLAGS="$AM_LDFLAGS $MKL_LDFLAGS "
  LIBS="$LIBS $MKL_LIBS"

############ Select either openblas or atlas ############
else    
  if test "x$enable_openblas" = "xyes"; then
    ######## Handle the OpenBLAS library (linear algebra: BLAS + LAPACKe) ########
    ACX_OPENBLAS($with_openblas_libdir, $with_openblas_incdir, $use_pthreads, no,
      [
        AM_CFLAGS="$AM_CFLAGS $OPENBLAS_CFLAGS "
        AM_LDFLAGS="$AM_LDFLAGS $OPENBLAS_LDFLAGS "
        LIBS="$OPENBLAS_LIBS $LIBS"
        if test "$OPENBLAS_WARN" != ""; then
          AC_MSG_WARN([$OPENBLAS_WARN])
        fi
      ],
      AC_MSG_ERROR([$OPENBLAS_ERROR Exiting.])
    )

  else
    ######### handle the ATLAS library (linear algebra: BLAS + cLAPACK) ##########
    ACX_ATLAS($with_atlas_libdir, $with_atlas_incdir, $use_pthreads,
      [
        [LIBS="$ATLAS_LIBS $LIBS"]
        if test "$ATLAS_WARN" != ""; then
      AC_MSG_WARN([$ATLAS_WARN])
    fi
      ],
      AC_MSG_ERROR([$ATLAS_ERROR Exiting. You could try --enable-openblas if Atlas is unavailable.])
    )
  fi
fi

AC_ARG_WITH([lapack],
  [AS_HELP_STRING([--without-lapack],
  [disable support for lapack])],
  [],
  [with_lapack=no])

LIBLAPACK=
  AS_IF([test "x$with_lapack" != xno],
  [
    AX_BLAS([], [AC_MSG_ERROR([BLAS library not found])])
    AX_LAPACK([], [AC_MSG_ERROR([LAPACK library not found])])

    LIBS="$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS"
    AC_CHECK_LIB(
    [lapack], [zgetrf], 
    [AC_SUBST([LIBLAPACK], ["$LAPACK_LIBS $BLAS_LIBS $LIBS $FLIBS"]) AC_DEFINE([LAPACK], [1], [Define if you have liblapack])],
    [AC_MSG_FAILURE([lapack library test failed (--without-lapack to disable)])],
    [])
  ])

另请注意,您将需要他们的宏库 (available here),它们太大而无法粘贴到答案中:

  • acx_mkl.m4
  • acx_atlas.m4
  • acx_openblas.m4

您可以使用dlopen()动态加载您需要的库函数。那么您不必担心 configure.ac 设置,因为您的应用程序会在运行时自动检测可用的库。

zgetrf()zgetrs() 调用的 xnec2c antenna simulator does this using their mathlib.c and mathlib.h 实现。它也可以扩展以支持其他线性代数调用。也许有人会写一个统一的线性代数元库来动态支持一个前端库中的所有各种实现! (如果你这样做,一定要告诉 xnec2c 维护者,这样他们可能会使用你的更改。)

mathlib.c 文件包含一个 typedef 结构 mathlib_t,它定义了每个库的库名称、共享对象路径和函数前缀。它支持在运行时自动检测 Ubuntu/Debian、CentOS/RHEL 和 openSUSE 的共享对象库名称;其他发行版或多或少使用相同的库名称,因此,实际上,支持的不仅仅是上面列出的发行版:

static mathlib_t mathlibs[] = {
    {.type = MATHLIB_ATLAS, .lib = "libtatlas.so.3", .name = "ATLAS, Threaded", .f_prefix = "clapack_"},
    {.type = MATHLIB_OPENBLAS, .lib = "libopenblaso.so", .name = "OpenBLAS+LAPACKe, OpenMP", .f_prefix = "LAPACKE_"},
}

请注意,ATLAS 和 OpenBLAS 使用不同的函数前缀:clapack_ vs LAPACKE_;所以对不同的库进行包装是很有用的。 Xnec2c支持ATLAS、OpenBLAS+LAPACK、Intel MKL