链接程序和库指南

与其他库链接

虽然编译器驱动程序通常确保对链接编辑器指定适当的库,但您经常必须提供自己的库。通过显式指定链接编辑器需要的输入文件可以指定共享库和归档。但是,更常见且更灵活的方法涉及使用链接编辑器的 -l 选项。

库命名约定

根据约定,通常指定共享库具有前缀 lib 和后缀 .so。指定归档具有前缀 lib 和后缀 .a。例如,libc.so 是可用于编译环境的标准 C 库的共享版本。libc.a 是库的归档版本。

这些约定可由链接编辑器的 -l 选项识别。此选项通常用于为链接编辑提供其他库。以下示例指示链接编辑器搜索 libfoo.so。如果链接编辑器未找到 libfoo.so,则在继续搜索下一个目录之前将搜索 libfoo.a


$ cc -o prog file1.c file2.c -lfoo

注 –

在编译环境和运行时环境中使用的共享库都遵循相应的命名约定。编译环境使用简单 .so 后缀,而运行时环境通常使用带有附加版本号的后缀。 请参见命名约定协调版本化文件名


当链接编辑处于动态模式时,可以选择同时链接共享库和归档。当链接编辑处于静态模式时,仅接受归档库作为输入。

在动态模式下使用 -l 选项时,链接编辑器首先搜索给定目录以查找与指定名称匹配的共享库。如果未找到任何匹配项,则链接编辑器将在相同目录中查找归档库。在静态模式下使用 -l 选项时,将仅查找归档库。

同时链接共享库和归档

动态模式下的库搜索机制搜索给定目录以查找共享库,然后搜索归档库。使用 -B 选项可以更精确地控制搜索。

通过在命令行中指定 -B dynamic-B static 选项,可以分别在共享库或归档之间切换库搜索。例如,要将应用程序与归档 libfoo.a 和共享库 libbar.so 链接,可发布以下命令:


$ cc -o prog main.o file1.c -Bstatic -lfoo -Bdynamic -lbar

-B static-B dynamic 关键字并不完全对称。指定 -B static 时,链接编辑器要等到下一次出现 -B dynamic 时才接受共享库作为输入。但是,指定 -B dynamic 时,链接编辑器首先在任何给定的目录中查找共享库,然后查找归档库。

对上一个示例的准确说明如下:链接编辑器首先搜索 libfoo.a,然后搜索 libbar.so ,如果此搜索失败,则搜索 libbar.a。最后,链接编辑器搜索 libc.so,如果此搜索失败,则搜索 libc.a

命令行中归档的位置

命令行中归档的位置可以影响要生成的输出文件。链接编辑器搜索归档只是为了解析先前遇到的未定义或暂定外部引用。完成此搜索并提取所有需要的成员后,链接编辑器将继续处理命令行中的下一个输入文件。

因此,缺省情况下,不能使用归档解析命令行中归档后面的输入文件中的任何新引用。例如,以下命令指示链接编辑器搜索 libfoo.a,仅仅是为了解析从 file1.c 中获取的符号引用。不能使用 libfoo.a 归档解析 file2.cfile3.c 中的符号引用。


$ cc -o prog file1.c -Bstatic -lfoo file2.c file3.c -Bdynamic

注 –

应该在命令行末尾指定任何归档,除非多重定义冲突要求采取其他方式。


归档之间可以存在相互的依赖性,这样,要从一个归档中提取成员,还必须从另一个归档中提取相应成员。如果这些依赖性构成循环,则必须在命令行中重复指定归档以满足前面的引用。 例如:


$ cc -o prog .... -lA -lB -lC -lA -lB -lC -lA

确定和维护重复指定的归档是一个繁琐的任务。使用 -z rescan 选项可以简化此过程。处理完所有输入文件后,此选项将导致重新处理整个归档列表。此处理过程尝试查到解析符号引用的其他归档成员。继续重新扫描此归档,直到扫描归档列表一遍但未提取任何新成员为止。因此,上一个示例可以简化为:


$ cc -o prog -z rescan .... -lA -lB -lC

链接编辑器搜索的目录

上面所有示例都假定链接编辑器了解在哪里搜索命令行中列出的库。缺省情况下,在链接 32 位目标文件时,链接编辑器只知道在三个标准目录中查找库:先搜索 /usr/ccs/lib,然后搜索 /lib,最后搜索 /usr/lib。在链接 64 位目标文件时,只使用两个标准目录:先搜索 /lib/64,然后搜索 /usr/lib/64。必须显式地将要搜索的所有其他目录添加到链接编辑器的搜索路径中。

可以使用命令行选项或环境变量来更改链接编辑器的搜索路径。

使用命令行选项

可以使用 -L 选项将新的路径名添加到库搜索路径中。在命令行中遇到此选项时,将改变搜索路径。例如,以下命令搜索 path1,然后搜索 /usr/ccs/lib/lib,最后搜索 /usr/lib 来查找 libfoo。此命令搜索 path1,然后搜索 path2,接着搜索 /usr/ccs/lib/lib/usr/lib 来查找 libbar


$ cc -o prog main.o -Lpath1 file1.c -lfoo file2.c -Lpath2 -lbar

使用 -L 选项定义的路径名仅由链接编辑器使用。这些路径名不会记录在要创建的输出文件映像中。因此,运行时链接程序不能使用这些路径名。


注 –

如果要链接编辑器在当前目录中搜索库,则必须指定 -L。可以使用句点 (.) 来表示当前目录。


可以使用 -Y 选项更改链接编辑器搜索的缺省目录。随此选项提供的参数采用以冒号分隔的目录列表形式。例如,以下命令仅在目录 /opt/COMPILER/lib/home/me/lib 中搜索 libfoo


$ cc -o prog main.c -YP,/opt/COMPILER/lib:/home/me/lib -lfoo

可以使用 -L 选项补充使用 -Y 选项指定的目录。

使用环境变量

还可以使用环境变量 LD_LIBRARY_PATH(采用冒号分隔的目录列表形式)将要搜索的目录添加到链接编辑器的库搜索路径中。LD_LIBRARY_PATH 最常见的形式是以分号分隔的两个目录列表。系统按照命令行中提供的列表依次进行搜索。

以下示例说明在设置 LD_LIBRARY_PATH 且调用链接编辑器时使用多个 -L 的情况下所得结果:


$ LD_LIBRARY_PATH=dir1:dir2;dir3

$ export LD_LIBRARY_PATH

$ cc -o prog main.c -Lpath1 ... -Lpath2 ... -Lpathn -lfoo

有效搜索路径为 dir1:dir2:path1:path2... pathn:dir3:/usr/ccs/lib:/lib:/usr/lib

如果在 LD_LIBRARY_PATH 定义中未指定分号,则将在解释所有 -L 选项之后解释指定的目录列表。在以下示例中,有效搜索路径为 path1:path2... pathn:dir1:dir2:/usr/ccs/lib:/lib:/usr/lib


$ LD_LIBRARY_PATH=dir1:dir2

$ export LD_LIBRARY_PATH

$ cc -o prog main.c -Lpath1 ... -Lpath2 ... -Lpathn -lfoo

注 –

还可以使用此环境变量扩充运行时链接程序的搜索路径。 请参见运行时链接程序搜索的目录。为了防止此环境变量影响链接编辑器,请使用 -i 选项。


运行时链接程序搜索的目录

运行时链接程序在两个缺省位置中查找依赖项。在处理 32 位目标文件时,缺省位置为 /lib/usr/lib。在处理 64 位目标文件时,缺省位置为 /lib/64/usr/lib/64。必须显式地将要搜索的所有其他目录添加到运行时链接程序的搜索路径中。

当动态可执行文件或共享库与其他共享库链接时,这些共享库将作为依赖性进行记录。运行时链接程序执行进程期间必须找到这些依赖性。链接动态库时,可以在输出文件中记录一个或多个搜索路径。这些搜索路径称为运行路径。运行时链接程序使用目标文件的运行路径来查找该目标文件的依赖性。

可以使用 -z nodefaultlib 选项生成专用目标文件,以便在运行时不搜索任何缺省位置。该选项的用法表示使用目标文件的运行路径可以查找该目标文件的所有依赖性。如果不使用此选项,则无论如何扩充运行时链接程序的搜索路径,该搜索路径中的最后一个元素始终是缺省位置。


注 –

可以使用运行时配置文件管理缺省搜索路径。 请参见配置缺省搜索路径。但是,目标文件的创建者不应依赖于此文件的存在。应始终确保目标文件仅使用其运行路径或缺省位置即可找到它的依赖性。


可以使用 -R 选项(采用冒号分隔的目录列表形式)将运行路径记录在动态可执行文件或共享库中。以下示例将运行路径 /home/me/lib:/home/you/lib 记录在动态可执行文件 prog 中。


$ cc -o prog main.c -R/home/me/lib:/home/you/lib -Lpath1 \

-Lpath2 file1.c file2.c -lfoo -lbar

运行时链接程序使用这些路径(后接缺省位置)来获取任何共享库的依赖性。在本示例中,此运行路径用于查找 libfoo.so.1libbar.so.1

链接编辑器接受多个 -R 选项。指定的多个选项串联在一起,用冒号分隔。因此,上一个示例还可以按如下所示表示。


$ cc -o prog main.c -R/home/me/lib -Lpath1 -R/home/you/lib \

-Lpath2 file1.c file2.c -lfoo -lbar

对于可以安装在各种位置的目标文件,$ORIGIN 动态字符串标记提供了一种记录运行路径的灵活方法。 请参见查找关联的依赖项


注 –

以前指定 -R 选项的替代方法是设置环境变量 LD_RUN_PATH,并使链接编辑器可以使用此环境变量。LD_RUN_PATH-R 的作用域和功能完全相同,但如果同时指定了这两者,则 -R 会取代 LD_RUN_PATH