【问题标题】:How to dynamically find and include libraries如何动态查找和包含库
【发布时间】:2019-09-18 14:37:44
【问题描述】:

我有一个库,我正在开发用于使用 Autotools 套件的配置和生成文件。该库需要正在编译的系统上的外部库(特别是 fftw3),我希望 Autoconf/Automake 在编译之前/编译时自动查找和链接/包含外部库(在 configure.ac 或 Makefile.am 中)。

我目前只是为用户使用 autoconf "--with-" 标志来提供库文件和系统上外部库的包含文件夹的位置,但这对用户来说似乎很麻烦.我正在为其构建配置文件和 makefile 的库将部署在各种共享系统上,因此很难假设必要的外部库总是在同一个地方。

解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: c++ linker autotools autoconf automake


    【解决方案1】:

    你可能想多了。库可能安装在不同系统的不同位置本身并不是问题。开发工具链了解使用它们的系统的布局。基本情况相当稳健;只是(例如)...

    AC_CHECK_LIB([fftw3], [fftw_plan_dft])
    

    这将识别出libfftw3 在搜索路径中确实可用,并且在这种情况下,会将适当的链接选项添加到LIBS 变量并定义HAVE_LIBFFTW3

    只有当您想要使用不在链接器默认搜索路径中的库,或者在该路径的较早位置找到不同版本的库时,才会出现问题。 这是提供--with-foo 选项的情况,构建器可以通过该选项指定位置。但请注意,这是一个有点特殊的问题,至少在链接动态库时是这样,因为开发库通常与运行时库一起安装,如果在构建时静态链接器找不到开发库,那么通常你需要一些动态链接器在运行时找到运行时库的一种特殊规定。

    不过,如果您想检查编码为configure 的可能库位置列表,则可以相对轻松地完成。生成的configure 是一个shell 脚本,你可以将它的文字代码写入你的configure.ac 而不会有太多麻烦。例如,

    # Preserve the original value of LIBS
    LIBS_save=$LIBS
    
    # This is how we will report out the result
    FFTW3_LIBS=
    
    # Check the default locations first
    AC_CHECK_LIB([fftw3], [fftw_plan_dft], [
      # libfftw3 found in the library search path
      FFTW3_LIBS=-lfftw3
    ], [
      # libfftw3 not found in the library search path; try some other paths
      # make the linker search the chosen path by adding an `-L` option to the LDFLAGS
      LDFLAGS_save=$LDFLAGS
      for fftw_libdir in
          /usr/lib/fftw
          /usr/lib/fftw3
          /usr/local/lib/fftw3
      do
        LDFLAGS="${LDFLAGS_save} -L${fftw_libdir}"
        AC_CHECK_LIB([fftw3], [fftw_plan_dft], [
          # library found
          FFTW3_LIBS="-L${fftw_libdir} -lfftw3"
          break
        ])
      done
    
      # restore the original LDFLAGS
      LDFLAGS=$LDFLAGS_save
    ])
    
    # restore the original LIBS
    LIBS=$LIBS_save
    
    AS_IF([test x = "x${FFTW3_LIBS}"], [
      # configure fails if it does not find libfftw3
      AC_MSG_ERROR([libfftw3 not found])
    ])
    
    # Make FFTW3_LIBS an output variable
    AC_OUTPUT([FFTW3_LIBS])
    

    该代码的显着特征包括

    • 保存和恢复 configure 在运行测试 (LDFLAGS) 和报告结果 (LIBS) 中使用的变量
    • 使用 shell 循环测试各种选项
    • 使用AC_CHECK_LIB的成功/错误操作
      • 了解AC_CHECK_LIB 是一个,而不是一个函数,因此,例如,您可以将break 放入其参数中,这将退出使用AC_CHECK_LIB 的循环
    • 使用输出变量将结果报告为一组链接选项。您可以通过将$(FFTW3_LIBS) 添加到适当的*LIBADD*LDADD 变量中来在Makefile.am 中使用它。 (或者,如果您不使用 Automake,则以任何合适的方式将其添加到链接命令中。)

    当然,您可以将其与使用 --with-foo 选项结合起来,以支持您未预料到的案例(留作练习)。

    【讨论】:

      【解决方案2】:

      由于fftw3 似乎安装了*.pc 文件,我将在configure.ac 中使用基于pkg-config 的宏,类似于

      PKG_CHECK_MODULES([FFTW3], [fftw3])
      

      或者,如果您想对编译您的库的人提供更多帮助,例如

      PKG_CHECK_MODULES([FFTW3], [fftw3], [],
                        [AC_MSG_ERROR([fftw3 devel package not found])])
      

      当然,这需要在autoreconfconfigure 时间安装pkg-config

      如果有人碰巧在不寻常的地方安装了fftw3,可以将*.pc文件的安装目录添加到PKG_CONFIG_PATH环境变量中。

      在定义libfoo 库的Makefile.am 文件中,您可以添加类似的行

      libfoo_CFLAGS += $(FFTW3_CFLAGS)
      libfoo_LIBADD += $(FFTW3_LIBS)
      

      如果您想及早发现那些试图在您的源代码上运行autoreconf 而没有安装pkg-config 的人,您可以在configure.ac 中添加一行以确保定义了PKG_CHECK_MODULES autoconf m4 宏:

      m4_pattern_forbid([PKG_CHECK_MODULES])dnl
      

      不过,这在野外很少见。

      相对于内置的AC_CHECK_LIB & Co 宏的优势在于*.pc 文件可以定义更多信息。例如

      [user@host ~]$ pkg-config --libs fftw3
      -lfftw3 
      

      没有惊喜,但是

      [user@host ~]$ pkg-config --libs fftw3q
      -lfftw3q -lquadmath 
      

      可能包含令人惊讶的附加标志。分发包也可能在那里添加了系统特定信息。

      恕我直言,当依赖项发送 *.pc 文件时,使用 PKG_CHECK_MDOULE 比使用 AC_CHECK_LIB 更可取。

      【讨论】:

        猜你喜欢
        • 2019-05-23
        • 1970-01-01
        • 2011-04-14
        • 2019-05-07
        • 2021-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多