I cannot easily test my program after build:
$ ./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
is in ./src/nsreclient/x86_64-unknown-linux-gnu/
and a proper -L
flag was used during link
Automake builds my binary with libtool. It creates a wrapper script src/rap/rap
.
My expectation was: while generating the script, libtool would ignore the current value of LD_LIBRARY_PATH
. When running the script, it would append the needed directories in the build tree to existing value of LD_LIBRARY_PATH
. e.g, executing:
LD_LIBRARY_PATH=/foo ./src/rap/rap
would result:
LD_LIBRARY_PATH=/foo:/home/il/workspace/rap/src/nsreclient/x86_64-unknown-linux-gnu ./src/rap/.libs/lt-rap
But libtool does the opposite: it hardcodes the current value of LD_LIBRARY_PATH
into the generated script:
LD_LIBRARY_PATH=/opt/oracle/product/11.2.0/client_64/lib:/lib:/usr/lib:/usr/local/lib; export LD_LIBRARY_PATH;
It makes no sense. Why doesn't it add there the build tree directories?
Here's pretty formated output of make command:
/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
The wrapper script does not set LD_LIBRARY_PATH
at all. It assumes that subdirs containing the needed libraries were added to RPATH
of the real binary.
When -lfoo
flag passed to libtool
, it first tries to open the corresponding file libfoo.la
. If that file does not exist, libtool
falls back to passing the flag to gcc
unchanged.
If the .la
file exists and points to a shared library, libtool
tells the linker to add the directory containing the library to RPATH
of output binary.
Many packages install their .la
files to /usr/lib/
. That means newer libtool
will be able parse files created by previous versions. It must be totally safe to manually write .la
files for precompiled .so
files instead of generating them every time.
I created the file ./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'
After rebuild, my wrapper script no longer complains.