ライブラリは変化し、元の機能が望ましくなくなることがあります。新しい機能が追加され、古い機能が廃止されたとみなされることはよくあります。下位互換性が重要な場合は、既存のオブジェクトのためにこのような古い機能をライブラリに保持しておく必要があります。ただし、これらの機能を新たに使用することのないように設定できます。このポリシーを実施するには、スタブオブジェクトを使用します。mapfile STUB_ELIMINATE フラグを使用して、実オブジェクトに残しながらスタブオブジェクトから削除する必要のあるオブジェクトの機能やデータにマークを付けます。これによって、スタブオブジェクトにリンクする新しいコードは、これらの廃止された項目を使用できなくなり、推奨のインタフェースを使用するように書き換えられます。実オブジェクトにはまだこれらの項目が含まれているので、既存のオブジェクトはこれらを使用できます。
前のセクションの libidx5 の例には、このことが示されています。このライブラリは、オブジェクトから大域データをエクスポートする方法を示しています。ただし、大域データのエクスポートは動的リンクを複雑にするので、行わないことをお勧めします。通常は、libidx5 によって提供される idx5_func() 関数など、このようなデータにアクセスする関数を用意したほうが適切な設計になります。この例の続きでは、既存のプログラムのために実オブジェクト内で古いインタフェースを提供しながら、スタブにリンクする新しいコードで大域データを使用できないようにするために、STUB_ELIMINATE を使用できます。
mapfile は、STUB_ELIMINATE を 2 つの大域データシンボルに適用するように書き換えられます。STUB_ELIMINATE を大域データに適用した場合、データサイズを指定する ASSERT 指令を用意する必要がなくなるという利点があります。この例では、ASSERT がコメントアウトされています。実際の mapfile では、完全に省略されていることもあります。
$ cat better_mapfile $mapfile_version 2 STUB_OBJECT; SYMBOL_SCOPE { _idx5 { FLAGS=STUB_ELIMINATE; #ASSERT { TYPE=data; SIZE=4[5] }; }; idx5 { FLAGS=STUB_ELIMINATE; #ASSERT { BINDING=weak; ALIAS=_idx5 }; }; idx5_func; local: *; };
新しいバージョンのテストプログラムだけが機能インタフェースを使用します。
$ cat better_main.c #include <stdio.h> extern int idx5_func(int); int main(int argc, char **argv) { int i; for (i = 0; i < 5; i++) (void) printf("[%d] %d\n", i, idx5_func(i)); return (0); }
古いテストプログラムは保存され、スタブオブジェクトは新しい mapfile を使用して再構築され、テストプログラムは再構築され、STUB_ELIMINATE を採用した新しいスタブオブジェクトに対してリンクします。
$ cp a.out original_a.out $ cc -Kpic -G -M better_mapfile -h libidx5.so.1 idx5.c -o stublib/libidx5.so.1 -zstub $ cc better_main.c -o better_a.out -L stublib -R '$ORIGIN/lib' -lidx5 -lc $ ./better_a.out [0] 0 [1] 1 [2] 2 [3] 3 [4] 4
スタブライブラリには必要な大域データシンボルが欠如しているので、元のテストプログラムはもはや構築できません。ただし、まだ実際のライブラリ大域がデータシンボルを提供するので、それらを使用していた事前に存在するバイナリは機能し続けます。
$ cc main.c -L stublib -R '$ORIGIN/lib' -lidx5 -lc Undefined first referenced symbol in file idx5 main.o _idx5 main.o ld: fatal: symbol referencing errors $ ./original_a.out [0] 0 0 0 [1] 1 1 1 [2] 2 2 2 [3] 3 3 3 [4] 4 4 4