链接程序和库指南

记录共享库名称

缺省情况下,动态可执行文件或共享库中的依赖项记录将是链接编辑器所引用的关联共享库的文件名。例如,根据同一共享库 libfoo.so 生成的以下动态可执行文件会导致对同一依赖项具有不同的解释。


$ cc -o ../tmp/libfoo.so -G foo.o

$ cc -o prog main.o -L../tmp -lfoo

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   libfoo.so



$ cc -o prog main.o ../tmp/libfoo.so

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   ../tmp/libfoo.so



$ cc -o prog main.o /usr/tmp/libfoo.so

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   /usr/tmp/libfoo.so

如这些示例所示,这种记录依赖项机制会因编译技术的不同而出现不一致性。此外,在链接编辑过程中引用的共享库的位置也可能会与已安装系统上的共享库的最终位置有所不同。为了提供更一致的指定依赖项的方法,共享库可以在自身中记录运行时引用共享库应依据的文件名。

在链接编辑共享库过程中,可以使用 -h 选项在共享库自身中记录其运行时名称。在以下示例中,将在文件自身中记录共享库的运行时名称 libfoo.so.1。此标识称为 soname


$ cc -o ../tmp/libfoo.so -G -K pic -h libfoo.so.1 foo.c

以下示例说明如何使用 dump(1) 并引用具有 SONAME 标记的项来显示 soname 记录。


$ dump -Lvp ../tmp/libfoo.so



../tmp/libfoo.so:

[INDEX] Tag      Value

[1]     SONAME   libfoo.so.1

.........

当链接编辑器处理包含 soname 的共享库时,此名称便是作为要生成的输出文件中的依赖项记录的名称。

如果在上一示例的创建动态可执行文件 prog 的过程中使用此新版本的 libfoo.so,则所有三种创建可执行文件的方法都会记录同一依赖项。


$ cc -o prog main.o -L../tmp -lfoo

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   libfoo.so.1



$ cc -o prog main.o ../tmp/libfoo.so

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   libfoo.so.1



$ cc -o prog main.o /usr/tmp/libfoo.so

$ dump -Lv prog | grep NEEDED

[1]     NEEDED   libfoo.so.1

在上述示例中,使用 -h 选项来指定不包含 "/" 的简单文件名。借助此约定,运行时链接程序可以使用一组规则来查找实际文件。 有关更多详细信息,请参见查找共享库依赖项

在归档文件中包含共享库

如果共享库始终通过归档库进行处理,则在共享库中记录 soname 是基本机制。

归档文件可以根据一个或多个共享库生成,并可用于生成动态可执行文件或共享库。可以从归档文件中提取共享库来满足链接编辑的要求。与处理可重定位的目标文件(串联成要创建的输出文件)不同,从归档文件中提取的任何共享库都将记录为依赖项。有关归档文件提取条件的更多详细信息,请参见归档处理

归档成员的名称由链接编辑器构造,并且由归档文件名称和归档文件中的目标文件串联而成。 例如:


$ cc -o libfoo.so.1 -G -K pic foo.c

$ ar -r libfoo.a libfoo.so.1

$ cc -o main main.o libfoo.a

$ dump -Lv main | grep NEEDED

[1]     NEEDED   libfoo.a(libfoo.so.1)

由于具有此串联名称的文件无法在运行时存在,因此,在共享库中提供 soname 是生成依赖项有意义运行时文件名的唯一方法。


注 –

运行时链接程序不会从归档文件中提取目标文件。因此,在上一示例中,必须从归档文件中提取所需的共享库依赖项并使其可用于运行时环境。


已记录名称冲突

使用共享库创建动态可执行文件或其他共享库时,链接编辑器会执行多项一致性检查。这些检查可确保输出文件中记录的任何依赖项名称都是唯一的。

如果用作链接编辑的输入文件的两个共享库包含相同的 soname,则会出现依赖项名称冲突。 例如:


$ cc -o libfoo.so -G -K pic -h libsame.so.1 foo.c

$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c

$ cc -o prog main.o -L. -lfoo -lbar

ld: fatal: recording name conflict: file `./libfoo.so' and \

    file `./libbar.so' provide identical dependency names: libsame.so.1

ld: fatal: File processing errors. No output written to prog

如果某个没有已记录 soname 的共享库的文件名与同一链接编辑过程使用的其他共享库的 soname 匹配,则也会出现类似的错误情况。

如果要生成的共享库的运行时名称与它的某个依赖项匹配,则链接编辑器也会报告名称冲突。


$ cc -o libbar.so -G -K pic -h libsame.so.1 bar.c -L. -lfoo

ld: fatal: recording name conflict: file `./libfoo.so' and \

    -h option provide identical dependency names: libsame.so.1

ld: fatal: File processing errors. No output written to libbar.so