为什么 autoconf/automake 项目会链接到已安装的库而不是本地开发库?
我正在创建一个库 libgdata
,其中包含一些测试和未安装的程序。 我遇到的问题是,一旦安装了该库一次,程序似乎就链接到已安装的版本,而不是 ../src/libgdata.la
中的本地版本。
什么可能导致这种情况? 我做错了什么可怕的事情吗?
这是我的 test/Makefile.am 的样子:
INCLUDES = -I$(top_srcdir)/src/ -I$(top_srcdir)/test/
# libapiutil contains all of our dependencies!
AM_CXXFLAGS = $(APIUTIL_CFLAGS)
AM_LDFLAGS = $(APIUTIL_LIBS)
LDADD = $(top_builddir)/src/libgdata.la
noinst_PROGRAMS = gdatacalendar gdatayoutube
gdatacalendar_SOURCES = gdatacalendar.cc
gdatayoutube_SOURCES = gdatayoutube.cc
TESTS = check_bare
check_PROGRAMS = $(TESTS)
check_bare_SOURCES = check_bare.cc
(libapiutil 是另一个库,它有一些用于处理 libcurl 和 libxml++ 的帮助程序)
所以,例如,如果我在没有安装任何东西的情况下运行测试,一切正常。 我可以在本地进行更改,这些程序会立即接受这些更改。
如果我安装该软件包,这些程序将编译(看起来它实际上确实在本地查找标头),但是一旦我运行该程序,它就会抱怨缺少符号。
据我所知,它是根据 make 输出链接到新建的库(../src/libgdata.la),所以我不确定为什么会发生这种情况。 如果我删除已安装的文件,则可以很好地拾取对 src/* 的本地更改。
我在下面包含了 gdatacalendar 的 make 输出。
g++ -DHAVE_CONFIG_H -I. -I.. -I../src/ -I../test/ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -MT gdatacalendar.o -MD -MP -MF .deps/gdatacalendar.Tpo -c -o gdatacalendar.o gdatacalendar.cc
mv -f .deps/gdatacalendar.Tpo .deps/gdatacalendar.Po
/bin/bash ../libtool --tag=CXX --mode=link g++ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -L/home/altern8/workspaces/4355/dev-install/lib -lapiutil -lcurl -lgssapi_krb5 -lxml++-2.6 -lxml2 -lglibmm-2.4 -lgobject-2.0 -lsigc-2.0 -lglib-2.0 -o gdatacalendar gdatacalendar.o ../src/libgdata.la
mkdir .libs
g++ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -o .libs/gdatacalendar gdatacalendar.o -L/home/altern8/workspaces/4355/dev-install/lib /home/altern8/workspaces/4355/dev-install/lib/libapiutil.so /usr/lib/libcurl.so -lgssapi_krb5 /usr/lib/libxml++-2.6.so /usr/lib/libxml2.so /usr/lib/libglibmm-2.4.so /usr/lib/libgobject-2.0.so /usr/lib/libsigc-2.0.so /usr/lib/libglib-2.0.so ../src/.libs/libgdata.so -Wl,--rpath -Wl,/home/altern8/workspaces/4355/dev-install/lib
creating gdatacalendar
帮助。 :)
更新
当我在安装库后将 addCommonRequestHeader()
方法添加到 Service 类后尝试运行日历程序时,我收到以下消息没有 addCommonRequestHeader()
方法。
/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:
symbol lookup error:
/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:
undefined symbol:
_ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
尤金尝试设置 $LD_LIBRARY_PATH 变量的建议没有帮助。
更新2
我做了两次测试。 首先,我在删除我的 dev-install 目录 (--prefix) 后执行此操作,在这种情况下,它会创建 test/.libs/lt-gdatacalendar
。 不过,一旦我安装了该库,它就会创建 test/.libs/gdatacalendar
。 ldd 的输出对于两者来说是相同的,但有一个例外:
# before install
# ldd test/.libs/lt-gdatacalendar
libgdata.so.0 => /home/altern8/workspaces/4355/libgdata/src/.libs/libgdata.so.0 (0xb7c32000)
# after install
# ldd test/.libs/gdatacalendar
libgdata.so.0 => /home/altern8/workspaces/4355/dev-install/lib/libgdata.so.0 (0xb7c87000)
什么会导致在一种情况下创建 lt-gdatacalendar 而在另一种情况下创建 gdatacalendar?
libgdata 上 ldd 的输出是:
altern8@goldfrapp:~/workspaces/4355/libgdata$ ldd /home/altern8/workspaces/4355/libgdata/src/.libs/libgdata.so.0
linux-gate.so.1 => (0xb7f7c000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7f3b000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dec000)
/lib/ld-linux.so.2 (0xb7f7d000)
I'm creating a library libgdata
that has some tests and non-installed programs. I am running into the problem that once I've installed the library once, the programs seem to be linking to the installed version and not the local version in ../src/libgdata.la
any longer.
What could cause this? Am I doing something horribly wrong?
Here is what my test/Makefile.am
looks like:
INCLUDES = -I$(top_srcdir)/src/ -I$(top_srcdir)/test/
# libapiutil contains all of our dependencies!
AM_CXXFLAGS = $(APIUTIL_CFLAGS)
AM_LDFLAGS = $(APIUTIL_LIBS)
LDADD = $(top_builddir)/src/libgdata.la
noinst_PROGRAMS = gdatacalendar gdatayoutube
gdatacalendar_SOURCES = gdatacalendar.cc
gdatayoutube_SOURCES = gdatayoutube.cc
TESTS = check_bare
check_PROGRAMS = $(TESTS)
check_bare_SOURCES = check_bare.cc
(libapiutil
is another library that has some helper stuff for dealing with libcurl and libxml++)
So, for instance, if I run the tests without having installed anything, everything works fine. I can make changes locally and they are picked up by these programs right away.
If I install the package, these programs will compile (it seems like it does actually look locally for the headers), but once I run the program it complains about missing symbols.
As far as I can tell, it is linking against the newly built library (../src/libgdata.la) based on the make output, so I'm not sure why this would be happening. If i remove the installed files, the local changes to src/* are picked up just fine.
I've included the make output for gdatacalendar below.
g++ -DHAVE_CONFIG_H -I. -I.. -I../src/ -I../test/ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -MT gdatacalendar.o -MD -MP -MF .deps/gdatacalendar.Tpo -c -o gdatacalendar.o gdatacalendar.cc
mv -f .deps/gdatacalendar.Tpo .deps/gdatacalendar.Po
/bin/bash ../libtool --tag=CXX --mode=link g++ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -L/home/altern8/workspaces/4355/dev-install/lib -lapiutil -lcurl -lgssapi_krb5 -lxml++-2.6 -lxml2 -lglibmm-2.4 -lgobject-2.0 -lsigc-2.0 -lglib-2.0 -o gdatacalendar gdatacalendar.o ../src/libgdata.la
mkdir .libs
g++ -I/home/altern8/workspaces/4355/dev-install/include -I/usr/include/libxml++-2.6 -I/usr/lib/libxml++-2.6/include -I/usr/include/libxml2 -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -o .libs/gdatacalendar gdatacalendar.o -L/home/altern8/workspaces/4355/dev-install/lib /home/altern8/workspaces/4355/dev-install/lib/libapiutil.so /usr/lib/libcurl.so -lgssapi_krb5 /usr/lib/libxml++-2.6.so /usr/lib/libxml2.so /usr/lib/libglibmm-2.4.so /usr/lib/libgobject-2.0.so /usr/lib/libsigc-2.0.so /usr/lib/libglib-2.0.so ../src/.libs/libgdata.so -Wl,--rpath -Wl,/home/altern8/workspaces/4355/dev-install/lib
creating gdatacalendar
Help. :)
UPDATE
I get the following messages when I try to run the calendar program when I've added the addCommonRequestHeader()
method to the Service class after I had installed the library without the addCommonRequestHeader()
method.
/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:
symbol lookup error:
/home/altern8/workspaces/4355/libgdata/test/.libs/lt-gdatacalendar:
undefined symbol:
_ZN55gdata7service7Service22addCommonRequestHeaderERKSsS4_
Eugene's suggestion to try setting the $LD_LIBRARY_PATH
variable did not help.
UPDATE 2
I did two tests. First, I did this after blowing away my dev-install directory (--prefix) and in that case, it creates test/.libs/lt-gdatacalendar
. Once I have installed the library, though, it creates test/.libs/gdatacalendar
instead. The output of ldd is the same for both with one exception:
# before install
# ldd test/.libs/lt-gdatacalendar
libgdata.so.0 => /home/altern8/workspaces/4355/libgdata/src/.libs/libgdata.so.0 (0xb7c32000)
# after install
# ldd test/.libs/gdatacalendar
libgdata.so.0 => /home/altern8/workspaces/4355/dev-install/lib/libgdata.so.0 (0xb7c87000)
What would cause this to create lt-gdatacalendar in one case but gdatacalendar in another?
The output of ldd on libgdata is:
altern8@goldfrapp:~/workspaces/4355/libgdata$ ldd /home/altern8/workspaces/4355/libgdata/src/.libs/libgdata.so.0
linux-gate.so.1 => (0xb7f7c000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7f3b000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dec000)
/lib/ld-linux.so.2 (0xb7f7d000)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想我已经解决了这个问题。
问题应该是 libtool 在看到“../src/libgdata.so”部分之前在命令行中看到了“-L”标志。 在这种情况下,它使用该“-L”路径的“-Wl,-rpath,...”执行链接器。 如果该路径包含“libgdata.so”,那么它将始终被使用,这里就是这种情况。
就我而言,我已将“prog_LDADD”重新排列为如下所示:
“prog_LDADD = $(top_builddir)/src/my_lib.so $(DEPENDENCY_LIBS)”
在您的情况下,尝试删除 AM_LDFLAGS 并写入:
LDADD = $(top_builddir)/src/libgdata.la $(APIUTIL_LIBS)
I think I've sorted this out.
The problem should be that libtool sees the "-L" flag in the command line before it sees the "../src/libgdata.so" part. In this case, it executes the linker with "-Wl,-rpath,..." for that "-L" path. If that path contains "libgdata.so", then it will always be used, which is the case here.
In my case, I've rearranged "prog_LDADD" to like like this:
"prog_LDADD = $(top_builddir)/src/my_lib.so $(DEPENDENCY_LIBS)"
In your case, try to delete AM_LDFLAGS and write:
LDADD = $(top_builddir)/src/libgdata.la $(APIUTIL_LIBS)
不确定如何在 autoconf 中执行此操作,但最终命令可能需要 -L../src,以便链接器可以首先找到新构建的库。
尝试手动运行最后一个命令并添加该命令,看看是否有帮助。
编辑:好吧,我想读错了,以为它没有链接,但你是说它链接但不运行?
如果是这种情况,请在您的二进制文件上运行 ldd 并查看它选择了哪个 .so —— 最有可能是已安装(和过时)的。
在这种情况下,要么在运行之前安装更新的库,要么在运行之前导出 LD_LIBRARY_PATH 环境变量。
Not sure how to do that in autoconf, but final command might need to have -L../src, so linker can find newly built library first.
Try manually running last command with that addition and see if that helps.
EDIT: Ok, I guess misread it, thought it wasn't linking, but you are saying it links but doesn't run?
If that is the case, run ldd on your binary and see which .so it picks up -- most likely installed (and outdated) ones.
In this case, either install updated libs before running, or export LD_LIBRARY_PATH env variable before running.
我知道要使依赖项正常工作,您需要使用
LDADD
中的相对路径引用libgdata.la
; 这也可能会影响您所描述的情况。但我不确定为什么。 您所描述的行为确实看起来有点奇怪; 也许值得向 libtool 开发人员报告。
I know that for dependencies to work correctly, you need to refer to
libgdata.la
with a relative path inLDADD
; it's possible that affects the situation you're describing as well.I'm not sure why, though. The behavior you're describing does seem a bit odd; and perhaps worth reporting to the libtool developers.
如果没有 -no-install libtool 会创建脚本包装器并将可执行文件放入 .libs/ 子目录中(与已安装库链接)。 调用包装器会使您的可执行文件加载/链接到本地(未安装)库 - 因此一切正常,例如
make check
不会测试已安装的库,而是测试新烘焙的库。在某些情况下(例如,在调试或 valgrinding 时),您不希望使用这些包装器,而是希望将真正的可执行文件直接与本地库链接。 为此,您可以使用
AM_LDFLAGS = -no-install
(或仅将其设置为单个目标)。更多详细信息此处
Without -no-install libtool creates script wrappers and puts the executables into the .libs/ subdir (linked with the installed libraries). Calling the wrapper makes your executable load/link with your local (not installed) library - so everything works fine, e.g.
make check
does not test the installed but your freshly baken library.In some cases (e.g. when debugging or valgrinding), you do not want to have those wrappers, but real executables directly linked with your local library. For this you use
AM_LDFLAGS = -no-install
(or just set it for single targets).More details here