dlopen - cannot open shared object file - gcc

I'm compiling a shared library with gcc and loading it using dlopen. I also pass the following to the compiler:
-fvisibility=hidden
When I compile the library WITHOUT the visibility flag, everything works perfectly. However, when I compile WITH the flag, I get the following error with dlopen:
libtest.so: cannot open shared object file: No such file or directory
The linbrary .so file exists! This seems weird to me, since if some symbols are hidden, I would expect dlsym to fail if something cannot be found. However, this already fails when loading the library (aka dlopen).
I also tried adding
__attribute__ ((visibility ("default")))
to the functions I later call (extern "C"), without any success. Does anyone know what I can do about this? Or alternatively, is there any way to debug this to figure out why dlopen fails? I do not want to remove the visibility flag, since his drastically reduces my executable size.

My lib was depended on another lib that could not be found.
You may use ldd to see the list of all dependencies, including missing.
ldd libtest.so

Related

Can gcc build an executable without access to a required shared library?

When building an executable, gcc requires the -l flag to list the shared libraries, even though they can be changed freely without recompiling the executable. Does gcc use that flag only to check if all the symbols are ok? Can I build the executable without performing this verification?
You can use dlopen to load the dynamic library at runtime, and dlsym to get the pointer to the function you like to call.
Here is a sample http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html

Libtool link shared lib against a static lib given by an explicit path (no -l option)

I want to pull all symbols from a static library (libyaml-cpp) into a shared one that I'm building (libLHAPDF), to avoid an explicit dependency for users of the latter. (It's not my favourite way to do things, but the difficulty of installing the prerequisite was a regular negative feedback about the package.) So I try to build the relevant bit of my shared library with an automake rule like this:
libLHAPDFInfo_la_LDFLAGS = $(AM_LDFLAGS) \
$(srcdir)/yamlcpp/yaml-cpp/libyaml-cpp.a
I specifically want something like this rather than
libLHAPDFInfo_la_LDFLAGS = -L$(srcdir)/yamlcpp/yaml-cpp -lyaml-cpp \
$(AM_LDFLAGS)
because there could be a shared lib version of libyaml-cpp installed elsewhere on the system, and I don't want to use it. (The odd flag ordering in that latter case is an attempt to make sure that -lyaml-cpp finds the one built in the srcdir... and yes it really is srcdir and not builddir in this case!)
However, the first version gives a warning that I'd rather not have:
*** Warning: Linking the shared library libLHAPDFInfo.la against the
*** static library ./yamlcpp/yaml-cpp/libyaml-cpp.a is not portable!
and more importantly it doesn't actually work: if I run nm on the generated library I see undefined symbols:
$ nm src/.libs/libLHAPDFInfo.a | grep YAML
U _ZN11LHAPDF_YAML4NodeC1Ev
U _ZN11LHAPDF_YAML4NodeD1Ev
...
(Details: libLHAPDFInfo.a is a noinst_LTLIBRARIES entry used as an intermediate to building the final shared lib. So this doesn't even work when linking one static lib against another. And to avoid symbol clashes, the bundled version is slightly hacked to rename the YAML namespace to LHAPDF_YAML: that doesn't change anything, but I thought I'd mention it just in case those symbol names seem strange to you.)
If I use the second form of the link flags (the -lyaml-cpp way), I get all the LHAPDF_YAML symbols in libLHAPDFInfo.a and thereafter into the shared library. And there is no longer any warning about non-portability of the static library linking (which was built with -fPIC, so it is valid to do this). But if a shared libyaml-cpp is also found on the system, it gets used regardless of the -L/-l flag ordering -- which I don't want.
Any suggestions of how I can make sure that the version of the library at a particular path will be used, while getting the symbols correctly copied across and avoiding libtool warnings?
EDIT: Having said that I could get symbols copied from libyaml-cpp.a into libLHAPDFInfo.a via the -lyaml-cpp flag, after more iterations I could no longer get this approach to show the expected symbols via nm. Looking at the ar/ranlib commands executed by libtool when making libLHAPDFInfo.a, the -l arguments seem to get completely dropped. So I don't know how it ever worked... as far as I can tell it's just not a mode that libtool supports, not that that is documented. In the end I renamed libyaml-cpp to liblhapdf-yaml-cpp.a as part of the build (since no lib with that name should be found accidentally), and linked that into the final shared libLHAPDF.so rather than the static convenience lib. Not as neat as I'd have liked -- I was hoping to isolate all the yaml-cpp dependency handling into the build of one convenience lib, and relying on file copies to disambiguate library lookup is unsatisfying -- but it works.

Cygwin-to-Linux cross-compiling gcc fails because it can not find a shared library, but it does not tell me which

I have obtained and installed a Cygwin-to-Linux cross-compiler from the Cygwin Ports Project and am trying to use it to compile a simple "Hello world"-program. Then this happens:
$i686-pc-linux-gnu-gcc main.c
/usr/bin/i686-pc-linux-gnu-g++.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
Obviously, GCC can't find some DLL. Unforntunately, it does not print which and I do not know how I can find out.
This even happens when I try something as simple as running the preprocessor (through i686-pc-linux-gnu-gcc -E) over a C file that does nothing but return 0.
This GCC is version 4.7.2.
Does someone know how I can fix this? Or at least how I could find out the name of the library which can not be found?

Building a Shared Library but linking against a Static One

I have an Autogen Makefile.am that I'm trying to use to build a test program for a shared library. To build my test binary, I want to continue building the shared library as target but I want the test program to be linked statically. I've spent the last few hours trying to craft my Makefile.am to get it to do this.
I've tried explicitly changing the LDADD line to use the .a version of the library and get a file not found error even though I can see this library is getting built.
I try to add the .libs directory to my link path via LDFLAGS and still it can't find it.
I tried moving my library sources to my test SOURCES list and this won't work because executable object files are built differently than those for static libraries.
I even tried replicating a lib_LIBRARIES entry for the .a version (so there's both a lib_LTLIBRARIES and a lib_LIBRARIES) and replicate all the LDFLAGS, SOURCES, dir and HEADERS for the shared version as part of the static version (replacing la with a of the form _a_SOURCES = _la_SOURCES. Still that doesn't work because now it can't figure out what to build.
My configure.ac file is using the default LT_INIT which should give me both static and dynamic libraries and as I said it is apprently building both even if the libtool can't see the .a file.
Please, anyone know how to do this?
As #Brett Hale mentions in his comment, you should tell Makefile.am that you want the program to be statically linked.
To achieve this you must append -static to your LDFLAGS.
Changing the LDFLAGS for a specific binary is achieved by changing binary_LDFLAGS (where binary is the name of the binary you want to build).
so something like this should do the trick:
binary_LDFLAGS = $(AM_LDFLAGS) -static

How to specify non-default shared-library path in GCC Linux? Getting "error while loading shared libraries" when running

There is a laptop on which I have no root privilege.
onto the machine I have a library installed using configure --prefix=$HOME/.usr .
after that, I got these files in ~/.usr/lib :
libXX.so.16.0.0
libXX.so.16
libXX.so
libXX.la
libXX.a
when I compile a program that invokes one of function provided by the library with this command :
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX
xxx.out was generated without warning, but when I run it error like this was thrown:
./xxx.out: error while loading shared libraries: libXX.so.16: cannot open shared object file: No such file or directory , though libXX.so.16 resides there.
my clue-less assumption is that ~/.usr/lib wasn't searched when xxx.out is invoked.
but what can I do to specify path of .so , in order that xxx.out can look there for .so file?
An addition is when I feed -static to gcc, another error happens like this:
undefined reference to `function_proviced_by_the_very_librar'
It seems .so does not matter even though -L and -l are given to gcc.
what should I do to build a usable exe with that library?
For other people who has the same question as I did
I found a useful article at tldp about this.
It introduces static/shared/dynamic loaded library, as well as some example code to use them.
There are two ways to achieve that:
Use -rpath linker option:
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX -Wl,-rpath=/home/user/.usr/lib
Use LD_LIBRARY_PATH environment variable - put this line in your ~/.bashrc file:
export LD_LIBRARY_PATH=/home/user/.usr/lib
This will work even for a pre-generated binaries, so you can for example download some packages from the debian.org, unpack the binaries and shared libraries into your home directory, and launch them without recompiling.
For a quick test, you can also do (in bash at least):
LD_LIBRARY_PATH=/home/user/.usr/lib ./xxx.out
which has the advantage of not changing your library path for everything else.
Should it be LIBRARY_PATH instead of LD_LIBRARY_PATH.
gcc checks for LIBRARY_PATH which can be seen with -v option

Resources