假设您可以将程序中的所有例程分布在一组源文件中,同时假定这些文件全部包含在子目录 test_lib/ 中。
进一步假定这些文件是以这样一种方式组织的:它们每一个都只包含一个用户程序将会调用的主要子程序,同时还包含该子程序可能会调用的任何“帮助程序”例程,但这些例程不会从库中的任何其他例程中调用。另外,从一个以上库例程中调用的任何帮助程序例程均被集合到单个源文件中。这样就给出了一个组织得非常合理的源文件及目标文件集。
假定每个源文件的名称均取自文件中第一个例程的名称,在多数情况下,该例程是库中的主要文件之一:
demo% cd test_lib demo% ls total 14 2 dropx.f 2 evalx.f 2 markx.f 2 delte.f 2 etc.f 2 linkz.f 2 point.f |
更低级的“帮助程序”例程被集中到文件 etc.f 中。其他文件可以包含一个或多个子程序。
首先,使用 -c 选项编译每一个库源文件,生成相应的可重定位 .o 文件:
demo% f95 -c *.f demo% ls total 42 2 dropx.f 4 etc.o 2 linkz.f 4 markx.o 2 delte.f 4 dropx.o 2 evalx.f 4 linkz.o 2 point.f 4 delte.o 2 etc.f 4 evalx.o 2 markx.f 4 point.o demo% |
现在,使用 ar 创建静态库 testlib.a:
demo% ar cr testlib.a *.o |
要使用该库,可在编译命令中包括此库文件,或者使用 -l 和 -L 编译选项。以下示例直接使用 .a 文件:
demo% cat trylib.f C program to test testlib routines x=21.998 call evalx(x) call point(x) print*, ’value ’,x end demo% f95 -o trylib trylib.f test_lib/testlib.a demo% |
注意,主程序只调用库中的两个例程。您可以验证并未将库中未调用的例程装入可执行文件,方法是查找用 nm 显示的可执行文件的名称列表中是否有这些例程。
demo% nm trylib | grep FUNC | grep point [146] | 70016| 152|FUNC |GLOB |0 |8 |point_ demo% nm trylib | grep FUNC | grep evalx [165] | 69848| 152|FUNC |GLOB |0 |8 |evalx_ demo% nm trylib | grep FUNC | grep delte demo% nm trylib | grep FUNC | grep markx demo% ..etc |
在上述示例中,grep 只在名称列表中查找与实际调用的那些库例程相应的项。
引用库的另一方法是通过 -llibrary 和 -Lpath 选项。这里,必须更改库的名称以符合 libname.a 惯例:
demo% mv test_lib/testlib.a test_lib/libtestlib.a demo% f95 -o trylib trylib.f -Ltest_lib -ltestlib |
-llibrary 和 -Lpath 选项与安装在系统公共访问目录(如 /usr/local/lib)中的库一起使用,以便其他用户可以引用它。例如,假如将 libtestlib.a 置于 /usr/local/lib 中,可以通知其他用户使用以下命令编译:
demo% f95 -o myprog myprog.f -L/usr/local/lib -ltestlib |
如果仅有几个元素需要重新编译,没有必要重新编译整个库。ar 的 -r 选项允许替换静态库中的个别元素。
示例:重新编译并替换静态库中的单个例程:
demo% f95 -c point.f demo% ar -r testlib.a point.o |
要在 ar 正在生成静态库时对其中的元素进行排序,请使用命令 lorder(1) 和 tsort(1):
demo% ar -cr mylib.a ’lorder exg.o fofx.o diffz.o | tsort’ |