如何动态查找和包含库
How to dynamically find and include libraries
我有一个库,我正在开发用于使用 Autotools 套件的配置和 makefile。该库在正在编译的系统上需要一个外部库(特别是 fftw3),我希望 Autoconf/Automake 自动查找和 link/include 外部库 before/when 编译(在 configure.ac 或 Makefile.am).
我目前只是使用 autoconf “--with-” 标志来为用户提供库文件和外部库的 include 文件夹在他们系统上的位置,但这对于用户。我正在为其构建配置文件和 makefile 的库将部署在各种共享系统上,因此很难假设必要的外部库将始终位于同一位置。
解决这个问题的最佳方法是什么?
你可能想多了。库可能安装在不同系统的不同位置本身并不是问题。开发工具链了解使用它们的系统的布局。基本案例相当稳健;只是(例如)...
AC_CHECK_LIB([fftw3], [fftw_plan_dft])
这将识别 libfftw3
在搜索路径中可用(如果确实如此),并且在这种情况下会将适当的 link 选项添加到 LIBS
变量并定义 HAVE_LIBFFTW3
.
仅当您要提供不在 link 用户默认搜索路径中的库,或者在该路径的较早位置找到不同版本的库时,才会出现问题。 这就是 提供 --with-foo
选项的情况,构建器可以通过这些选项指定位置。但请注意,这是一个有点特殊的问题,至少在 linking 针对动态库时,因为开发库通常与 运行time 库一起安装,并且如果静态库找不到开发库linker 在构建时,那么通常您需要某种特殊规定,以便动态 linker 在 运行 时间找到 运行time 库。
不过,如果您想检查编码为 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])
该代码的显着特征包括
- 保存和恢复配置在 运行ning 测试(
LDFLAGS
)和报告结果(LIBS
)中使用的变量
- 使用 shell 循环来测试各种选项
- 使用
AC_CHECK_LIB
的成功/错误操作
- 了解
AC_CHECK_LIB
是一个 宏 ,而不是一个函数,因此,例如,您可以将 break
放入其参数中以退出使用 AC_CHECK_LIB
的循环
- 使用输出变量将结果报告为一组 link 选项。您可以通过将
$(FFTW3_LIBS)
添加到适当的 *LIBADD
或 *LDADD
变量来在 Makefile.am
中使用它。 (或者,如果您不使用 Automake,则以任何合适的方式将其添加到 link 命令。)
当然,您可以将其与使用 --with-foo
选项相结合,以支持您没有预料到的情况(留作练习)。
由于 fftw3
似乎要安装 *.pc
文件,我会在 configure.ac
中使用基于 pkg-config
的宏,类似于
PKG_CHECK_MODULES([FFTW3], [fftw3])
或者,如果您想为编译您的库的人提供更多帮助,例如
PKG_CHECK_MODULES([FFTW3], [fftw3], [],
[AC_MSG_ERROR([fftw3 devel package not found])])
当然,这需要在autoreconf
和configure
时安装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
.
更可取
我有一个库,我正在开发用于使用 Autotools 套件的配置和 makefile。该库在正在编译的系统上需要一个外部库(特别是 fftw3),我希望 Autoconf/Automake 自动查找和 link/include 外部库 before/when 编译(在 configure.ac 或 Makefile.am).
我目前只是使用 autoconf “--with-” 标志来为用户提供库文件和外部库的 include 文件夹在他们系统上的位置,但这对于用户。我正在为其构建配置文件和 makefile 的库将部署在各种共享系统上,因此很难假设必要的外部库将始终位于同一位置。
解决这个问题的最佳方法是什么?
你可能想多了。库可能安装在不同系统的不同位置本身并不是问题。开发工具链了解使用它们的系统的布局。基本案例相当稳健;只是(例如)...
AC_CHECK_LIB([fftw3], [fftw_plan_dft])
这将识别 libfftw3
在搜索路径中可用(如果确实如此),并且在这种情况下会将适当的 link 选项添加到 LIBS
变量并定义 HAVE_LIBFFTW3
.
仅当您要提供不在 link 用户默认搜索路径中的库,或者在该路径的较早位置找到不同版本的库时,才会出现问题。 这就是 提供 --with-foo
选项的情况,构建器可以通过这些选项指定位置。但请注意,这是一个有点特殊的问题,至少在 linking 针对动态库时,因为开发库通常与 运行time 库一起安装,并且如果静态库找不到开发库linker 在构建时,那么通常您需要某种特殊规定,以便动态 linker 在 运行 时间找到 运行time 库。
不过,如果您想检查编码为 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])
该代码的显着特征包括
- 保存和恢复配置在 运行ning 测试(
LDFLAGS
)和报告结果(LIBS
)中使用的变量 - 使用 shell 循环来测试各种选项
- 使用
AC_CHECK_LIB
的成功/错误操作- 了解
AC_CHECK_LIB
是一个 宏 ,而不是一个函数,因此,例如,您可以将break
放入其参数中以退出使用AC_CHECK_LIB
的循环
- 了解
- 使用输出变量将结果报告为一组 link 选项。您可以通过将
$(FFTW3_LIBS)
添加到适当的*LIBADD
或*LDADD
变量来在Makefile.am
中使用它。 (或者,如果您不使用 Automake,则以任何合适的方式将其添加到 link 命令。)
当然,您可以将其与使用 --with-foo
选项相结合,以支持您没有预料到的情况(留作练习)。
由于 fftw3
似乎要安装 *.pc
文件,我会在 configure.ac
中使用基于 pkg-config
的宏,类似于
PKG_CHECK_MODULES([FFTW3], [fftw3])
或者,如果您想为编译您的库的人提供更多帮助,例如
PKG_CHECK_MODULES([FFTW3], [fftw3], [],
[AC_MSG_ERROR([fftw3 devel package not found])])
当然,这需要在autoreconf
和configure
时安装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
.