In which order does the linker process the library directories? - c++

It is possible that more than one instance of the library exists in the search path during compilation. In what order will linker process directories included in the search path? The platform in question is Sun OS.

The directories are searched in the order in which they are specified on the command line. Directories specified on the command line are searched before the default directories. All -L options apply to all -l options, regardless of the order in which the options appear. LD_LIBRARY_PATH may also be used to supplement the library search path. The directory search stops at the first directory containing the matching library.
LD_LIBRARY_PATH is tricky though:
LD_LIBRARY_PATH
A list of directories in which to search for libraries specified with
the -l option. Multiple directories
are separated by a colon. In the most
general case, it will contain two
directory lists separated by a
semicolon:
dirlist1; dirlist2
If ld is called with any number of occurrences of -L, as in:
ld . . . -Lpath1 . . . -Lpathn . . .
then the search path ordering is:
dirlist1 path1 . . . pathn dirlist2 LIBPATH
When the list of directories does not contain a semicolon, it is
interpreted as dirlist2.
LD_LIBRARY_PATH is also used to specify library search directories to
the runtime linker. That is, if
LD_LIBRARY_PATH exists in the
environment, the runtime linker will
search the directories named in it,
before its default directory, for
shared objects to be linked with the
program at execution.
Please read more about it here.

Related

Why can't cmake locate C++/C++ABI runtime dependencies?

I was trying to write a cmake script to auto install my targets:
set_target_properties(tiflash PROPERTIES INSTALL_RPATH "$ORIGIN/")
install (TARGETS A
COMPONENT A-release
DESTINATION "."
RUNTIME_DEPENDENCY_SETA-dependency)
install (RUNTIME_DEPENDENCY_SET A-dependency
COMPONENT A-release
DESTINATION "."
POST_EXCLUDE_REGEXES "libdl.*" "libc-.*" "libc\\..*" "libgcc_s.*" "librt.*" "libm.*" "ld-.*" "libpthread.*")
In this case, RUNTIME_DEPENDENCY_SET is supposed to include libc++.so.1 and libc++abi.so.1 as I was using LLVM toolchain and I wanted to package the runtime libs with my executables.
CMake did include the expected libs; but it complained that cmake cannot locate libc++.so.1 and libc++abi.so.1. (I suppose this was because libc++.so.1 and libc++abi.so.1 were installed in an unregistered location /usr/local/lib/x86_64-unknown-linux-gnu).
I can walk around this problem by adding sth like DIRECTORIES /usr/local/lib/x86_64-unknown-linux-gnu to the install function. However, warnings will be issued. The document says:
If it is found in such a directory, a warning is issued, because it means that the file is incomplete (it does not list all of the directories that contain its dependencies)
I am curious what does it does not list all of the directories that contain its dependencies mean here? In what list? Rpaths or something else?
I tried to put /usr/local/lib/x86_64-unknown-linux-gnu to BUILD_RPATH of my target. It did not work. (I have checked the generated install script, it calls file(GET_RUNTIME_DEPENDENCIES) on the building target; so I suppose install rpath won't affect the results.)
I also have LD_LIBRARY_PATH and LIBRARY_PATH set in my environment (which contains /usr/local/lib/x86_64-unknown-linux-gnu). And CMAKE_PREFIX_PATH is pointing to /usr/local/.
I just noticed that cmake explained the resolution procedure:
If the depending file does not have any RUNPATH entries, and the library exists in one of the depending file's RPATH entries, or its parents', in that order, the dependency is resolved to that file.
Otherwise, if the depending file has any RUNPATH entries, and the library exists in one of those entries, the dependency is resolved to that file.
Otherwise, if the library exists in one of the directories listed by ldconfig, the dependency is resolved to that file.
Otherwise, if the library exists in one of the DIRECTORIES entries, the dependency is resolved to that file. In this case, a warning is issued, because finding a file in one of the DIRECTORIES means that the depending file is not complete (it does not list all the directories from which it pulls dependencies).
Otherwise, the dependency is unresolved.
So, I set the runtime path, what is the problem then?
It turns out that A depends on an imported lib, let us say, B.
However, B also depends on libc++.so.1 and it does not set the runtime path. I guess cmake do the resolution in a DFS manner and finalize all leaves before roots. So, the error is actually generated for B.
As a solution, I think it would be better if I do ldconfig properly.

Is it possible to get location of dependent libraries from within code

I want to load some dependent libraries from my program with dlopen function. Is it possible to know actual location of these libraries?
eg, ldd shows all dependent libraries with paths in system. How does it work? Is it possible to get paths to correspondent libraries I need to load with dlopen via some call from my C++ code?
From man dlopen one can read:
The function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque "handle" for the dynamic library. If filename is NULL, then the returned handle is for the main program. If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details):
(ELF only) If the executable file for the calling program contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the directories listed in the DT_RPATH tag are searched.
If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated list of directories, then these are searched. (As a security measure this variable is ignored for set-user-ID and set-group-ID programs.)
(ELF only) If the executable file for the calling program contains a DT_RUNPATH tag, then the directories listed in that tag are searched.
The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is checked to see whether it contains an entry for filename.
The directories /lib and /usr/lib are searched (in that order).
So, if the desired library is "installed", a simple dlopen("foobar.so", flag) will do.

convert -l, -L on C++ linker line to full paths

I have in my make file a list of libraries to link into the executable formatted as follows:
LIBRARIES=-L/usr/lib -lmail
and I want to use it to fill out a makefile dependency list so that the executable will re-link any time one of the linked libraries changes.
I expect that I will need to translate the linker line into full paths for each library and then specify them as dependencies like so
$(EXEC_NAME) : /usr/lib/libmail.so
Is there a utility that will translate the search paths and lib names into full paths? or is there a better way to specify the makefile dependencies?

How to change the shared library searching order?

When a program needs a shared library (say libabc.so), it will first check the path of "-labc", and then the environment variable LD_LIBRARY_PATH, then the /etc/ld.so.conf . What should I do if I want the program search the /etc/ld.so.conf first?
Specify it explicitly, in the list of files, before any -l option.
Under Unix (including Linux), the libraries are processed in the order
they are given, one after the other. And whether you specify a library
with the -l option or by specifying the actual path doesn't make a
difference; you can invoke g++ with things like:
g++ file1.o file2.o ... /etc/ld.so.conf ... -labc ...
You could unset the LD_LIBRARY_PATH variable.
unset LD_LIBRARY_PATH
As far as i am concerned the purpose of the LD_LIBRARY_PATH variable is to provide a library which does not exists in your ld.so.conf. Also you have to make sure that a library which you provide by including it in /etc/ld.so.conf is in the cache your /etc/ld.so.cache. you have do execute
ldconfig
as super user to update your /etc/ld.so.cache

Linking libraries (C++)

Using MinGW through Eclipse for C/C++, and attempting to get GLUT (OpenGL Utility Toolkit) working on it, but I suspect it's a simple problem.
Attempts to build result in:
g++ -LC:\Documents and Settings\C\workspace\GLUTtest\Debug -LC:\Tools\MinGW\include\GL -LC:\Tools\MinGW\include -oGLUTtest.exe main.o -lglut32.lib
C:\Tools\MinGW\bin..\lib\gcc\mingw32\3.4.5........\mingw32\bin\ld.exe: cannot find -lglut32.lib
I have glut32.lib in the workspace directory, C:\Documents and Settings\C\workspace\GLUTtest. Here are the options as given by eclipse:
-L"C:\Documents and Settings\C\workspace\GLUTtest" -L"C:\Documents and Settings\C\workspace\GLUTtest\Debug" -L"C:\Documents and Settings\C\workspace\GLUTtest\GL" -L"C:\Tools\MinGW\include\GL" -L"C:\Tools\MinGW\include"
Any idea why it isn't picking up the library?
Seems your trying to pass include directories as link directories. Find the directory that contains glut32.lib and add a link-directory parameter (-L) with the directory you find.
Let's say you have a library file named libxxx.a, libxxx.so or xxx.lib. When linking, you should put the parameter as -lxxx
And second, sometimes you have to put library path with ( -L/path/to/lib/dir )
Your are passing "C:\Tools\MinGW\include\GL -LC:\Tools\MinGW\include" as your linking directory ( -L ) which seems to be your include path. so pass your include directory in include path which will appear with -I option and just check that whether your linking path is present in the list given with -L options, if not then add it in the list otherwise it will say undefined references.