Autoconf:链接器错误链接到自定义库
Posted
技术标签:
【中文标题】Autoconf:链接器错误链接到自定义库【英文标题】:Autoconf: linker error linking against custom library 【发布时间】:2012-02-24 16:37:49 【问题描述】:1) 我有一个项目包含一个链接到一些外部库(即gcrypt
、gpg-error
、z
和ssh2
)的共享库。让我们称之为“mylib”。
这个库构建完美,我可以看到libtool
正确链接了依赖项。
libtool: link: ppc-linux-gcc -shared -fPIC -DPIC .libs/mylib1.o .libs/mylib2.o .libs/mylib3.o
-Wl,-rpath -Wl,/opt/ELDK/ppc_8xx/lib -Wl,-rpath \
-Wl,/opt/ELDK/ppc_8xx/lib /opt/ELDK/ppc_8xx/lib/libssh2.so \
-L/opt/ELDK/ppc_8xx/lib -lz /opt/ELDK/ppc_8xx/lib/libgcrypt.so \
/opt/ELDK/ppc_8xx/lib/libgpg-error.so -lpthread -O2 \
-Wl,-soname -Wl,mylib.so.0 -o .libs/mylib.so.0.0.0
2) 同一个项目有几个链接到“mylib”的程序。 但是,当我尝试链接它们时,我收到了关于相同先前库的链接器错误:
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
warning: libssh2.so.1, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
warning: libz.so.1, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
warning: libgcrypt.so.11, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
/opt/ELDK-3.1/usr/bin/../lib/gcc-lib/ppc-linux/3.3.3/../../../../ppc-linux/bin/ld: \
warning: libgpg-error.so.0, needed by ./../myLib/.libs/mylib.so, not found (try using -rpath or -rpath-link)
./../myLib/.libs/mylib.so: undefined reference to `libssh2_channel_process_startup'
./../myLib/.libs/mylib.so: undefined reference to `libssh2_scp_send_ex'
在“mylib”configure.ac
我明确搜索库:
AC_SEARCH_LIBS(gpg_err_set_errno,[gpg-error])
AC_SEARCH_LIBS(gcry_check_version,[gcrypt])
AC_SEARCH_LIBS(deflate,[z])
AC_SEARCH_LIBS(libssh2_init,[ssh2])
我还必须使用“mylib”在每个项目中明确包含所有这些库吗? 当我第一次在“mylib”中链接它们时,它不应该已经解决了吗?
有没有更好的方法来做到这一点?
谢谢。
P.S.:我在autoconf
这件事上不是很聪明,对不起。
注意:我正在使用(还很旧的)ELDK 3.1 为 PowerPC 进行交叉编译。
【问题讨论】:
您是否覆盖了 Makefile.am 中程序的任何指令? 我有类似program1_CPPFLAGS = -I$(top_srcdir) $(MYLIB_CFLAGS)
的东西,其中MYLIB_CFLAGS
和MYLIB_LIBS
在“program1”的configure.ac
中定义为AC_ARG_WITH
,以允许我链接到本地“mylib”而不是一个系统安装了一个(请告诉我这是否是一种更好的方法)。
CPPFLAGS 应该不相关,但是如何在 Makefile.am 中使用 MYLIB_LIBS?在您的最终 Makefile 中,应该有一个包含 $(LINK) 命令的 program1$(EXEEXT) 的目标,并且该命令应该有 $(LIBS),如果 AC_SEARCH_LIBS 成功找到给定的库,则它应该包含库。
在 mylib.so 上运行 ldd 的输出会很有用,尽管我不确定在交叉编译时这样做有多容易。同样有趣的是检查 readelf -a
以确保 RPATH 确实按照您的要求添加。
【参考方案1】:
注意:由于我在 2 年后收到了答复,但这并没有解决我的问题,我认为最好与大家分享我所做的事情。
回答:
我发现在基于autoconf
的项目中自动包含链接器依赖项的更好方法是将pkg-config
信息添加到我的库中。
更改为configure.ac
:
export PKG_CONFIG_PATH=../MyLibPath:$PKG_CONFIG_PATH
PKG_CHECK_MODULES([DEPS], [libssh2 >= 1.3.0])
# Output configuration files.
AC_CONFIG_FILES([Makefile libMyLib-1.0.pc libMyLib-1.0-uninstalled.pc])
第二个输出文件libMyLib-1.0-uninstalled.pc
是为了让我可以继续使用卸载版本的 MyLib 开发我的项目。
更改为Makefile.am
:
libMyLib_la_CPPFLAGS = $(DEPS_CPPFLAGS)
libMyLib_la_CFLAGS = $(DEPS_CFLAGS)
libMyLib_la_CXXFLAGS = $(DEPS_CXXFLAGS)
libMyLib_la_LIBADD = $(DEPS_LIBS)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libMyLib-1.0.pc
添加到项目libMyLib-1.0.pc
:
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: MyLib
Description: My library.
Requires: libssh2
Requires.private:
Version: @PACKAGE_VERSION@
Libs: -L$libdir -lMyLib -lstdc++ -lm -lslog -lpthread
Libs.private:
Cflags: -I$includedir/libMyLib-1.0
和libMyLib-1.0-uninstalled.pc
:
prefix=@abs_builddir@
exec_prefix=@exec_prefix@
libdir=$prefix/.libs
includedir=$prefix
Name: MyLib
Description: My library.
Requires: libssh2
Requires.private:
Version: @PACKAGE_VERSION@
Libs: -Wl,-rpath-link,$libdir -L$libdir -lMyLib -lstdc++ -lm -lslog -lpthread
Libs.private:
Cflags: -I$includedir/
在每个依赖项目中:
configure.ac
:
export PKG_CONFIG_PATH=../MyLibPath:$PKG_CONFIG_PATH
PKG_CHECK_MODULES([MYLIB], [libMyLib-1.0 >= 1.0.0])
Makefile.am
:
dependent_CPPFLAGS = $(MYLIB_CPPFLAGS)
dependent_CFLAGS = $(MYLIB_CFLAGS)
dependent_CXXFLAGS = $(MYLIB_CXXFLAGS)
dependent_LIBADD = $(MYLIB_LIBS)
【讨论】:
除非libslog
或标准库也位于不同的路径中,否则您不需要在 Libs 条目中使用 -rpath-link
。
是的,它位于 uninstalled
配置文件中的不同路径中。谢谢!【参考方案2】:
如果不知道 Makefile.am
或 configure.ac
中的内容,就很难准确判断您在做什么,但由于我看到您使用的是 -Wl,-rpath
,因此我假设您将其传递为 LDFLAGS
当您拨打 ./configure
时,从外部。
发生的情况是libtool
通常不会存储-rpath
值,但它会存储-L
;所以我通常的建议是同时传递-L
和-rpath
,这样.la
文件将包含找到要链接到它的库的路径。
虽然您不必在每个二进制文件上都传递它,但 libtool
会,然后让链接编辑器正确解析它。
【讨论】:
非常感谢您回答 Diego。最后我把pkgconfig
玩了,它解决了我的问题。现在我不必为每个依赖项重复链接库。不过,令人失望的是,autoconf
无法自动“级联”这种依赖关系......
您只能级联共享对象依赖项,但不能级联静态存档,但在这种情况下,在我看来,您似乎有一些额外的依赖项完全位于不同的路径中,这更棘手,因为它的搜索路径改变。
恼人的想法是我不得不在共享项目中不断重复依赖(共享)库。尽管MyLib
已经动态链接,但如果我省略(已在 MyLib 中链接)依赖项,最终程序/库会给出链接器错误。
这些是系统库的一部分还是在单独的路径中?链接编辑器似乎不知道在哪里寻找它们。以上是关于Autoconf:链接器错误链接到自定义库的主要内容,如果未能解决你的问题,请参考以下文章