Apologize because for the moment I don't have the environment to experiment and sort out the following questions myself:
1) Let's say I have four library files: libmylib_super.a and libmylib_super.so, mylib_dumb.a and mylib_dumb.so. While specifying libraries to link to, what are the differences between the following approaches:
A) -l:libmylib_super.a
B) -llibmylib_super
C) -lmylib_super
D) -lmylib_dumb
2) Definition of -static from man page:
On systems that support dynamic
linking, this prevents linking with
the shared libraries. On other
systems, this option has no effect.
Does this linker option have anything to do with question #1? Or... by any chance will they interfere with each other?
Thanks.
--- edited 2009-12-28 ---
I just got my environment up and experimenting a bit, by linking to Boost date_time library. Say I have three library files: libboost_date_time-mt-d.a, libboost_date_time-mt-d.so.1.41.0, libboost_date_time-mt-d.so -> libboost_date_time-mt-d.so.1.41.0 (sym link).
A.1) -l:libboost_date_time-mt-d.a ==> linking OK, binary works even without the library file.
A.2) -l:libboost_date_time-mt-d.a with -static ==> linking error /usr/bin/ld: cannot find -lm
C.1) -lboost_date_time-mt-d ==> linking OK, binary works but requires the shared library file.
C.2) -lboost_date_time-mt-d with -static ==> linking error /usr/bin/ld: cannot find -lm
Any idea about the error in A.2 and C.2?
Additionally, while running the program in C.1, it seems searching the shared library file with name libboost_date_time-mt-d.so.1.41.0 but not the libboost_date_time-mt-d.so. Wouldn't that be inconvenient if the program is running on a system without the exact version of library? What could be the practical way to handle the version while using shared library?
According to the manual,
A) searches the library path for a file exactly named libmylib_super.a (the search first for a shared library behavior doesn't apply)
B) searches the library path for a file named liblibmylib_super.so first then liblibmylib_super.a or only searches for a file named liblibmylib_super.a if -static is used -- note it's the linker that adds the lib prefix and the file extension
C) searches the library path for a file named libmylib_super.so first then libmylib_super.a or only searches for a file named liblibmylib_super.so if -static is used
D) see C)
Note that B) won't work because it's the linker that should add the lib prefix to the library name.
Note that D) won't work because your mylib_dumb doesn't follow the naming convention.
See the GNU Linker Manual:
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of files to link. This option may be used any number of times. If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it will search the library path for a file called libnamespec.a.
On systems which support shared libraries, ld may also search for files other than libnamespec.a. Specifically, on ELF and SunOS systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a. (By convention, a .so extension indicates a shared library.) Note that this behavior does not apply to :filename, which always specifies a file called filename.
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
See the -( option for a way to force the linker to search archives multiple times.
You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX, note that it is different from the behaviour of the AIX linker.
Related
I am having difficulty understanding the order in which directories are searched for linking to libraries. I have a CentOS6 system and 3 versions of gcc, 4.4.7, 4.7.2, 4.9.2. The system version is 4.4.7 and version 4.7.2 and 4.9.2 are modules. In /etc/ld.so.conf.d/ there two files, gcc-4.7.2.conf and gcc-4.9.2.conf which contain the paths to the 4.7.2 and 4.9.2 libraries.
I created a simple C++ program, main.cpp
#include <cstdio>
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello You!" << endl;
printf("Back at you!\n");
return 0;
}
compiling it with g++-4.4.7 and running ldd a.out, I see
linux-vdso.so.1 => (0x00007fff5535b000)
libstdc++.so.6 => /nonstandardpath/gcc-4.7.2/lib64/libstdc++.so.6 (0x00002ac12de73000)
libm.so.6 => /lib64/libm.so.6 (0x00002ac12e17a000)
libgcc_s.so.1 => /nonstandardpath/gcc-4.7.2/lib64/libgcc_s.so.1 (0x00002ac12e3ff000)
libc.so.6 => /lib64/libc.so.6 (0x00002ac12e614000)
/lib64/ld-linux-x86-64.so.2 (0x00002ac12dc51000)
Looking at man ld, it states (under -rpath-link=dir) :
The linker uses the following search paths to locate required shared
libraries:
Any directories specified by -rpath-link options.
Any directories specified by -rpath options. The difference between -rpath and
-rpath-link is that directories specified by -rpath options are included in the
executable and used at runtime, whereas the -rpath-link option is only effective at
link time. Searching -rpath in this way is only supported by native linkers and
cross linkers which have been configured with the --with-sysroot option.
On an ELF system, for native linkers, if the -rpath and -rpath-link options were not
used, search the contents of the environment variable "LD_RUN_PATH".
On SunOS, if the -rpath option was not used, search any directories specified using
-L options.
For a native linker, the search the contents of the environment variable
"LD_LIBRARY_PATH".
For a native ELF linker, the directories in "DT_RUNPATH" or "DT_RPATH" of a shared
library are searched for shared libraries needed by it. The "DT_RPATH" entries are
ignored if "DT_RUNPATH" entries exist.
The default directories, normally /lib and /usr/lib.
For a native linker on an ELF system, if the file /etc/ld.so.conf exists, the list
of directories found in that file.
If the required shared library is not found, the linker will issue a warning and
continue with the link.
It does not state the order in which the directories are searched. From my example above, it appears that /etc/ld.so.conf.d is searched before /usr/lib or /lib
QUESTION : what is the order in which linker searches for libraries (e.g. LD_LIBRARY_PATH, ld.so.conf.d, -rpath, -L)?
The online man page states the order for ld:
When resolving shared object dependencies, the dynamic linker first
inspects each dependency string to see if it contains a slash (this
can occur if a shared object pathname containing slashes was
specified at link time).
If a slash is found, then the dependency
string is interpreted as a (relative or absolute) pathname, and the
shared object is loaded using that pathname.
If a shared object dependency does not contain a slash, then it is searched for in the following order:
Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
Using the environment variable LD_LIBRARY_PATH (unless the executable is being run in secure-execution mode; see below). in which case it is ignored.
Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present. Such directories are searched only to find those objects required by DT_NEEDED (direct dependencies) entries and do not apply to those objects' children, which must themselves have their own DT_RUNPATH entries. This is unlike DT_RPATH, which is applied to searches for all children in the dependency tree.
From the cache file /etc/ld.so.cache, which contains a compiled list of candidate shared objects previously found in the augmented library path. If, however, the binary was linked with the -z nodeflib linker option, shared objects in the default paths are skipped. Shared objects installed in hardware capability directories (see below) are preferred to other shared objects.
In the default path /lib, and then /usr/lib. (On some 64-bit architectures, the default paths for 64-bit shared objects are /lib64, and then /usr/lib64.) If the binary was linked with the -z nodeflib linker option, this step is skipped.
Taken from the 2017-09-15 version. I assume older versions of ld are similar.
Should it make a difference whether a gcc linker links archive files or object files (or both)?
Background:
In an embedded project, an ISR (which is of course not referenced by any other source code) is located as the only function in a file. This file is compiled to an object file and then put into an archive file.
Other functions in other files are compiled to separate object files.
The binary is built without complaints and runs on the target with no exceptions, no matter whether the linker uses the ISR object file or the ISR archive file.
However, if using the archive file, the ISR is not linked.
Plus, if there is any other reference (e.g. a variable used by some other function in some other file) in the same file, it is linked completely.
Why this?
Yes, it makes a difference.
Any object file that is specified on the linker commandline is linked
into the executable, regardless of whether any of the symbols that it
defines are referenced by the executable.
The linkage of a static library is different. It is an archive of object
files. For each object file in the archive, the linker will determine
whether that object file provides a definition for any of the symbols
that are so far undefined at that point in the linkage. If it does so,
then the linker will extract that object file from the archive and
link it in the executable; otherwise not.
This behaviour is as documented for the ld, the GNU linker {- l | --library }
option:
-l namespec
--library=namespec
...
The linker will search an archive only once, at the location where
it is specified on the command line. If the archive defines a symbol
which was undefined in some object which appeared before the archive
on the command line, the linker will include the appropriate file(s)
from the archive. However, an undefined symbol in an object appearing
later on the command line will not cause the linker to search the
archive again.
...
(To see that this applies to linkages invoked with gcc or another GNU compiler,you may need to know that the named compiler is simply a tool-driver that delegates to the appropriate tool for discharging the commandline options that are presented: when it sees options that call for a linkage, it calls ld.)
Hence the object file containing the unreferenced ISR is not linked when
it is in a library, and contains no other referenced symbols, and it is
linked when it is not in a library, or when it contains some other
referenced symbol.
I have added libxxx.a in /usr/lib but when I perform otool -L myproject.so, libxxx.a was not included in the list of libraries. I have also included libxxx.a in my build file so I was thinking that I have successfully added it.
How can I like .a file?
I didn't have a problem with .dylib files though.
otool won't show the static library as they are included within the executable binary (a .dylib in this case). This is because static libraries are a collection of object (.o) files and it's pretty much the same as adding file1.o ... fileN.o to the linker command line and you can't see object files from otool either.
One way to check that your static library is part of the executable (other than it successfully linking) is to use the nm command which lists symbols. Providing the executable binary is not stripped, you would do something like:
$ nm /path/to/libLibrary.dylib | grep aClassOrFunctionInStaticLibrary
and the symbol being searched should have the letter t next to it, to indicate that it's part of the executable text section.
Also as mentioned by #PaulR, /usr/lib is part of the operating system and you should not add files there; use /usr/local/lib instead as /usr/local is designed for site-specific additions to the system and files there will survive an operating system update.
I am a regular C programmer, and there's something I have wondered for some time about GNU GCC/LD internals.
I have noticed that, when passing a sequence of object files to GCC (e.g gcc main.o otherfile.o), GCC automatically links libc.a library file without my explicitly specifying -lc in the options. Similarly, when I compile a program using ncurses, I just need to specify -lncurses and libtinfo.a gets linked automatically (no need to specify -ltinfo). In other words, even though ncurses functions use functions from libtinfo (for instance, unctrl()), I don't need to explicitly link libtinfo.
How can it be possible?
Does GCC/LD have a list of "default libraries" where it looks for missing symbols when linking? If such a table exists, where is it and how can it be configured?
A direct answer is that you can see what libraries are linked by command line options by adding -v to the linking command line. This will show you the commands as they are executed.
The C library and the GCC support library or libraries are linked automatically; other libraries have to be specified manually.
The case of -lncurses and libtinfo.a (libtinfo.so?) is rather different. There, the link command used to build libncurses.so tells the linker that this library also needs -ltinfo, so it automatically picks up the extra library.
Using gcc and gnu ld, I am compiling a binary (a shared object in this case) that depends on a library, let's say libfoo. libfoo comes as both .a and .so files, in the same directory.
Can I know which is being used, the static or the dynamic?
GNU ld on my Linux (Ubuntu 12.10 box) will load the .so file first.
From man ld:
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of
files to link. This option may be used any number of times. If
namespec is of the form :filename, ld will search the library path
for a file called filename, otherwise it will search the library
path for a file called libnamespec.a.
On systems which support shared libraries, ld may also search for
files other than libnamespec.a. Specifically, on ELF and SunOS
systems, ld will search a directory for a library called
libnamespec.so before searching for one called libnamespec.a. (By
convention, a ".so" extension indicates a shared library.) Note
that this behavior does not apply to :filename, which always
specifies a file called filename.
gcc (and ld, which it's really running behind the scenes) default to dynamic linking if it's available. You can check the output binary to see which it did, if you want.
If you want to force it to use the static library, you can use the -static link option.