Sun Studio 12:Fortran 编程指南

4.5 创建动态库

动态库文件是由链接程序 ld 自预编译目标模块生成的,这些模块可在执行开始之后绑定到可执行文件。

动态库的另一功能是模块可供系统中其他正在执行的程序使用,而无需在每个程序的内存中复制模块。鉴于此原因,动态库也是一个共享库。

动态库提供下列功能:

4.5.1 权衡动态库

动态库引入了其他一些权衡考虑因素:

各程序间的性能特征随程序的不同会有很大变化。并非总能预先判断或估计动态库与静态库相比性能会提高(还是降低)。但是,如果所需库的这两种形式对您都可用,则分别评估一下程序使用每种库时的性能还是很值得的。

4.5.2 位置无关代码和 –xcode

可以将位置无关代码 (position-independent code, PIC) 绑定到程序中的任何地址,而无需链接编辑器进行重新定位。从固有性质出发,此类代码可以在同时发生的进程间共享。因而,如果要生成动态共享库,必须使用 -xcode 编译器选项将组件例程编译成与位置无关。

在与位置无关的代码中,对全局项的每一引用均会通过全局偏移表中的指针编译为某一引用。每个函数调用均会通过过程链接表以相对编址模式进行编译。在 SPARC 处理器上,全局偏移表的大小限制为 8 K 字节。

编译器标志 -xcode=v 用于指定二进制对象的代码地址空间。使用该标志,不但可以生成 32、44 或 64 位绝对地址,而且可生成与位置无关的、大小不同的模型代码。(-xcode=pic13 等效于传统的 -pic 标志,-xcode=pic32 等效于 -PIC。)

-xcode=pic32 编译器选项与 -xcode=pic13 类似,但前者允许全局偏移表跨 32 位地址范围。有关详细信息,请参见 f95(1) 手册页或《Fortran 用户指南》。

4.5.3 绑定选项

可以在编译时指定动态或静态库绑定。这些选项实际上是链接程序选项,但它们是由编译器识别并传递给链接程序的。

4.5.3.1 –Bdynamic | -Bstatic

–Bdynamic 用于在各种可能的情况下为共享动态绑定设置首选项。-Bstatic 将绑定只限制于静态库。

当库的静态和动态版本都可用时,使用该选项在命令行首选项间进行切换:

f95 prog.f -Bdynamic -lwells -Bstatic -lsurface

4.5.3.2 –dy | -dn

允许或不允许对整个可执行文件进行动态链接。(该选项只能在命令行上出现一次。)

–dy 允许链接动态共享库。-dn 不允许链接动态库。

4.5.3.3 64 位环境中的绑定

某些静态系统库(如 libm.alibc.a)不能在 64 位 Solaris 操作环境中使用。这些库只作为动态库提供。在这些环境中使用 -dn 将会导致错误,指示缺少某些静态系统库。另外,如果编译器命令行以 -Bstatic 结尾,其结果将是一样的。

要与特定库的静态版本进行链接,请使用类似下面的命令行:

f95 -o prog prog.f -Bstatic -labc -lxyz -Bdynamic

在此,链接的是用户的 libabc.alibxyz.a 文件(而不是 libabc.solibxyz.so),最后的 -Bdynamic 确保以动态方式链接包括系统库在内的其余各库。

在更复杂的情况下,可能必须在链接阶段根据需要用相应的 -Bstatic-Bdynamic 显式引用每个系统库和用户库。首先使用设置为 ’-Dfiles’LD_OPTIONS 获取全部所需库的列表。然后用 -nolib 执行链接步骤(禁止自动链接系统库)并显式引用所需的库。例如:

f95 -m64 -o cdf -nolib cdf.o -Bstatic -lsunmath \ -Bdynamic -lm -lc

4.5.4 命名惯例

为符合链接加载程序和编译器假定的动态库命名惯例,请为您使用前缀 lib 和后缀 .so 创建的动态库命名。例如,编译器选项 -lmyfavs 可以引用 libmyfavs.so

链接程序还接受可选的版本号后缀:例如,libmyfavs.so.1 代表库的第版。

编译器的 -hname 选项将 name 记录为正在生成的动态库的名称。

4.5.5 一个简单动态库

生成动态库需要用 -xcode 选项和链接程序选项 -G-ztext-hname 编译源文件。这些链接程序选项可通过编译器命令行来提供。

您可以用静态库示例中使用的相同文件创建一个动态库。

示例:用 -pic 和其他链接程序选项编译:


demo% f95 -o libtestlib.so.1 -G -xcode=pic13 -ztext  \ 
–hlibtestlib.so.1 *.f

–G 告知链接程序生成一个动态库。

–ztext 会在发现与位置无关的代码以外的任何内容(如可重定位文本)时发出警告。

示例:使用动态库生成可执行文件 a.out


demo% f95 -o trylib -R”pwd” trylib.f libtestlib.so.1
demo% file trylib
trylib:ELF 32–bit MSB executable SPARC Version 1, dynamically linked, not stripped
demo% ldd trylib
     libtestlib.so.1 => /export/home/U/Tests/libtestlib.so.1
     libfui.so.1 => /opt/SUNWspro/lib/libfui.so.1
     libfai.so.1 => /opt/SUNWspro/lib/libfai.so.1
     libc.so.1 => /usr/lib/libc.so.1

注意,此示例使用 -R 选项将动态库路径(当前目录)绑定到可执行文件中。

file 命令显示可执行文件是以动态方式链接的。

4.5.6 初始化公共块

生成动态库时,通过将已初始化的公共块集中到同一库中并在其他所有库之前引用该库,可确保正确初始化公共块(用 DATABLOCK DATA 表示的块)。

例如:


demo% f95 -G -xcode=pic32 -o init.so blkdat1.f blkdat2.f blkdat3.f
demo% f95 -o prog main.f init.so otherlib1.so otherlib2.so

首次编译会由定义公共块并在 BLOCK DATA 单元中对其进行初始化的文件创建一个动态库。第二次编译创建可执行二进制文件,将已编译的主程序与应用程序所需的动态库链接起来。注意,初始化所有公共块的动态库在其他所有库之前首先出现。这样将确保正确地初始化这些块。