Although the compiler drivers often ensure that appropriate libraries are specified to the link-editor, frequently you must supply your own. Shared objects and archives can be specified by explicitly naming the input files required to the link-editor. However, a more common and more flexible method involves using the link-editor's –l option.
By convention, shared objects are usually designated by the prefix lib and the suffix .so. Archives are designated by the prefix lib and the suffix .a. For example, libfoo.so is the shared object version of the “foo” implementation that is made available to the compilation environment. libfoo.a is the library's archive version.
These conventions are recognized by the –l option of the link-editor. This option is commonly used to supply additional libraries to a link-edit. The following example directs the link-editor to search for libfoo.so. If the link-editor does not find libfoo.so, a search for libfoo.a is made before moving on to the next directory to be searched.
$ cc -o prog file1.c file2.c -lfoo
When link-editing in dynamic mode, you can choose to link with a mix of shared objects and archives. When link-editing in static mode, only archive libraries are acceptable for input.
In dynamic mode, when using the –l option, the link-editor first searches the given directory for a shared object that matches the specified name. If no match is found, the link-editor looks for an archive library in the same directory. In static mode, when using the –l option, only archive libraries are sought.
The library search mechanism in dynamic mode searches a given directory for a shared object, and then searches for an archive library. Finer control of the search is possible through the –B option.
By specifying the –B dynamic and –B static options on the command line, you can toggle the library search between shared objects or archives respectively. For example, to link an application with the archive libfoo.a and the shared object libbar.so, issue the following command.
$ cc -o prog main.o file1.c -Bstatic -lfoo -Bdynamic -lbar
The –B static and –B dynamic options are not exactly symmetrical. When you specify –B static, the link-editor does not accept shared objects as input until the next occurrence of –B dynamic. However, when you specify –B dynamic, the link-editor first looks for shared objects and then archive library's in any given directory.
The precise description of the previous example is that the link-editor first searches for libfoo.a. The link-editor then searches for libbar.so, and if that search fails, searches for libbar.a.
The position of an archive on the command line can affect the output file being produced. The link-editor searches an archive only to resolve undefined or tentative external references that have previously been encountered. After this search is completed and any required members have been extracted, the link-editor moves onto the next input file on the command line.
Therefore by default, the archive is not available to resolve any new references from the input files that follow the archive on the command line. For example, the following command directs the link-editor to search libfoo.a only to resolve symbol references that have been obtained from file1.c. The libfoo.a archive is not available to resolve symbol references from file2.c or file3.c.
$ cc -o prog file1.c -Bstatic -lfoo file2.c file3.c -Bdynamic
Interdependencies between archives can exist, such that the extraction of members from one archive must be resolved by extracting members from another archive. If these dependencies are cyclic, the archives must be specified repeatedly on the command line to satisfy previous references.
$ cc -o prog .... -lA -lB -lC -lA -lB -lC -lA
The determination, and maintenance, of repeated archive specifications can be tedious. The –z rescan-now option makes this process simpler. The –z rescan-now option is processed by the link-editor immediately when the option is encountered on the command line. All archives that have been processed from the command line prior to this option are immediately reprocessed. This processing attempts to locate additional archive members that resolve symbol references. This archive rescanning continues until a pass over the archive list occurs in which no new members are extracted. The previous example can be simplified as follows.
$ cc -o prog .... -lA -lB -lC -z rescan-now
Alternatively, the –z rescan-start and –z rescan-end options can be used to group mutually dependent archives together into an archive group. These groups are reprocessed by the link-editor immediately when the closing delimiter is encountered on the command line. Archives found within the group are reprocessed in an attempt to locate additional archive members that resolve symbol references. This archive rescanning continues until a pass over the archive group occurs in which no new members are extracted. Using archive groups, the previous example can be written as follows.
$ cc -o prog .... -z rescan-start -lA -lB -lC -z rescan-end
All previous examples assume the link-editor knows where to search for the libraries listed on the command line. By default, when linking 32–bit objects, the link-editor knows of only two standard directories in which to look for libraries, /lib followed by /usr/lib. When linking 64–bit objects, only two standard directories are used, /lib/64 followed by /usr/lib/64. All other directories to be searched must be added to the link-editor's search path explicitly.
You can change the link-editor search path by using a command line option, or by using an environment variable.
You can use the –L option to add a new path name to the library search path. This option alters the search path at the point the option is encountered on the command line. For example, the following command searches path1, followed by /lib, and finally /usr/lib, to find libfoo. The command searches path1 and then path2, followed by /lib, and /usr/lib, to find libbar.
$ cc -o prog main.o -Lpath1 file1.c -lfoo file2.c -Lpath2 -lbar
Path names that are defined by using the –L option are used only by the link-editor. These path names are not recorded in the output file image being created. Therefore, these path names are not available for use by the runtime linker.
You can use the –Y option to change the default directories searched by the link-editor. The argument supplied with this option takes the form of a colon separated list of directories. For example, the following command searches for libfoo only in the directories /opt/COMPILER/lib and /home/me/lib.
$ cc -o prog main.c -YP,/opt/COMPILER/lib:/home/me/lib -lfoo
You can also use the environment variable LD_LIBRARY_PATH to add to the link-editor's library search path. Typically, LD_LIBRARY_PATH takes a colon-separated list of directories. In its most general form, LD_LIBRARY_PATH can also take two directory lists separated by a semicolon. These lists are searched before and after the –Y lists supplied on the command line.
The following example shows the combined effect of setting LD_LIBRARY_PATH and calling the link-editor with several –L occurrences.
$ LD_LIBRARY_PATH=dir1:dir2;dir3 $ export LD_LIBRARY_PATH $ cc -o prog main.c -Lpath1 .... -Lpath2 .... -Lpathn -lfoo
The effective search path is dir1:dir2:path1:path2:....:pathn:dir3:/lib:/usr/lib.
If no semicolon is specified as part of the LD_LIBRARY_PATH definition, the specified directory list is interpreted after any –L options. In the following example, the effective search path is path1:path2:....:pathn:dir1:dir2:/lib:/usr/lib.
$ LD_LIBRARY_PATH=dir1:dir2 $ export LD_LIBRARY_PATH $ cc -o prog main.c -Lpath1 .... -Lpath2 .... -Lpathn -lfoo
The runtime linker looks in two default locations for dependencies. When processing 32–bit objects, the default locations are /lib and /usr/lib. When processing 64–bit objects, the default locations are /lib/64 and /usr/lib/64. All other directories to be searched must be added to the runtime linker's search path explicitly.
When a dynamic executable or shared object is linked with additional shared objects, the shared objects are recorded as dependencies. These dependencies must be located during process execution by the runtime linker. When linking a dynamic object, one or more search paths can be recorded in the output file. These search paths are referred to as a runpath. The runtime linker uses the runpath of an object to locate the dependencies of that object.
Specialized objects can be built with the –z nodefaultlib option to suppress any search of the default location at runtime. Use of this option implies that all the dependencies of an object can be located using its runpaths. Without this option, no matter how you augment the runtime linker's search path, the last search paths used are always the default locations.
You can use the –R option, which takes a colon-separated list of directories, to record a runpath in a dynamic executable or shared object. The following example records the runpath /home/me/lib:/home/you/lib in the dynamic executable prog.
$ cc -o prog main.c -R/home/me/lib:/home/you/lib -Lpath1 \ -Lpath2 file1.c file2.c -lfoo -lbar
The runtime linker uses these paths, followed by the default location, to obtain any shared object dependencies. In this case, this runpath is used to locate libfoo.so.1 and libbar.so.1.
The link-editor accepts multiple –R options. These multiple specifications are concatenate together, separated by a colon. Thus, the previous example can also be expressed as follows.
$ cc -o prog main.c -R/home/me/lib -Lpath1 -R/home/you/lib \ -Lpath2 file1.c file2.c -lfoo -lbar
For objects that can be installed in various locations, the $ORIGIN dynamic string token provides a flexible means of recording a runpath. See Locating Associated Dependencies.