Sun Studio 12: Fortran プログラミングガイド

4.4 静的ライブラリの作成

静的ライブラリファイルは、ar(1) ユーティリティーを使用して、すでにコンパイルされたオブジェクトファイル (. o ファイル) から構築します。

リンカーは、リンクするプログラム中で参照される入口を持つ要素をライブラリから抽出します。 たとえば、副プログラム、入口名、BLOCKDATA 副プログラム中で初期化される COMMON ブロックなどです。これらの抽出された要素 (ルーチン) は、リンカーによって生成される a.out 実行可能ファイルに恒久的にリンクされます。

4.4.1 静的ライブラリの長所と短所

静的ライブラリとリンクには、動的なライブラリとリンクと比較した場合、主に 3 つの問題に注意しなければいけません。

例: Fortran プログラムが main.fcrunch.f の 2 つのファイルに記述され、crunch.f だけがライブラリにアクセスする場合、crunch.f または crunch.o より前にライブラリを参照するとエラーになります。


demo% f95 main.f -lmylibrary crunch.f -o myprog

(誤)


demo% f95 main.f crunch.f -lmylibrary -o myprog    

(正)

4.4.2 簡単な静的ライブラリを作成する

1 つのプログラムのルーチンすべてがいくつかのソースファイルのグループに分散されており、また、これらのソースファイルすべてがサブディレクトリ test_lib/ にあるものと仮定します。

さらに、それぞれのファイルがユーザーのプログラムによって呼び出される 1 つの副プログラムと、その副プログラムからは呼び出されるがライブラリ中のほかのルーチンからは呼び出されない「ヘルパー」ルーチンを持つように、ファイルを編成すると仮定します。また、複数のライブラリルーチンから呼び出されるヘルパールーチンはすべて 1 つのソースファイルにまとめられているとします。これによって、合理的に上手に編成されたソースファイルとオブジェクトファイルのセットができます。

各ソースファイルの名前は、そのファイルの中の最初のルーチンの名前から決定すると仮定します。ほとんどの場合、それはライブラリ中の主要なファイルです。


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 にまとめられます。ほかのファイルには、1 つまたは複数の副プログラムが入ります。

まず、-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    testlib ルーチン群をテストするためのプログラム
            x=21.998
            call evalx(x)
            call point(x)
            print*, ’value ’,x
            end
demo% f95 -o trylib trylib.f test_lib/testlib.a
demo%

主プログラムがライブラリ中の 2 つのルーチンだけを呼び出しているところに注目してください。ライブラリ中の呼び出されないルーチンが実行可能ファイルに読み込まれていないことを確認するには、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 は名前のリストから、実際に呼び出されたライブラリルーチンの項目だけを見つけます。

ライブラリを参照するもう 1 つの方法は、-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

4.4.2.1 静的ライブラリ中の置換

2、3 の要素だけをコンパイルし直す場合、ライブラリ全体をコンパイルし直す必要はありません。ar-r オプションを使用すると、静的ライブラリ中の個々の要素を置換できます。

例: 静的ライブラリ中の 1 つのルーチンをコンパイルし直し、置換します。


demo% f95 -c point.f
demo% ar -r testlib.a point.o

4.4.2.2 静的ライブラリ中のルーチンの整列

ar を使用して構築しているときに静的ライブラリ中の要素を整列するには、コマンド lorder(1) と tsort(1) を使用します。


demo% ar -cr mylib.a 'lorder exg.o fofx.o diffz.o | tsort'