内置库目录未添加到 libtool 包装器脚本中的 LD_LIBRARY_PATH
built library dirs not added to LD_LIBRARY_PATH in libtool wrapper script
构建后我无法轻松测试我的程序:
$ ./src/rap/rap -h
/home/il/workspace/rap/src/rap/.libs/lt-rap: error while loading shared libraries: libpmclient.so: cannot open shared object file: No such file or directory
libpmclient.so
在 ./src/nsreclient/x86_64-unknown-linux-gnu/
中,并且在 link
期间使用了正确的 -L
标志
Automake 使用 libtool 构建我的二进制文件。它创建一个包装脚本 src/rap/rap
.
我的预期是:在生成脚本时,libtool 会忽略 LD_LIBRARY_PATH
的当前值。当 运行 脚本时,它将 附加 构建树中所需的目录到 LD_LIBRARY_PATH
的现有值。例如,执行:
LD_LIBRARY_PATH=/foo ./src/rap/rap
结果:
LD_LIBRARY_PATH=/foo:/home/il/workspace/rap/src/nsreclient/x86_64-unknown-linux-gnu ./src/rap/.libs/lt-rap
但 libtool 的作用恰恰相反:它将 LD_LIBRARY_PATH
的当前值硬编码到生成的脚本中:
LD_LIBRARY_PATH=/opt/oracle/product/11.2.0/client_64/lib:/lib:/usr/lib:/usr/local/lib; export LD_LIBRARY_PATH;
没有意义。为什么它不在那里添加构建树目录?
这里是 make 命令的格式化输出:
/bin/sh ../../libtool --tag=CC --mode=link gcc -Werror-implicit-function-declaration -O2 \
-pthread -o rap rap.o \
librap.a \
../liclib/liblic.a \
../fget-1.3.3/lib/libfget.a \
../lib_mt/libppb.la \
../sgplib/libsgp.la \
../../variations/asn1lib/ebuf_lib_mt/libasn1cebuf.la \
-L../../src/nsreclient/x86_64-unknown-linux-gnu -lpmclient \
-L/opt/oracle/product/11.2.0/client_64/lib -lclntsh \
-L/usr/lib -lexpat \
-lssl \
-lcrypto \
-lm
libtool: link: gcc -Werror-implicit-function-declaration -O2 -pthread -o .libs/rap rap.o librap.a ../liclib/liblic.a ../fget-1.3.3/lib/libfget.a \
../lib_mt/.libs/libppb.so \
../sgplib/.libs/libsgp.so \
../../variations/asn1lib/ebuf_lib_mt/.libs/libasn1cebuf.so \
-L../../src/nsreclient/x86_64-unknown-linux-gnu -lpmclient \
-L/opt/oracle/product/11.2.0/client_64/lib -lclntsh \
-L/usr/lib /usr/lib/libexpat.so \
-lssl -lcrypto -lm -pthread -Wl,-rpath -Wl,/usr/local/lib
存在对 libtool
的误解,它的包装脚本为您做了什么。
特别是它将不解析传递给库路径链接器的所有标志(-L
)并将它们添加到某个LD_LIBRARY_PATH
变量中。
libtool 包装器脚本的目的是 (cf the docs) 满足 运行 卸载的应用程序 和
[any] uninstalled libtool library.
现在 libtool libraries
是那些奇怪的 .la
文件(而不是带有 .so
后缀的实际动态库)。
由于您的 libpmclient.so
不是这样的野兽,因此包装脚本在这里对您帮助不大。
解决方案?
如果您无法安装您的第 3 方库到运行时链接器可以找到它们的地方,我建议将所需的路径添加到您的 LD_LIBRARY_PATH
和每当你进行黑客攻击时获取该配置文件(你 可以 也可以在你的 ~/.bashrc
中执行此操作,但如果你将你的帐户用于其他目的,它可能会在以后妨碍你比在单个项目上编码更重要)
包装脚本根本没有设置 LD_LIBRARY_PATH
。它假定包含所需库的子目录已添加到真实二进制文件的 RPATH
。
当-lfoo
标志传递给libtool
时,它首先尝试打开相应的文件libfoo.la
。如果该文件不存在,libtool
退回到将标志传递给 gcc
不变。
如果 .la
文件存在并指向共享库,libtool
告诉链接器将包含该库的目录添加到输出二进制文件的 RPATH
。
许多软件包将它们的 .la
文件安装到 /usr/lib/
。这意味着较新的 libtool
将能够解析以前版本创建的文件。为预编译的 .so
文件手动编写 .la
文件而不是每次都生成它们一定是完全安全的。
我创建了文件 ./src/nsreclient/x86_64-unknown-linux-gnu/libpmclient.la
:
# libpmclient.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpmclient.so'
# Names of this library.
library_names='libpmclient.so'
# The name of the static archive.
old_library='libpmclient.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpmclient.
current=0
age=0
revision=0
# Is this an already installed library?
installed=no
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/usr/local/lib'
重建后,我的包装器脚本不再报错。
构建后我无法轻松测试我的程序:
$ ./src/rap/rap -h
/home/il/workspace/rap/src/rap/.libs/lt-rap: error while loading shared libraries: libpmclient.so: cannot open shared object file: No such file or directory
libpmclient.so
在 ./src/nsreclient/x86_64-unknown-linux-gnu/
中,并且在 link
-L
标志
Automake 使用 libtool 构建我的二进制文件。它创建一个包装脚本 src/rap/rap
.
我的预期是:在生成脚本时,libtool 会忽略 LD_LIBRARY_PATH
的当前值。当 运行 脚本时,它将 附加 构建树中所需的目录到 LD_LIBRARY_PATH
的现有值。例如,执行:
LD_LIBRARY_PATH=/foo ./src/rap/rap
结果:
LD_LIBRARY_PATH=/foo:/home/il/workspace/rap/src/nsreclient/x86_64-unknown-linux-gnu ./src/rap/.libs/lt-rap
但 libtool 的作用恰恰相反:它将 LD_LIBRARY_PATH
的当前值硬编码到生成的脚本中:
LD_LIBRARY_PATH=/opt/oracle/product/11.2.0/client_64/lib:/lib:/usr/lib:/usr/local/lib; export LD_LIBRARY_PATH;
没有意义。为什么它不在那里添加构建树目录?
这里是 make 命令的格式化输出:
/bin/sh ../../libtool --tag=CC --mode=link gcc -Werror-implicit-function-declaration -O2 \
-pthread -o rap rap.o \
librap.a \
../liclib/liblic.a \
../fget-1.3.3/lib/libfget.a \
../lib_mt/libppb.la \
../sgplib/libsgp.la \
../../variations/asn1lib/ebuf_lib_mt/libasn1cebuf.la \
-L../../src/nsreclient/x86_64-unknown-linux-gnu -lpmclient \
-L/opt/oracle/product/11.2.0/client_64/lib -lclntsh \
-L/usr/lib -lexpat \
-lssl \
-lcrypto \
-lm
libtool: link: gcc -Werror-implicit-function-declaration -O2 -pthread -o .libs/rap rap.o librap.a ../liclib/liblic.a ../fget-1.3.3/lib/libfget.a \
../lib_mt/.libs/libppb.so \
../sgplib/.libs/libsgp.so \
../../variations/asn1lib/ebuf_lib_mt/.libs/libasn1cebuf.so \
-L../../src/nsreclient/x86_64-unknown-linux-gnu -lpmclient \
-L/opt/oracle/product/11.2.0/client_64/lib -lclntsh \
-L/usr/lib /usr/lib/libexpat.so \
-lssl -lcrypto -lm -pthread -Wl,-rpath -Wl,/usr/local/lib
存在对 libtool
的误解,它的包装脚本为您做了什么。
特别是它将不解析传递给库路径链接器的所有标志(-L
)并将它们添加到某个LD_LIBRARY_PATH
变量中。
libtool 包装器脚本的目的是 (cf the docs) 满足 运行 卸载的应用程序 和
[any] uninstalled libtool library.
现在 libtool libraries
是那些奇怪的 .la
文件(而不是带有 .so
后缀的实际动态库)。
由于您的 libpmclient.so
不是这样的野兽,因此包装脚本在这里对您帮助不大。
解决方案?
如果您无法安装您的第 3 方库到运行时链接器可以找到它们的地方,我建议将所需的路径添加到您的 LD_LIBRARY_PATH
和每当你进行黑客攻击时获取该配置文件(你 可以 也可以在你的 ~/.bashrc
中执行此操作,但如果你将你的帐户用于其他目的,它可能会在以后妨碍你比在单个项目上编码更重要)
包装脚本根本没有设置 LD_LIBRARY_PATH
。它假定包含所需库的子目录已添加到真实二进制文件的 RPATH
。
当-lfoo
标志传递给libtool
时,它首先尝试打开相应的文件libfoo.la
。如果该文件不存在,libtool
退回到将标志传递给 gcc
不变。
如果 .la
文件存在并指向共享库,libtool
告诉链接器将包含该库的目录添加到输出二进制文件的 RPATH
。
许多软件包将它们的 .la
文件安装到 /usr/lib/
。这意味着较新的 libtool
将能够解析以前版本创建的文件。为预编译的 .so
文件手动编写 .la
文件而不是每次都生成它们一定是完全安全的。
我创建了文件 ./src/nsreclient/x86_64-unknown-linux-gnu/libpmclient.la
:
# libpmclient.la - a libtool library file
# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06)
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpmclient.so'
# Names of this library.
library_names='libpmclient.so'
# The name of the static archive.
old_library='libpmclient.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpmclient.
current=0
age=0
revision=0
# Is this an already installed library?
installed=no
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/usr/local/lib'
重建后,我的包装器脚本不再报错。